blob: 61be54d7b726d919f63898ccfcf91724a720da34 [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
Bram Moolenaarefd88552020-06-18 20:50:10 +020026// values for ctx_skip
27typedef enum {
28 SKIP_NOT, // condition is a constant, produce code
29 SKIP_YES, // condition is a constant, do NOT produce code
Bram Moolenaar280b0dc2020-06-20 13:29:03 +020030 SKIP_UNKNOWN // condition is not a constant, produce code
Bram Moolenaarefd88552020-06-18 20:50:10 +020031} skip_T;
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033/*
34 * Chain of jump instructions where the end label needs to be set.
35 */
36typedef struct endlabel_S endlabel_T;
37struct endlabel_S {
38 endlabel_T *el_next; // chain end_label locations
39 int el_end_label; // instruction idx where to set end
40};
41
42/*
43 * info specific for the scope of :if / elseif / else
44 */
45typedef struct {
Bram Moolenaarefd88552020-06-18 20:50:10 +020046 int is_seen_else;
47 int is_had_return; // every block ends in :return
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010048 int is_if_label; // instruction idx at IF or ELSEIF
49 endlabel_T *is_end_label; // instructions to set end label
50} ifscope_T;
51
52/*
53 * info specific for the scope of :while
54 */
55typedef struct {
56 int ws_top_label; // instruction idx at WHILE
57 endlabel_T *ws_end_label; // instructions to set end
58} whilescope_T;
59
60/*
61 * info specific for the scope of :for
62 */
63typedef struct {
64 int fs_top_label; // instruction idx at FOR
65 endlabel_T *fs_end_label; // break instructions
66} forscope_T;
67
68/*
69 * info specific for the scope of :try
70 */
71typedef struct {
72 int ts_try_label; // instruction idx at TRY
73 endlabel_T *ts_end_label; // jump to :finally or :endtry
74 int ts_catch_label; // instruction idx of last CATCH
75 int ts_caught_all; // "catch" without argument encountered
76} tryscope_T;
77
78typedef enum {
79 NO_SCOPE,
80 IF_SCOPE,
81 WHILE_SCOPE,
82 FOR_SCOPE,
83 TRY_SCOPE,
84 BLOCK_SCOPE
85} scopetype_T;
86
87/*
88 * Info for one scope, pointed to by "ctx_scope".
89 */
90typedef struct scope_S scope_T;
91struct scope_S {
92 scope_T *se_outer; // scope containing this one
93 scopetype_T se_type;
94 int se_local_count; // ctx_locals.ga_len before scope
Bram Moolenaarefd88552020-06-18 20:50:10 +020095 skip_T se_skip_save; // ctx_skip before the block
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010096 union {
97 ifscope_T se_if;
98 whilescope_T se_while;
99 forscope_T se_for;
100 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +0100101 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100102};
103
104/*
105 * Entry for "ctx_locals". Used for arguments and local variables.
106 */
107typedef struct {
108 char_u *lv_name;
109 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200110 int lv_idx; // index of the variable on the stack
111 int lv_from_outer; // when TRUE using ctx_outer scope
112 int lv_const; // when TRUE cannot be assigned to
113 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100114} lvar_T;
115
116/*
117 * Context for compiling lines of Vim script.
118 * Stores info about the local variables and condition stack.
119 */
120struct cctx_S {
121 ufunc_T *ctx_ufunc; // current function
122 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200123 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100124 garray_T ctx_instr; // generated instructions
125
126 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200127 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100128
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200129 int ctx_closure_count; // number of closures created in the
130 // function
131
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100132 garray_T ctx_imports; // imported items
133
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200134 skip_T ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135 scope_T *ctx_scope; // current scope, NULL at toplevel
Bram Moolenaarefd88552020-06-18 20:50:10 +0200136 int ctx_had_return; // last seen statement was "return"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100137
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200138 cctx_T *ctx_outer; // outer scope for lambda or nested
139 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200140 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200141
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100142 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200143 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100144};
145
146static char e_var_notfound[] = N_("E1001: variable not found: %s");
147static char e_syntax_at[] = N_("E1002: Syntax error at %s");
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +0200148static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
Bram Moolenaar47a519a2020-06-14 23:05:10 +0200149static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +0200150static char e_namespace[] = N_("E1075: Namespace not supported: %s");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100151
Bram Moolenaar20431c92020-03-20 18:39:46 +0100152static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200153static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100154
155/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200156 * Lookup variable "name" in the local scope and return it.
157 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100158 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200159 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100160lookup_local(char_u *name, size_t len, cctx_T *cctx)
161{
162 int idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200163 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100164
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100165 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200166 return NULL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200167
168 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100169 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
170 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200171 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100172 if (STRNCMP(name, lvar->lv_name, len) == 0
173 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200174 {
175 lvar->lv_from_outer = FALSE;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200176 return lvar;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200177 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100178 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200179
180 // Find local in outer function scope.
181 if (cctx->ctx_outer != NULL)
182 {
183 lvar = lookup_local(name, len, cctx->ctx_outer);
184 if (lvar != NULL)
185 {
186 // TODO: are there situations we should not mark the outer scope as
187 // used?
188 cctx->ctx_outer_used = TRUE;
189 lvar->lv_from_outer = TRUE;
190 return lvar;
191 }
192 }
193
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200194 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100195}
196
197/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200198 * Lookup an argument in the current function and an enclosing function.
199 * Returns the argument index in "idxp"
200 * Returns the argument type in "type"
201 * Sets "gen_load_outer" to TRUE if found in outer scope.
202 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100203 */
204 static int
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200205lookup_arg(
206 char_u *name,
207 size_t len,
208 int *idxp,
209 type_T **type,
210 int *gen_load_outer,
211 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100212{
213 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200214 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100215
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100216 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200217 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100218 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
219 {
220 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
221
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200222 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
223 {
224 if (idxp != NULL)
225 {
226 // Arguments are located above the frame pointer. One further
227 // if there is a vararg argument
228 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
229 + STACK_FRAME_SIZE)
230 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
231
232 if (cctx->ctx_ufunc->uf_arg_types != NULL)
233 *type = cctx->ctx_ufunc->uf_arg_types[idx];
234 else
235 *type = &t_any;
236 }
237 return OK;
238 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100239 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100240
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200241 va_name = cctx->ctx_ufunc->uf_va_name;
242 if (va_name != NULL
243 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
244 {
245 if (idxp != NULL)
246 {
247 // varargs is always the last argument
248 *idxp = -STACK_FRAME_SIZE - 1;
249 *type = cctx->ctx_ufunc->uf_va_type;
250 }
251 return OK;
252 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100253
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200254 if (cctx->ctx_outer != NULL)
255 {
256 // Lookup the name for an argument of the outer function.
257 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
258 == OK)
259 {
260 *gen_load_outer = TRUE;
261 return OK;
262 }
263 }
264
265 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100266}
267
268/*
269 * Lookup a variable in the current script.
270 * Returns OK or FAIL.
271 */
272 static int
273lookup_script(char_u *name, size_t len)
274{
275 int cc;
276 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
277 dictitem_T *di;
278
279 cc = name[len];
280 name[len] = NUL;
281 di = find_var_in_ht(ht, 0, name, TRUE);
282 name[len] = cc;
283 return di == NULL ? FAIL: OK;
284}
285
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100286/*
287 * Check if "p[len]" is already defined, either in script "import_sid" or in
288 * compilation context "cctx".
289 * Return FAIL and give an error if it defined.
290 */
291 int
Bram Moolenaarcbb6bdc2020-07-06 21:53:17 +0200292check_defined(char_u *p, size_t len, cctx_T *cctx)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100293{
294 if (lookup_script(p, len) == OK
295 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200296 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaareef21022020-08-01 22:16:43 +0200297 || lookup_arg(p, len, NULL, NULL, NULL, cctx) == OK))
298 || find_imported(p, len, cctx) != NULL)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100299 {
Bram Moolenaareef21022020-08-01 22:16:43 +0200300 semsg(_(e_already_defined), p);
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100301 return FAIL;
302 }
303 return OK;
304}
305
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200306/*
307 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
308 * be freed later.
309 */
310 static type_T *
311alloc_type(garray_T *type_gap)
312{
313 type_T *type;
314
315 if (ga_grow(type_gap, 1) == FAIL)
316 return NULL;
317 type = ALLOC_CLEAR_ONE(type_T);
318 if (type != NULL)
319 {
320 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
321 ++type_gap->ga_len;
322 }
323 return type;
324}
325
Bram Moolenaar6110e792020-07-08 19:35:21 +0200326 void
327clear_type_list(garray_T *gap)
328{
329 while (gap->ga_len > 0)
330 vim_free(((type_T **)gap->ga_data)[--gap->ga_len]);
331 ga_clear(gap);
332}
333
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100334 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200335get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100336{
337 type_T *type;
338
339 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200340 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100341 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200342 if (member_type->tt_type == VAR_VOID
343 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100344 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100345 if (member_type->tt_type == VAR_BOOL)
346 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100347 if (member_type->tt_type == VAR_NUMBER)
348 return &t_list_number;
349 if (member_type->tt_type == VAR_STRING)
350 return &t_list_string;
351
352 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200353 type = alloc_type(type_gap);
354 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100355 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100356 type->tt_type = VAR_LIST;
357 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200358 type->tt_argcount = 0;
359 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100360 return type;
361}
362
363 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200364get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100365{
366 type_T *type;
367
368 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200369 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100370 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200371 if (member_type->tt_type == VAR_VOID
372 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100373 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100374 if (member_type->tt_type == VAR_BOOL)
375 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100376 if (member_type->tt_type == VAR_NUMBER)
377 return &t_dict_number;
378 if (member_type->tt_type == VAR_STRING)
379 return &t_dict_string;
380
381 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200382 type = alloc_type(type_gap);
383 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100384 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100385 type->tt_type = VAR_DICT;
386 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200387 type->tt_argcount = 0;
388 type->tt_args = NULL;
389 return type;
390}
391
392/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200393 * Allocate a new type for a function.
394 */
395 static type_T *
396alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
397{
398 type_T *type = alloc_type(type_gap);
399
400 if (type == NULL)
401 return &t_any;
402 type->tt_type = VAR_FUNC;
403 type->tt_member = ret_type;
404 type->tt_argcount = argcount;
405 type->tt_args = NULL;
406 return type;
407}
408
409/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200410 * Get a function type, based on the return type "ret_type".
411 * If "argcount" is -1 or 0 a predefined type can be used.
412 * If "argcount" > 0 always create a new type, so that arguments can be added.
413 */
414 static type_T *
415get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
416{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200417 // recognize commonly used types
418 if (argcount <= 0)
419 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200420 if (ret_type == &t_unknown)
421 {
422 // (argcount == 0) is not possible
423 return &t_func_unknown;
424 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200425 if (ret_type == &t_void)
426 {
427 if (argcount == 0)
428 return &t_func_0_void;
429 else
430 return &t_func_void;
431 }
432 if (ret_type == &t_any)
433 {
434 if (argcount == 0)
435 return &t_func_0_any;
436 else
437 return &t_func_any;
438 }
439 if (ret_type == &t_number)
440 {
441 if (argcount == 0)
442 return &t_func_0_number;
443 else
444 return &t_func_number;
445 }
446 if (ret_type == &t_string)
447 {
448 if (argcount == 0)
449 return &t_func_0_string;
450 else
451 return &t_func_string;
452 }
453 }
454
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200455 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100456}
457
Bram Moolenaara8c17702020-04-01 21:17:24 +0200458/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200459 * For a function type, reserve space for "argcount" argument types (including
460 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200461 */
462 static int
463func_type_add_arg_types(
464 type_T *functype,
465 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200466 garray_T *type_gap)
467{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200468 // To make it easy to free the space needed for the argument types, add the
469 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200470 if (ga_grow(type_gap, 1) == FAIL)
471 return FAIL;
472 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
473 if (functype->tt_args == NULL)
474 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200475 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
476 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200477 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200478 return OK;
479}
480
481/*
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200482 * Get a type_T for a typval_T.
483 * "type_list" is used to temporarily create types in.
Bram Moolenaara8c17702020-04-01 21:17:24 +0200484 */
Bram Moolenaar34db91f2020-06-13 19:00:10 +0200485 type_T *
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200486typval2type(typval_T *tv, garray_T *type_gap)
Bram Moolenaara8c17702020-04-01 21:17:24 +0200487{
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200488 type_T *actual;
489 type_T *member_type;
490
Bram Moolenaara8c17702020-04-01 21:17:24 +0200491 if (tv->v_type == VAR_NUMBER)
492 return &t_number;
493 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200494 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200495 if (tv->v_type == VAR_STRING)
496 return &t_string;
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200497
498 if (tv->v_type == VAR_LIST
499 && tv->vval.v_list != NULL
500 && tv->vval.v_list->lv_first != NULL)
501 {
502 // Use the type of the first member, it is the most specific.
503 member_type = typval2type(&tv->vval.v_list->lv_first->li_tv, type_gap);
504 return get_list_type(member_type, type_gap);
505 }
506
507 if (tv->v_type == VAR_DICT
508 && tv->vval.v_dict != NULL
509 && tv->vval.v_dict->dv_hashtab.ht_used > 0)
510 {
511 dict_iterator_T iter;
512 typval_T *value;
513
514 // Use the type of the first value, it is the most specific.
515 dict_iterate_start(tv, &iter);
516 dict_iterate_next(&iter, &value);
517 member_type = typval2type(value, type_gap);
518 return get_dict_type(member_type, type_gap);
519 }
520
521 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
522 {
523 char_u *name = NULL;
524 ufunc_T *ufunc = NULL;
525
526 if (tv->v_type == VAR_PARTIAL)
527 {
528 if (tv->vval.v_partial->pt_func != NULL)
529 ufunc = tv->vval.v_partial->pt_func;
530 else
531 name = tv->vval.v_partial->pt_name;
532 }
533 else
534 name = tv->vval.v_string;
535 if (name != NULL)
536 // TODO: how about a builtin function?
537 ufunc = find_func(name, FALSE, NULL);
Bram Moolenaar4fc224c2020-07-26 17:56:25 +0200538 if (ufunc != NULL)
539 {
540 // May need to get the argument types from default values by
541 // compiling the function.
542 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
543 && compile_def_function(ufunc, TRUE, NULL) == FAIL)
544 return NULL;
545 if (ufunc->uf_func_type != NULL)
546 return ufunc->uf_func_type;
547 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200548 }
549
550 actual = alloc_type(type_gap);
551 if (actual == NULL)
552 return NULL;
553 actual->tt_type = tv->v_type;
554 actual->tt_member = &t_any;
555
556 return actual;
557}
558
559/*
560 * Get a type_T for a typval_T, used for v: variables.
561 * "type_list" is used to temporarily create types in.
562 */
563 type_T *
564typval2type_vimvar(typval_T *tv, garray_T *type_gap)
565{
Bram Moolenaara8c17702020-04-01 21:17:24 +0200566 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
567 return &t_list_string;
568 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
569 return &t_dict_any;
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200570 return typval2type(tv, type_gap);
571}
572
573
574/*
575 * Return FAIL if "expected" and "actual" don't match.
576 */
577 int
578check_typval_type(type_T *expected, typval_T *actual_tv)
579{
580 garray_T type_list;
581 type_T *actual_type;
582 int res = FAIL;
583
584 ga_init2(&type_list, sizeof(type_T *), 10);
585 actual_type = typval2type(actual_tv, &type_list);
586 if (actual_type != NULL)
587 res = check_type(expected, actual_type, TRUE);
588 clear_type_list(&type_list);
589 return res;
Bram Moolenaara8c17702020-04-01 21:17:24 +0200590}
591
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200592 static void
593type_mismatch(type_T *expected, type_T *actual)
594{
595 char *tofree1, *tofree2;
596
597 semsg(_("E1013: type mismatch, expected %s but got %s"),
598 type_name(expected, &tofree1), type_name(actual, &tofree2));
599 vim_free(tofree1);
600 vim_free(tofree2);
601}
602
603 static void
604arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
605{
606 char *tofree1, *tofree2;
607
608 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
609 argidx,
610 type_name(expected, &tofree1), type_name(actual, &tofree2));
611 vim_free(tofree1);
612 vim_free(tofree2);
613}
614
615/*
616 * Check if the expected and actual types match.
617 * Does not allow for assigning "any" to a specific type.
618 */
Bram Moolenaar34db91f2020-06-13 19:00:10 +0200619 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200620check_type(type_T *expected, type_T *actual, int give_msg)
621{
622 int ret = OK;
623
624 // When expected is "unknown" we accept any actual type.
625 // When expected is "any" we accept any actual type except "void".
626 if (expected->tt_type != VAR_UNKNOWN
627 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
628
629 {
630 if (expected->tt_type != actual->tt_type)
631 {
632 if (give_msg)
633 type_mismatch(expected, actual);
634 return FAIL;
635 }
636 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
637 {
638 // "unknown" is used for an empty list or dict
639 if (actual->tt_member != &t_unknown)
640 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
641 }
642 else if (expected->tt_type == VAR_FUNC)
643 {
644 if (expected->tt_member != &t_unknown)
645 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
646 if (ret == OK && expected->tt_argcount != -1
647 && (actual->tt_argcount < expected->tt_min_argcount
648 || actual->tt_argcount > expected->tt_argcount))
649 ret = FAIL;
Bram Moolenaarb8070e32020-07-23 20:56:04 +0200650 if (expected->tt_args != NULL && actual->tt_args != NULL)
651 {
652 int i;
653
654 for (i = 0; i < expected->tt_argcount; ++i)
655 if (check_type(expected->tt_args[i], actual->tt_args[i],
656 FALSE) == FAIL)
657 {
658 ret = FAIL;
659 break;
660 }
661 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200662 }
663 if (ret == FAIL && give_msg)
664 type_mismatch(expected, actual);
665 }
666 return ret;
667}
668
Bram Moolenaar65b95452020-07-19 14:03:09 +0200669
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100670/////////////////////////////////////////////////////////////////////
671// Following generate_ functions expect the caller to call ga_grow().
672
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200673#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return NULL
674#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return OK
Bram Moolenaar080457c2020-03-03 21:53:32 +0100675
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100676/*
677 * Generate an instruction without arguments.
678 * Returns a pointer to the new instruction, NULL if failed.
679 */
680 static isn_T *
681generate_instr(cctx_T *cctx, isntype_T isn_type)
682{
683 garray_T *instr = &cctx->ctx_instr;
684 isn_T *isn;
685
Bram Moolenaar080457c2020-03-03 21:53:32 +0100686 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100687 if (ga_grow(instr, 1) == FAIL)
688 return NULL;
689 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
690 isn->isn_type = isn_type;
691 isn->isn_lnum = cctx->ctx_lnum + 1;
692 ++instr->ga_len;
693
694 return isn;
695}
696
697/*
698 * Generate an instruction without arguments.
699 * "drop" will be removed from the stack.
700 * Returns a pointer to the new instruction, NULL if failed.
701 */
702 static isn_T *
703generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
704{
705 garray_T *stack = &cctx->ctx_type_stack;
706
Bram Moolenaar080457c2020-03-03 21:53:32 +0100707 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100708 stack->ga_len -= drop;
709 return generate_instr(cctx, isn_type);
710}
711
712/*
713 * Generate instruction "isn_type" and put "type" on the type stack.
714 */
715 static isn_T *
716generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
717{
718 isn_T *isn;
719 garray_T *stack = &cctx->ctx_type_stack;
720
721 if ((isn = generate_instr(cctx, isn_type)) == NULL)
722 return NULL;
723
724 if (ga_grow(stack, 1) == FAIL)
725 return NULL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +0200726 ((type_T **)stack->ga_data)[stack->ga_len] = type == NULL ? &t_any : type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100727 ++stack->ga_len;
728
729 return isn;
730}
731
732/*
733 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
734 */
735 static int
736may_generate_2STRING(int offset, cctx_T *cctx)
737{
738 isn_T *isn;
739 garray_T *stack = &cctx->ctx_type_stack;
740 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
741
742 if ((*type)->tt_type == VAR_STRING)
743 return OK;
744 *type = &t_string;
745
746 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
747 return FAIL;
748 isn->isn_arg.number = offset;
749
750 return OK;
751}
752
753 static int
754check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
755{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200756 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100757 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200758 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100759 {
760 if (*op == '+')
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200761 emsg(_("E1051: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100762 else
763 semsg(_("E1036: %c requires number or float arguments"), *op);
764 return FAIL;
765 }
766 return OK;
767}
768
769/*
770 * Generate an instruction with two arguments. The instruction depends on the
771 * type of the arguments.
772 */
773 static int
774generate_two_op(cctx_T *cctx, char_u *op)
775{
776 garray_T *stack = &cctx->ctx_type_stack;
777 type_T *type1;
778 type_T *type2;
779 vartype_T vartype;
780 isn_T *isn;
781
Bram Moolenaar080457c2020-03-03 21:53:32 +0100782 RETURN_OK_IF_SKIP(cctx);
783
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100784 // Get the known type of the two items on the stack. If they are matching
785 // use a type-specific instruction. Otherwise fall back to runtime type
786 // checking.
787 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
788 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200789 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100790 if (type1->tt_type == type2->tt_type
791 && (type1->tt_type == VAR_NUMBER
792 || type1->tt_type == VAR_LIST
793#ifdef FEAT_FLOAT
794 || type1->tt_type == VAR_FLOAT
795#endif
796 || type1->tt_type == VAR_BLOB))
797 vartype = type1->tt_type;
798
799 switch (*op)
800 {
801 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200802 && type1->tt_type != VAR_ANY
803 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100804 && check_number_or_float(
805 type1->tt_type, type2->tt_type, op) == FAIL)
806 return FAIL;
807 isn = generate_instr_drop(cctx,
808 vartype == VAR_NUMBER ? ISN_OPNR
809 : vartype == VAR_LIST ? ISN_ADDLIST
810 : vartype == VAR_BLOB ? ISN_ADDBLOB
811#ifdef FEAT_FLOAT
812 : vartype == VAR_FLOAT ? ISN_OPFLOAT
813#endif
814 : ISN_OPANY, 1);
815 if (isn != NULL)
816 isn->isn_arg.op.op_type = EXPR_ADD;
817 break;
818
819 case '-':
820 case '*':
821 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
822 op) == FAIL)
823 return FAIL;
824 if (vartype == VAR_NUMBER)
825 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
826#ifdef FEAT_FLOAT
827 else if (vartype == VAR_FLOAT)
828 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
829#endif
830 else
831 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
832 if (isn != NULL)
833 isn->isn_arg.op.op_type = *op == '*'
834 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
835 break;
836
Bram Moolenaar4c683752020-04-05 21:38:23 +0200837 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100838 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200839 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100840 && type2->tt_type != VAR_NUMBER))
841 {
842 emsg(_("E1035: % requires number arguments"));
843 return FAIL;
844 }
845 isn = generate_instr_drop(cctx,
846 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
847 if (isn != NULL)
848 isn->isn_arg.op.op_type = EXPR_REM;
849 break;
850 }
851
852 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200853 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100854 {
855 type_T *type = &t_any;
856
857#ifdef FEAT_FLOAT
858 // float+number and number+float results in float
859 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
860 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
861 type = &t_float;
862#endif
863 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
864 }
865
866 return OK;
867}
868
869/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200870 * Get the instruction to use for comparing "type1" with "type2"
871 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100872 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200873 static isntype_T
874get_compare_isn(exptype_T exptype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100875{
876 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100877
Bram Moolenaar4c683752020-04-05 21:38:23 +0200878 if (type1 == VAR_UNKNOWN)
879 type1 = VAR_ANY;
880 if (type2 == VAR_UNKNOWN)
881 type2 = VAR_ANY;
882
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100883 if (type1 == type2)
884 {
885 switch (type1)
886 {
887 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
888 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
889 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
890 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
891 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
892 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
893 case VAR_LIST: isntype = ISN_COMPARELIST; break;
894 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
895 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896 default: isntype = ISN_COMPAREANY; break;
897 }
898 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200899 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100900 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
901 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
902 isntype = ISN_COMPAREANY;
903
904 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
905 && (isntype == ISN_COMPAREBOOL
906 || isntype == ISN_COMPARESPECIAL
907 || isntype == ISN_COMPARENR
908 || isntype == ISN_COMPAREFLOAT))
909 {
910 semsg(_("E1037: Cannot use \"%s\" with %s"),
911 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200912 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100913 }
914 if (isntype == ISN_DROP
915 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
916 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
917 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
918 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
919 && exptype != EXPR_IS && exptype != EXPR_ISNOT
920 && (type1 == VAR_BLOB || type2 == VAR_BLOB
921 || type1 == VAR_LIST || type2 == VAR_LIST))))
922 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100923 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100924 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200925 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100926 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200927 return isntype;
928}
929
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200930 int
931check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2)
932{
933 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
934 return FAIL;
935 return OK;
936}
937
Bram Moolenaara5565e42020-05-09 15:44:01 +0200938/*
939 * Generate an ISN_COMPARE* instruction with a boolean result.
940 */
941 static int
942generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
943{
944 isntype_T isntype;
945 isn_T *isn;
946 garray_T *stack = &cctx->ctx_type_stack;
947 vartype_T type1;
948 vartype_T type2;
949
950 RETURN_OK_IF_SKIP(cctx);
951
952 // Get the known type of the two items on the stack. If they are matching
953 // use a type-specific instruction. Otherwise fall back to runtime type
954 // checking.
955 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
956 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
957 isntype = get_compare_isn(exptype, type1, type2);
958 if (isntype == ISN_DROP)
959 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100960
961 if ((isn = generate_instr(cctx, isntype)) == NULL)
962 return FAIL;
963 isn->isn_arg.op.op_type = exptype;
964 isn->isn_arg.op.op_ic = ic;
965
966 // takes two arguments, puts one bool back
967 if (stack->ga_len >= 2)
968 {
969 --stack->ga_len;
970 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
971 }
972
973 return OK;
974}
975
976/*
977 * Generate an ISN_2BOOL instruction.
978 */
979 static int
980generate_2BOOL(cctx_T *cctx, int invert)
981{
982 isn_T *isn;
983 garray_T *stack = &cctx->ctx_type_stack;
984
Bram Moolenaar080457c2020-03-03 21:53:32 +0100985 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100986 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
987 return FAIL;
988 isn->isn_arg.number = invert;
989
990 // type becomes bool
991 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
992
993 return OK;
994}
995
996 static int
997generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
998{
999 isn_T *isn;
1000 garray_T *stack = &cctx->ctx_type_stack;
1001
Bram Moolenaar080457c2020-03-03 21:53:32 +01001002 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001003 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
1004 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +02001005 // TODO: whole type, e.g. for a function also arg and return types
1006 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001007 isn->isn_arg.type.ct_off = offset;
1008
1009 // type becomes vartype
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001010 ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011
1012 return OK;
1013}
1014
1015/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001016 * Check that
1017 * - "actual" is "expected" type or
1018 * - "actual" is a type that can be "expected" type: add a runtime check; or
1019 * - return FAIL.
1020 */
1021 static int
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001022need_type(
1023 type_T *actual,
1024 type_T *expected,
1025 int offset,
1026 cctx_T *cctx,
1027 int silent)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001028{
1029 if (check_type(expected, actual, FALSE) == OK)
1030 return OK;
1031 if (actual->tt_type != VAR_ANY
1032 && actual->tt_type != VAR_UNKNOWN
1033 && !(actual->tt_type == VAR_FUNC
1034 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
1035 {
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001036 if (!silent)
1037 type_mismatch(expected, actual);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001038 return FAIL;
1039 }
1040 generate_TYPECHECK(cctx, expected, offset);
1041 return OK;
1042}
1043
1044/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001045 * Generate an ISN_PUSHNR instruction.
1046 */
1047 static int
1048generate_PUSHNR(cctx_T *cctx, varnumber_T number)
1049{
1050 isn_T *isn;
1051
Bram Moolenaar080457c2020-03-03 21:53:32 +01001052 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001053 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
1054 return FAIL;
1055 isn->isn_arg.number = number;
1056
1057 return OK;
1058}
1059
1060/*
1061 * Generate an ISN_PUSHBOOL instruction.
1062 */
1063 static int
1064generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
1065{
1066 isn_T *isn;
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_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
1070 return FAIL;
1071 isn->isn_arg.number = number;
1072
1073 return OK;
1074}
1075
1076/*
1077 * Generate an ISN_PUSHSPEC instruction.
1078 */
1079 static int
1080generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
1081{
1082 isn_T *isn;
1083
Bram Moolenaar080457c2020-03-03 21:53:32 +01001084 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001085 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
1086 return FAIL;
1087 isn->isn_arg.number = number;
1088
1089 return OK;
1090}
1091
1092#ifdef FEAT_FLOAT
1093/*
1094 * Generate an ISN_PUSHF instruction.
1095 */
1096 static int
1097generate_PUSHF(cctx_T *cctx, float_T fnumber)
1098{
1099 isn_T *isn;
1100
Bram Moolenaar080457c2020-03-03 21:53:32 +01001101 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001102 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
1103 return FAIL;
1104 isn->isn_arg.fnumber = fnumber;
1105
1106 return OK;
1107}
1108#endif
1109
1110/*
1111 * Generate an ISN_PUSHS instruction.
1112 * Consumes "str".
1113 */
1114 static int
1115generate_PUSHS(cctx_T *cctx, char_u *str)
1116{
1117 isn_T *isn;
1118
Bram Moolenaar080457c2020-03-03 21:53:32 +01001119 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001120 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
1121 return FAIL;
1122 isn->isn_arg.string = str;
1123
1124 return OK;
1125}
1126
1127/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001128 * Generate an ISN_PUSHCHANNEL instruction.
1129 * Consumes "channel".
1130 */
1131 static int
1132generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
1133{
1134 isn_T *isn;
1135
Bram Moolenaar080457c2020-03-03 21:53:32 +01001136 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001137 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
1138 return FAIL;
1139 isn->isn_arg.channel = channel;
1140
1141 return OK;
1142}
1143
1144/*
1145 * Generate an ISN_PUSHJOB instruction.
1146 * Consumes "job".
1147 */
1148 static int
1149generate_PUSHJOB(cctx_T *cctx, job_T *job)
1150{
1151 isn_T *isn;
1152
Bram Moolenaar080457c2020-03-03 21:53:32 +01001153 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001154 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001155 return FAIL;
1156 isn->isn_arg.job = job;
1157
1158 return OK;
1159}
1160
1161/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001162 * Generate an ISN_PUSHBLOB instruction.
1163 * Consumes "blob".
1164 */
1165 static int
1166generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1167{
1168 isn_T *isn;
1169
Bram Moolenaar080457c2020-03-03 21:53:32 +01001170 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001171 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1172 return FAIL;
1173 isn->isn_arg.blob = blob;
1174
1175 return OK;
1176}
1177
1178/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001179 * Generate an ISN_PUSHFUNC instruction with name "name".
1180 * Consumes "name".
1181 */
1182 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001183generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001184{
1185 isn_T *isn;
1186
Bram Moolenaar080457c2020-03-03 21:53:32 +01001187 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001188 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001189 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02001190 isn->isn_arg.string = name == NULL ? NULL : vim_strsave(name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001191
1192 return OK;
1193}
1194
1195/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001196 * Generate an ISN_GETITEM instruction with "index".
1197 */
1198 static int
1199generate_GETITEM(cctx_T *cctx, int index)
1200{
1201 isn_T *isn;
1202 garray_T *stack = &cctx->ctx_type_stack;
1203 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1204 type_T *item_type = &t_any;
1205
1206 RETURN_OK_IF_SKIP(cctx);
1207
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001208 if (type->tt_type != VAR_LIST)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001209 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001210 // cannot happen, caller has checked the type
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001211 emsg(_(e_listreq));
1212 return FAIL;
1213 }
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001214 item_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001215 if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
1216 return FAIL;
1217 isn->isn_arg.number = index;
1218
1219 // add the item type to the type stack
1220 if (ga_grow(stack, 1) == FAIL)
1221 return FAIL;
1222 ((type_T **)stack->ga_data)[stack->ga_len] = item_type;
1223 ++stack->ga_len;
1224 return OK;
1225}
1226
1227/*
Bram Moolenaar9af78762020-06-16 11:34:42 +02001228 * Generate an ISN_SLICE instruction with "count".
1229 */
1230 static int
1231generate_SLICE(cctx_T *cctx, int count)
1232{
1233 isn_T *isn;
1234
1235 RETURN_OK_IF_SKIP(cctx);
1236 if ((isn = generate_instr(cctx, ISN_SLICE)) == NULL)
1237 return FAIL;
1238 isn->isn_arg.number = count;
1239 return OK;
1240}
1241
1242/*
1243 * Generate an ISN_CHECKLEN instruction with "min_len".
1244 */
1245 static int
1246generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK)
1247{
1248 isn_T *isn;
1249
1250 RETURN_OK_IF_SKIP(cctx);
1251
1252 if ((isn = generate_instr(cctx, ISN_CHECKLEN)) == NULL)
1253 return FAIL;
1254 isn->isn_arg.checklen.cl_min_len = min_len;
1255 isn->isn_arg.checklen.cl_more_OK = more_OK;
1256
1257 return OK;
1258}
1259
1260/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001261 * Generate an ISN_STORE instruction.
1262 */
1263 static int
1264generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1265{
1266 isn_T *isn;
1267
Bram Moolenaar080457c2020-03-03 21:53:32 +01001268 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001269 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1270 return FAIL;
1271 if (name != NULL)
1272 isn->isn_arg.string = vim_strsave(name);
1273 else
1274 isn->isn_arg.number = idx;
1275
1276 return OK;
1277}
1278
1279/*
1280 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1281 */
1282 static int
1283generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1284{
1285 isn_T *isn;
1286
Bram Moolenaar080457c2020-03-03 21:53:32 +01001287 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001288 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1289 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001290 isn->isn_arg.storenr.stnr_idx = idx;
1291 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001292
1293 return OK;
1294}
1295
1296/*
1297 * Generate an ISN_STOREOPT instruction
1298 */
1299 static int
1300generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1301{
1302 isn_T *isn;
1303
Bram Moolenaar080457c2020-03-03 21:53:32 +01001304 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001305 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
1306 return FAIL;
1307 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1308 isn->isn_arg.storeopt.so_flags = opt_flags;
1309
1310 return OK;
1311}
1312
1313/*
1314 * Generate an ISN_LOAD or similar instruction.
1315 */
1316 static int
1317generate_LOAD(
1318 cctx_T *cctx,
1319 isntype_T isn_type,
1320 int idx,
1321 char_u *name,
1322 type_T *type)
1323{
1324 isn_T *isn;
1325
Bram Moolenaar080457c2020-03-03 21:53:32 +01001326 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001327 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1328 return FAIL;
1329 if (name != NULL)
1330 isn->isn_arg.string = vim_strsave(name);
1331 else
1332 isn->isn_arg.number = idx;
1333
1334 return OK;
1335}
1336
1337/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001338 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001339 */
1340 static int
1341generate_LOADV(
1342 cctx_T *cctx,
1343 char_u *name,
1344 int error)
1345{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001346 int di_flags;
1347 int vidx = find_vim_var(name, &di_flags);
1348 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001349
Bram Moolenaar080457c2020-03-03 21:53:32 +01001350 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001351 if (vidx < 0)
1352 {
1353 if (error)
1354 semsg(_(e_var_notfound), name);
1355 return FAIL;
1356 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02001357 type = typval2type_vimvar(get_vim_var_tv(vidx), cctx->ctx_type_list);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001358
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001359 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001360}
1361
1362/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001363 * Generate an ISN_UNLET instruction.
1364 */
1365 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001366generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001367{
1368 isn_T *isn;
1369
1370 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001371 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001372 return FAIL;
1373 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1374 isn->isn_arg.unlet.ul_forceit = forceit;
1375
1376 return OK;
1377}
1378
1379/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001380 * Generate an ISN_LOADS instruction.
1381 */
1382 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001383generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001384 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001385 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001386 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001387 int sid,
1388 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001389{
1390 isn_T *isn;
1391
Bram Moolenaar080457c2020-03-03 21:53:32 +01001392 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001393 if (isn_type == ISN_LOADS)
1394 isn = generate_instr_type(cctx, isn_type, type);
1395 else
1396 isn = generate_instr_drop(cctx, isn_type, 1);
1397 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001398 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001399 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1400 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001401
1402 return OK;
1403}
1404
1405/*
1406 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1407 */
1408 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001409generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001410 cctx_T *cctx,
1411 isntype_T isn_type,
1412 int sid,
1413 int idx,
1414 type_T *type)
1415{
1416 isn_T *isn;
1417
Bram Moolenaar080457c2020-03-03 21:53:32 +01001418 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001419 if (isn_type == ISN_LOADSCRIPT)
1420 isn = generate_instr_type(cctx, isn_type, type);
1421 else
1422 isn = generate_instr_drop(cctx, isn_type, 1);
1423 if (isn == NULL)
1424 return FAIL;
1425 isn->isn_arg.script.script_sid = sid;
1426 isn->isn_arg.script.script_idx = idx;
1427 return OK;
1428}
1429
1430/*
1431 * Generate an ISN_NEWLIST instruction.
1432 */
1433 static int
1434generate_NEWLIST(cctx_T *cctx, int count)
1435{
1436 isn_T *isn;
1437 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001438 type_T *type;
1439 type_T *member;
1440
Bram Moolenaar080457c2020-03-03 21:53:32 +01001441 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001442 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1443 return FAIL;
1444 isn->isn_arg.number = count;
1445
1446 // drop the value types
1447 stack->ga_len -= count;
1448
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001449 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001450 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001451 if (count > 0)
1452 member = ((type_T **)stack->ga_data)[stack->ga_len];
1453 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001454 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001455 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001456
1457 // add the list type to the type stack
1458 if (ga_grow(stack, 1) == FAIL)
1459 return FAIL;
1460 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1461 ++stack->ga_len;
1462
1463 return OK;
1464}
1465
1466/*
1467 * Generate an ISN_NEWDICT instruction.
1468 */
1469 static int
1470generate_NEWDICT(cctx_T *cctx, int count)
1471{
1472 isn_T *isn;
1473 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001474 type_T *type;
1475 type_T *member;
1476
Bram Moolenaar080457c2020-03-03 21:53:32 +01001477 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001478 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1479 return FAIL;
1480 isn->isn_arg.number = count;
1481
1482 // drop the key and value types
1483 stack->ga_len -= 2 * count;
1484
Bram Moolenaar436472f2020-02-20 22:54:43 +01001485 // Use the first value type for the list member type. Use "void" for an
1486 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001487 if (count > 0)
1488 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1489 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001490 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001491 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001492
1493 // add the dict type to the type stack
1494 if (ga_grow(stack, 1) == FAIL)
1495 return FAIL;
1496 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1497 ++stack->ga_len;
1498
1499 return OK;
1500}
1501
1502/*
1503 * Generate an ISN_FUNCREF instruction.
1504 */
1505 static int
1506generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1507{
1508 isn_T *isn;
1509 garray_T *stack = &cctx->ctx_type_stack;
1510
Bram Moolenaar080457c2020-03-03 21:53:32 +01001511 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001512 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1513 return FAIL;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001514 isn->isn_arg.funcref.fr_func = dfunc_idx;
1515 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001516
1517 if (ga_grow(stack, 1) == FAIL)
1518 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001519 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001520 // TODO: argument and return types
1521 ++stack->ga_len;
1522
1523 return OK;
1524}
1525
1526/*
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001527 * Generate an ISN_NEWFUNC instruction.
1528 */
1529 static int
1530generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
1531{
1532 isn_T *isn;
1533 char_u *name;
1534
1535 RETURN_OK_IF_SKIP(cctx);
1536 name = vim_strsave(lambda_name);
1537 if (name == NULL)
1538 return FAIL;
1539 if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
1540 return FAIL;
1541 isn->isn_arg.newfunc.nf_lambda = name;
1542 isn->isn_arg.newfunc.nf_global = func_name;
1543
1544 return OK;
1545}
1546
1547/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001548 * Generate an ISN_JUMP instruction.
1549 */
1550 static int
1551generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1552{
1553 isn_T *isn;
1554 garray_T *stack = &cctx->ctx_type_stack;
1555
Bram Moolenaar080457c2020-03-03 21:53:32 +01001556 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001557 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1558 return FAIL;
1559 isn->isn_arg.jump.jump_when = when;
1560 isn->isn_arg.jump.jump_where = where;
1561
1562 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1563 --stack->ga_len;
1564
1565 return OK;
1566}
1567
1568 static int
1569generate_FOR(cctx_T *cctx, int loop_idx)
1570{
1571 isn_T *isn;
1572 garray_T *stack = &cctx->ctx_type_stack;
1573
Bram Moolenaar080457c2020-03-03 21:53:32 +01001574 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001575 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1576 return FAIL;
1577 isn->isn_arg.forloop.for_idx = loop_idx;
1578
1579 if (ga_grow(stack, 1) == FAIL)
1580 return FAIL;
1581 // type doesn't matter, will be stored next
1582 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1583 ++stack->ga_len;
1584
1585 return OK;
1586}
1587
1588/*
1589 * Generate an ISN_BCALL instruction.
Bram Moolenaar389df252020-07-09 21:20:47 +02001590 * "method_call" is TRUE for "value->method()"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001591 * Return FAIL if the number of arguments is wrong.
1592 */
1593 static int
Bram Moolenaar389df252020-07-09 21:20:47 +02001594generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001595{
1596 isn_T *isn;
1597 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar389df252020-07-09 21:20:47 +02001598 int argoff;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001599 type_T *argtypes[MAX_FUNC_ARGS];
1600 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001601
Bram Moolenaar080457c2020-03-03 21:53:32 +01001602 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar389df252020-07-09 21:20:47 +02001603 argoff = check_internal_func(func_idx, argcount);
1604 if (argoff < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001605 return FAIL;
1606
Bram Moolenaar389df252020-07-09 21:20:47 +02001607 if (method_call && argoff > 1)
1608 {
1609 if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
1610 return FAIL;
1611 isn->isn_arg.shuffle.shfl_item = argcount;
1612 isn->isn_arg.shuffle.shfl_up = argoff - 1;
1613 }
1614
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001615 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1616 return FAIL;
1617 isn->isn_arg.bfunc.cbf_idx = func_idx;
1618 isn->isn_arg.bfunc.cbf_argcount = argcount;
1619
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001620 for (i = 0; i < argcount; ++i)
1621 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1622
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001623 stack->ga_len -= argcount; // drop the arguments
1624 if (ga_grow(stack, 1) == FAIL)
1625 return FAIL;
1626 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001627 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001628 ++stack->ga_len; // add return value
1629
1630 return OK;
1631}
1632
1633/*
1634 * Generate an ISN_DCALL or ISN_UCALL instruction.
1635 * Return FAIL if the number of arguments is wrong.
1636 */
1637 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001638generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001639{
1640 isn_T *isn;
1641 garray_T *stack = &cctx->ctx_type_stack;
1642 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001643 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001644
Bram Moolenaar080457c2020-03-03 21:53:32 +01001645 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001646 if (argcount > regular_args && !has_varargs(ufunc))
1647 {
1648 semsg(_(e_toomanyarg), ufunc->uf_name);
1649 return FAIL;
1650 }
1651 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1652 {
1653 semsg(_(e_toofewarg), ufunc->uf_name);
1654 return FAIL;
1655 }
1656
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001657 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001658 {
1659 int i;
1660
1661 for (i = 0; i < argcount; ++i)
1662 {
1663 type_T *expected;
1664 type_T *actual;
1665
1666 if (i < regular_args)
1667 {
1668 if (ufunc->uf_arg_types == NULL)
1669 continue;
1670 expected = ufunc->uf_arg_types[i];
1671 }
1672 else
1673 expected = ufunc->uf_va_type->tt_member;
1674 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001675 if (need_type(actual, expected, -argcount + i, cctx, TRUE) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001676 {
1677 arg_type_mismatch(expected, actual, i + 1);
1678 return FAIL;
1679 }
1680 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001681 if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
Bram Moolenaar45a15082020-05-25 00:28:33 +02001682 if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02001683 return FAIL;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001684 }
1685
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001686 if ((isn = generate_instr(cctx,
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001687 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
Bram Moolenaar822ba242020-05-24 23:00:18 +02001688 : ISN_UCALL)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001689 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001690 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001691 {
1692 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1693 isn->isn_arg.dfunc.cdf_argcount = argcount;
1694 }
1695 else
1696 {
1697 // A user function may be deleted and redefined later, can't use the
1698 // ufunc pointer, need to look it up again at runtime.
1699 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1700 isn->isn_arg.ufunc.cuf_argcount = argcount;
1701 }
1702
1703 stack->ga_len -= argcount; // drop the arguments
1704 if (ga_grow(stack, 1) == FAIL)
1705 return FAIL;
1706 // add return value
1707 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1708 ++stack->ga_len;
1709
1710 return OK;
1711}
1712
1713/*
1714 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1715 */
1716 static int
1717generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1718{
1719 isn_T *isn;
1720 garray_T *stack = &cctx->ctx_type_stack;
1721
Bram Moolenaar080457c2020-03-03 21:53:32 +01001722 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001723 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1724 return FAIL;
1725 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1726 isn->isn_arg.ufunc.cuf_argcount = argcount;
1727
1728 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001729 if (ga_grow(stack, 1) == FAIL)
1730 return FAIL;
1731 // add return value
1732 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1733 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001734
1735 return OK;
1736}
1737
1738/*
1739 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001740 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001741 */
1742 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001743generate_PCALL(
1744 cctx_T *cctx,
1745 int argcount,
1746 char_u *name,
1747 type_T *type,
1748 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001749{
1750 isn_T *isn;
1751 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001752 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001753
Bram Moolenaar080457c2020-03-03 21:53:32 +01001754 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001755
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001756 if (type->tt_type == VAR_ANY)
1757 ret_type = &t_any;
1758 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001759 {
1760 if (type->tt_argcount != -1)
1761 {
1762 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1763
1764 if (argcount < type->tt_min_argcount - varargs)
1765 {
1766 semsg(_(e_toofewarg), "[reference]");
1767 return FAIL;
1768 }
1769 if (!varargs && argcount > type->tt_argcount)
1770 {
1771 semsg(_(e_toomanyarg), "[reference]");
1772 return FAIL;
1773 }
1774 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001775 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001776 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001777 else
1778 {
1779 semsg(_("E1085: Not a callable type: %s"), name);
1780 return FAIL;
1781 }
1782
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001783 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1784 return FAIL;
1785 isn->isn_arg.pfunc.cpf_top = at_top;
1786 isn->isn_arg.pfunc.cpf_argcount = argcount;
1787
1788 stack->ga_len -= argcount; // drop the arguments
1789
1790 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001791 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001792
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001793 // If partial is above the arguments it must be cleared and replaced with
1794 // the return value.
1795 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1796 return FAIL;
1797
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001798 return OK;
1799}
1800
1801/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001802 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001803 */
1804 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001805generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001806{
1807 isn_T *isn;
1808 garray_T *stack = &cctx->ctx_type_stack;
1809 type_T *type;
1810
Bram Moolenaar080457c2020-03-03 21:53:32 +01001811 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001812 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001813 return FAIL;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001814 isn->isn_arg.string = vim_strnsave(name, len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001815
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001816 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001817 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001818 if (type->tt_type != VAR_DICT && type != &t_any)
1819 {
1820 emsg(_(e_dictreq));
1821 return FAIL;
1822 }
1823 // change dict type to dict member type
1824 if (type->tt_type == VAR_DICT)
1825 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001826
1827 return OK;
1828}
1829
1830/*
1831 * Generate an ISN_ECHO instruction.
1832 */
1833 static int
1834generate_ECHO(cctx_T *cctx, int with_white, int count)
1835{
1836 isn_T *isn;
1837
Bram Moolenaar080457c2020-03-03 21:53:32 +01001838 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001839 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1840 return FAIL;
1841 isn->isn_arg.echo.echo_with_white = with_white;
1842 isn->isn_arg.echo.echo_count = count;
1843
1844 return OK;
1845}
1846
Bram Moolenaarad39c092020-02-26 18:23:43 +01001847/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001848 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001849 */
1850 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001851generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001852{
1853 isn_T *isn;
1854
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001855 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001856 return FAIL;
1857 isn->isn_arg.number = count;
1858
1859 return OK;
1860}
1861
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001862 static int
1863generate_EXEC(cctx_T *cctx, char_u *line)
1864{
1865 isn_T *isn;
1866
Bram Moolenaar080457c2020-03-03 21:53:32 +01001867 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001868 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1869 return FAIL;
1870 isn->isn_arg.string = vim_strsave(line);
1871 return OK;
1872}
1873
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001874 static int
1875generate_EXECCONCAT(cctx_T *cctx, int count)
1876{
1877 isn_T *isn;
1878
1879 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1880 return FAIL;
1881 isn->isn_arg.number = count;
1882 return OK;
1883}
1884
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001885/*
1886 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001887 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001888 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001889 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001890reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1891{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001892 lvar_T *lvar;
1893
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001894 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001895 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001896 emsg_namelen(_(e_used_as_arg), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001897 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001898 }
1899
1900 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001901 return NULL;
1902 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001903
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001904 // Every local variable uses the next entry on the stack. We could re-use
1905 // the last ones when leaving a scope, but then variables used in a closure
1906 // might get overwritten. To keep things simple do not re-use stack
1907 // entries. This is less efficient, but memory is cheap these days.
1908 lvar->lv_idx = cctx->ctx_locals_count++;
1909
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001910 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001911 lvar->lv_const = isConst;
1912 lvar->lv_type = type;
1913
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001914 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001915}
1916
1917/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001918 * Remove local variables above "new_top".
1919 */
1920 static void
1921unwind_locals(cctx_T *cctx, int new_top)
1922{
1923 if (cctx->ctx_locals.ga_len > new_top)
1924 {
1925 int idx;
1926 lvar_T *lvar;
1927
1928 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1929 {
1930 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1931 vim_free(lvar->lv_name);
1932 }
1933 }
1934 cctx->ctx_locals.ga_len = new_top;
1935}
1936
1937/*
1938 * Free all local variables.
1939 */
1940 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001941free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001942{
1943 unwind_locals(cctx, 0);
1944 ga_clear(&cctx->ctx_locals);
1945}
1946
1947/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001948 * Skip over a type definition and return a pointer to just after it.
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001949 * When "optional" is TRUE then a leading "?" is accepted.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001950 */
1951 char_u *
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001952skip_type(char_u *start, int optional)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001953{
1954 char_u *p = start;
1955
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001956 if (optional && *p == '?')
1957 ++p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001958 while (ASCII_ISALNUM(*p) || *p == '_')
1959 ++p;
1960
1961 // Skip over "<type>"; this is permissive about white space.
1962 if (*skipwhite(p) == '<')
1963 {
1964 p = skipwhite(p);
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001965 p = skip_type(skipwhite(p + 1), FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001966 p = skipwhite(p);
1967 if (*p == '>')
1968 ++p;
1969 }
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001970 else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1])))
1971 && STRNCMP("func", start, 4) == 0)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001972 {
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001973 if (*p == '(')
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001974 {
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001975 // handle func(args): type
1976 ++p;
1977 while (*p != ')' && *p != NUL)
1978 {
1979 char_u *sp = p;
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001980
Bram Moolenaarace61322020-07-26 18:16:58 +02001981 if (STRNCMP(p, "...", 3) == 0)
1982 p += 3;
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001983 p = skip_type(p, TRUE);
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001984 if (p == sp)
1985 return p; // syntax error
1986 if (*p == ',')
1987 p = skipwhite(p + 1);
1988 }
1989 if (*p == ')')
1990 {
1991 if (p[1] == ':')
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001992 p = skip_type(skipwhite(p + 2), FALSE);
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001993 else
Bram Moolenaarbfba8652020-07-23 20:09:10 +02001994 ++p;
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001995 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001996 }
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001997 else
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001998 {
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001999 // handle func: return_type
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02002000 p = skip_type(skipwhite(p + 1), FALSE);
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02002001 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002002 }
2003
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002004 return p;
2005}
2006
2007/*
2008 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02002009 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002010 * Returns NULL in case of failure.
2011 */
2012 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02002013parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002014{
2015 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002016 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002017
2018 if (**arg != '<')
2019 {
2020 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02002021 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002022 else
2023 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01002024 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002025 }
2026 *arg = skipwhite(*arg + 1);
2027
Bram Moolenaard77a8522020-04-03 21:59:57 +02002028 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002029
2030 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002031 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002032 {
2033 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01002034 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002035 }
2036 ++*arg;
2037
2038 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002039 return get_list_type(member_type, type_gap);
2040 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002041}
2042
2043/*
2044 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02002045 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002046 */
2047 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02002048parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002049{
2050 char_u *p = *arg;
2051 size_t len;
2052
2053 // skip over the first word
2054 while (ASCII_ISALNUM(*p) || *p == '_')
2055 ++p;
2056 len = p - *arg;
2057
2058 switch (**arg)
2059 {
2060 case 'a':
2061 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
2062 {
2063 *arg += len;
2064 return &t_any;
2065 }
2066 break;
2067 case 'b':
2068 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
2069 {
2070 *arg += len;
2071 return &t_bool;
2072 }
2073 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
2074 {
2075 *arg += len;
2076 return &t_blob;
2077 }
2078 break;
2079 case 'c':
2080 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
2081 {
2082 *arg += len;
2083 return &t_channel;
2084 }
2085 break;
2086 case 'd':
2087 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
2088 {
2089 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002090 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002091 }
2092 break;
2093 case 'f':
2094 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
2095 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01002096#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002097 *arg += len;
2098 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01002099#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002100 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01002101 return &t_any;
2102#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002103 }
2104 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
2105 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002106 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002107 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002108 int argcount = -1;
2109 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002110 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002111 type_T *arg_type[MAX_FUNC_ARGS + 1];
2112
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002113 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002114 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002115 if (**arg == '(')
2116 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002117 // "func" may or may not return a value, "func()" does
2118 // not return a value.
2119 ret_type = &t_void;
2120
Bram Moolenaard77a8522020-04-03 21:59:57 +02002121 p = ++*arg;
2122 argcount = 0;
2123 while (*p != NUL && *p != ')')
2124 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002125 if (*p == '?')
2126 {
2127 if (first_optional == -1)
2128 first_optional = argcount;
2129 ++p;
2130 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002131 else if (STRNCMP(p, "...", 3) == 0)
2132 {
2133 flags |= TTFLAG_VARARGS;
2134 p += 3;
2135 }
Bram Moolenaar01865ad2020-07-26 18:33:09 +02002136 else if (first_optional != -1)
2137 {
2138 emsg(_("E1007: mandatory argument after optional argument"));
2139 return &t_any;
2140 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002141
2142 arg_type[argcount++] = parse_type(&p, type_gap);
2143
2144 // Nothing comes after "...{type}".
2145 if (flags & TTFLAG_VARARGS)
2146 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002147
Bram Moolenaard77a8522020-04-03 21:59:57 +02002148 if (*p != ',' && *skipwhite(p) == ',')
2149 {
2150 semsg(_(e_no_white_before), ",");
2151 return &t_any;
2152 }
2153 if (*p == ',')
2154 {
2155 ++p;
2156 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002157 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002158 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002159 return &t_any;
2160 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02002161 }
2162 p = skipwhite(p);
2163 if (argcount == MAX_FUNC_ARGS)
2164 {
2165 emsg(_("E740: Too many argument types"));
2166 return &t_any;
2167 }
2168 }
2169
2170 p = skipwhite(p);
2171 if (*p != ')')
2172 {
2173 emsg(_(e_missing_close));
2174 return &t_any;
2175 }
2176 *arg = p + 1;
2177 }
2178 if (**arg == ':')
2179 {
2180 // parse return type
2181 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002182 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002183 semsg(_(e_white_after), ":");
2184 *arg = skipwhite(*arg);
2185 ret_type = parse_type(arg, type_gap);
2186 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002187 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002188 type = get_func_type(ret_type, argcount, type_gap);
2189 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002190 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002191 type = alloc_func_type(ret_type, argcount, type_gap);
2192 type->tt_flags = flags;
2193 if (argcount > 0)
2194 {
2195 type->tt_argcount = argcount;
2196 type->tt_min_argcount = first_optional == -1
2197 ? argcount : first_optional;
2198 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002199 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002200 return &t_any;
2201 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02002202 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002203 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02002204 }
2205 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002206 }
2207 break;
2208 case 'j':
2209 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
2210 {
2211 *arg += len;
2212 return &t_job;
2213 }
2214 break;
2215 case 'l':
2216 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
2217 {
2218 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002219 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002220 }
2221 break;
2222 case 'n':
2223 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
2224 {
2225 *arg += len;
2226 return &t_number;
2227 }
2228 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002229 case 's':
2230 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
2231 {
2232 *arg += len;
2233 return &t_string;
2234 }
2235 break;
2236 case 'v':
2237 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
2238 {
2239 *arg += len;
2240 return &t_void;
2241 }
2242 break;
2243 }
2244
2245 semsg(_("E1010: Type not recognized: %s"), *arg);
2246 return &t_any;
2247}
2248
2249/*
2250 * Check if "type1" and "type2" are exactly the same.
2251 */
2252 static int
2253equal_type(type_T *type1, type_T *type2)
2254{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002255 int i;
2256
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002257 if (type1->tt_type != type2->tt_type)
2258 return FALSE;
2259 switch (type1->tt_type)
2260 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002261 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02002262 case VAR_ANY:
2263 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002264 case VAR_SPECIAL:
2265 case VAR_BOOL:
2266 case VAR_NUMBER:
2267 case VAR_FLOAT:
2268 case VAR_STRING:
2269 case VAR_BLOB:
2270 case VAR_JOB:
2271 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002272 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002273 case VAR_LIST:
2274 case VAR_DICT:
2275 return equal_type(type1->tt_member, type2->tt_member);
2276 case VAR_FUNC:
2277 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002278 if (!equal_type(type1->tt_member, type2->tt_member)
2279 || type1->tt_argcount != type2->tt_argcount)
2280 return FALSE;
2281 if (type1->tt_argcount < 0
2282 || type1->tt_args == NULL || type2->tt_args == NULL)
2283 return TRUE;
2284 for (i = 0; i < type1->tt_argcount; ++i)
2285 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
2286 return FALSE;
2287 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002288 }
2289 return TRUE;
2290}
2291
2292/*
2293 * Find the common type of "type1" and "type2" and put it in "dest".
2294 * "type2" and "dest" may be the same.
2295 */
2296 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02002297common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002298{
2299 if (equal_type(type1, type2))
2300 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002301 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002302 return;
2303 }
2304
2305 if (type1->tt_type == type2->tt_type)
2306 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002307 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
2308 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002309 type_T *common;
2310
Bram Moolenaard77a8522020-04-03 21:59:57 +02002311 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002312 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002313 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002314 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002315 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002316 return;
2317 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002318 if (type1->tt_type == VAR_FUNC)
2319 {
2320 type_T *common;
2321
2322 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
2323 if (type1->tt_argcount == type2->tt_argcount
2324 && type1->tt_argcount >= 0)
2325 {
2326 int argcount = type1->tt_argcount;
2327 int i;
2328
2329 *dest = alloc_func_type(common, argcount, type_gap);
2330 if (type1->tt_args != NULL && type2->tt_args != NULL)
2331 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02002332 if (func_type_add_arg_types(*dest, argcount,
2333 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002334 for (i = 0; i < argcount; ++i)
2335 common_type(type1->tt_args[i], type2->tt_args[i],
2336 &(*dest)->tt_args[i], type_gap);
2337 }
2338 }
2339 else
2340 *dest = alloc_func_type(common, -1, type_gap);
2341 return;
2342 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002343 }
2344
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002345 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002346}
2347
2348 char *
2349vartype_name(vartype_T type)
2350{
2351 switch (type)
2352 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002353 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002354 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002355 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002356 case VAR_SPECIAL: return "special";
2357 case VAR_BOOL: return "bool";
2358 case VAR_NUMBER: return "number";
2359 case VAR_FLOAT: return "float";
2360 case VAR_STRING: return "string";
2361 case VAR_BLOB: return "blob";
2362 case VAR_JOB: return "job";
2363 case VAR_CHANNEL: return "channel";
2364 case VAR_LIST: return "list";
2365 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002366
2367 case VAR_FUNC:
2368 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002369 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02002370 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002371}
2372
2373/*
2374 * Return the name of a type.
2375 * The result may be in allocated memory, in which case "tofree" is set.
2376 */
2377 char *
2378type_name(type_T *type, char **tofree)
2379{
2380 char *name = vartype_name(type->tt_type);
2381
2382 *tofree = NULL;
2383 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
2384 {
2385 char *member_free;
2386 char *member_name = type_name(type->tt_member, &member_free);
2387 size_t len;
2388
2389 len = STRLEN(name) + STRLEN(member_name) + 3;
2390 *tofree = alloc(len);
2391 if (*tofree != NULL)
2392 {
2393 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
2394 vim_free(member_free);
2395 return *tofree;
2396 }
2397 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002398 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002399 {
2400 garray_T ga;
2401 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002402 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002403
2404 ga_init2(&ga, 1, 100);
2405 if (ga_grow(&ga, 20) == FAIL)
2406 return "[unknown]";
2407 *tofree = ga.ga_data;
2408 STRCPY(ga.ga_data, "func(");
2409 ga.ga_len += 5;
2410
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002411 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002412 {
2413 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002414 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002415 int len;
2416
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002417 if (type->tt_args == NULL)
2418 arg_type = "[unknown]";
2419 else
2420 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002421 if (i > 0)
2422 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002423 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002424 ga.ga_len += 2;
2425 }
2426 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002427 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002428 {
2429 vim_free(arg_free);
2430 return "[unknown]";
2431 }
2432 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002433 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002434 {
2435 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
2436 ga.ga_len += 3;
2437 }
2438 else if (i >= type->tt_min_argcount)
2439 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002440 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002441 ga.ga_len += len;
2442 vim_free(arg_free);
2443 }
2444
2445 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002446 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002447 else
2448 {
2449 char *ret_free;
2450 char *ret_name = type_name(type->tt_member, &ret_free);
2451 int len;
2452
2453 len = (int)STRLEN(ret_name) + 4;
2454 if (ga_grow(&ga, len) == FAIL)
2455 {
2456 vim_free(ret_free);
2457 return "[unknown]";
2458 }
2459 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002460 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
2461 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002462 vim_free(ret_free);
2463 }
2464 return ga.ga_data;
2465 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002466
2467 return name;
2468}
2469
2470/*
2471 * Find "name" in script-local items of script "sid".
2472 * Returns the index in "sn_var_vals" if found.
2473 * If found but not in "sn_var_vals" returns -1.
2474 * If not found returns -2.
2475 */
2476 int
2477get_script_item_idx(int sid, char_u *name, int check_writable)
2478{
2479 hashtab_T *ht;
2480 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002481 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002482 int idx;
2483
2484 // First look the name up in the hashtable.
2485 if (sid <= 0 || sid > script_items.ga_len)
2486 return -1;
2487 ht = &SCRIPT_VARS(sid);
2488 di = find_var_in_ht(ht, 0, name, TRUE);
2489 if (di == NULL)
2490 return -2;
2491
2492 // Now find the svar_T index in sn_var_vals.
2493 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2494 {
2495 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2496
2497 if (sv->sv_tv == &di->di_tv)
2498 {
2499 if (check_writable && sv->sv_const)
2500 semsg(_(e_readonlyvar), name);
2501 return idx;
2502 }
2503 }
2504 return -1;
2505}
2506
2507/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02002508 * Find "name" in imported items of the current script or in "cctx" if not
2509 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002510 */
2511 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002512find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002513{
Bram Moolenaar086eb182020-07-01 16:00:44 +02002514 scriptitem_T *si;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002515 int idx;
2516
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02002517 if (current_sctx.sc_sid <= 0)
2518 return NULL;
2519 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002520 if (cctx != NULL)
2521 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2522 {
2523 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2524 + idx;
2525
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002526 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2527 : STRLEN(import->imp_name) == len
2528 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002529 return import;
2530 }
2531
2532 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2533 {
2534 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2535
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002536 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2537 : STRLEN(import->imp_name) == len
2538 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002539 return import;
2540 }
2541 return NULL;
2542}
2543
2544/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002545 * Free all imported variables.
2546 */
2547 static void
2548free_imported(cctx_T *cctx)
2549{
2550 int idx;
2551
2552 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2553 {
2554 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2555
2556 vim_free(import->imp_name);
2557 }
2558 ga_clear(&cctx->ctx_imports);
2559}
2560
2561/*
Bram Moolenaar23c55272020-06-21 16:58:13 +02002562 * Return TRUE if "p" points at a "#" but not at "#{".
2563 */
Bram Moolenaar75783bd2020-07-19 14:41:58 +02002564 int
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002565vim9_comment_start(char_u *p)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002566{
2567 return p[0] == '#' && p[1] != '{';
2568}
2569
2570/*
2571 * Return a pointer to the next line that isn't empty or only contains a
2572 * comment. Skips over white space.
2573 * Returns NULL if there is none.
2574 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002575 char_u *
2576peek_next_line_from_context(cctx_T *cctx)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002577{
2578 int lnum = cctx->ctx_lnum;
2579
2580 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
2581 {
2582 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002583 char_u *p;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002584
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002585 if (line == NULL)
2586 break;
2587 p = skipwhite(line);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002588 if (*p != NUL && !vim9_comment_start(p))
Bram Moolenaar23c55272020-06-21 16:58:13 +02002589 return p;
2590 }
2591 return NULL;
2592}
2593
2594/*
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002595 * Called when checking for a following operator at "arg". When the rest of
2596 * the line is empty or only a comment, peek the next line. If there is a next
2597 * line return a pointer to it and set "nextp".
2598 * Otherwise skip over white space.
2599 */
2600 static char_u *
2601may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
2602{
2603 char_u *p = skipwhite(arg);
2604
2605 *nextp = NULL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002606 if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002607 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002608 *nextp = peek_next_line_from_context(cctx);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002609 if (*nextp != NULL)
2610 return *nextp;
2611 }
2612 return p;
2613}
2614
2615/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002616 * Get the next line of the function from "cctx".
Bram Moolenaar23c55272020-06-21 16:58:13 +02002617 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
Bram Moolenaare6085c52020-04-12 20:19:16 +02002618 * Returns NULL when at the end.
2619 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002620 char_u *
Bram Moolenaar23c55272020-06-21 16:58:13 +02002621next_line_from_context(cctx_T *cctx, int skip_comment)
Bram Moolenaare6085c52020-04-12 20:19:16 +02002622{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002623 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002624
2625 do
2626 {
2627 ++cctx->ctx_lnum;
2628 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002629 {
2630 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002631 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002632 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002633 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002634 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02002635 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002636 } while (line == NULL || *skipwhite(line) == NUL
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002637 || (skip_comment && vim9_comment_start(skipwhite(line))));
Bram Moolenaare6085c52020-04-12 20:19:16 +02002638 return line;
2639}
2640
2641/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002642 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002643 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002644 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2645 */
2646 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002647may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002648{
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002649 if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002650 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002651 char_u *next = next_line_from_context(cctx, TRUE);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002652
2653 if (next == NULL)
2654 return FAIL;
2655 *arg = skipwhite(next);
2656 }
2657 return OK;
2658}
2659
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002660/*
2661 * Idem, and give an error when failed.
2662 */
2663 static int
2664may_get_next_line_error(char_u *whitep, char_u **arg, cctx_T *cctx)
2665{
2666 if (may_get_next_line(whitep, arg, cctx) == FAIL)
2667 {
2668 emsg(_("E1097: line incomplete"));
2669 return FAIL;
2670 }
2671 return OK;
2672}
2673
2674
Bram Moolenaara5565e42020-05-09 15:44:01 +02002675// Structure passed between the compile_expr* functions to keep track of
2676// constants that have been parsed but for which no code was produced yet. If
2677// possible expressions on these constants are applied at compile time. If
2678// that is not possible, the code to push the constants needs to be generated
2679// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002680// Using 50 should be more than enough of 5 levels of ().
2681#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002682typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002683 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002684 int pp_used; // active entries in pp_tv[]
2685} ppconst_T;
2686
Bram Moolenaar1c747212020-05-09 18:28:34 +02002687static int compile_expr0(char_u **arg, cctx_T *cctx);
2688static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2689
Bram Moolenaara5565e42020-05-09 15:44:01 +02002690/*
2691 * Generate a PUSH instruction for "tv".
2692 * "tv" will be consumed or cleared.
2693 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2694 */
2695 static int
2696generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2697{
2698 if (tv != NULL)
2699 {
2700 switch (tv->v_type)
2701 {
2702 case VAR_UNKNOWN:
2703 break;
2704 case VAR_BOOL:
2705 generate_PUSHBOOL(cctx, tv->vval.v_number);
2706 break;
2707 case VAR_SPECIAL:
2708 generate_PUSHSPEC(cctx, tv->vval.v_number);
2709 break;
2710 case VAR_NUMBER:
2711 generate_PUSHNR(cctx, tv->vval.v_number);
2712 break;
2713#ifdef FEAT_FLOAT
2714 case VAR_FLOAT:
2715 generate_PUSHF(cctx, tv->vval.v_float);
2716 break;
2717#endif
2718 case VAR_BLOB:
2719 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2720 tv->vval.v_blob = NULL;
2721 break;
2722 case VAR_STRING:
2723 generate_PUSHS(cctx, tv->vval.v_string);
2724 tv->vval.v_string = NULL;
2725 break;
2726 default:
2727 iemsg("constant type not supported");
2728 clear_tv(tv);
2729 return FAIL;
2730 }
2731 tv->v_type = VAR_UNKNOWN;
2732 }
2733 return OK;
2734}
2735
2736/*
2737 * Generate code for any ppconst entries.
2738 */
2739 static int
2740generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2741{
2742 int i;
2743 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002744 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002745
Bram Moolenaar9b68c822020-06-18 19:31:08 +02002746 cctx->ctx_skip = SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002747 for (i = 0; i < ppconst->pp_used; ++i)
2748 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2749 ret = FAIL;
2750 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002751 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002752 return ret;
2753}
2754
2755/*
2756 * Clear ppconst constants. Used when failing.
2757 */
2758 static void
2759clear_ppconst(ppconst_T *ppconst)
2760{
2761 int i;
2762
2763 for (i = 0; i < ppconst->pp_used; ++i)
2764 clear_tv(&ppconst->pp_tv[i]);
2765 ppconst->pp_used = 0;
2766}
2767
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002768/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002769 * Generate an instruction to load script-local variable "name", without the
2770 * leading "s:".
2771 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002772 */
2773 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002774compile_load_scriptvar(
2775 cctx_T *cctx,
2776 char_u *name, // variable NUL terminated
2777 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002778 char_u **end, // end of variable
2779 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002780{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002781 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002782 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2783 imported_T *import;
2784
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002785 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002786 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002787 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002788 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2789 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002790 }
2791 if (idx >= 0)
2792 {
2793 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2794
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002795 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002796 current_sctx.sc_sid, idx, sv->sv_type);
2797 return OK;
2798 }
2799
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002800 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002801 if (import != NULL)
2802 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002803 if (import->imp_all)
2804 {
2805 char_u *p = skipwhite(*end);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002806 char_u *exp_name;
2807 int cc;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002808 ufunc_T *ufunc;
2809 type_T *type;
2810
2811 // Used "import * as Name", need to lookup the member.
2812 if (*p != '.')
2813 {
2814 semsg(_("E1060: expected dot after name: %s"), start);
2815 return FAIL;
2816 }
2817 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002818 if (VIM_ISWHITE(*p))
2819 {
2820 emsg(_("E1074: no white space allowed after dot"));
2821 return FAIL;
2822 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002823
Bram Moolenaar1c991142020-07-04 13:15:31 +02002824 // isolate one name
2825 exp_name = p;
2826 while (eval_isnamec(*p))
2827 ++p;
2828 cc = *p;
2829 *p = NUL;
2830
2831 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type);
2832 *p = cc;
2833 p = skipwhite(p);
2834
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002835 // TODO: what if it is a function?
2836 if (idx < 0)
2837 return FAIL;
2838 *end = p;
2839
2840 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2841 import->imp_sid,
2842 idx,
2843 type);
2844 }
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002845 else if (import->imp_funcname != NULL)
2846 generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002847 else
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002848 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2849 import->imp_sid,
2850 import->imp_var_vals_idx,
2851 import->imp_type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002852 return OK;
2853 }
2854
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002855 if (error)
2856 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002857 return FAIL;
2858}
2859
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002860 static int
2861generate_funcref(cctx_T *cctx, char_u *name)
2862{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002863 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002864
2865 if (ufunc == NULL)
2866 return FAIL;
2867
Bram Moolenaarb8070e32020-07-23 20:56:04 +02002868 // Need to compile any default values to get the argument types.
2869 if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
2870 if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
2871 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002872 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002873}
2874
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002875/*
2876 * Compile a variable name into a load instruction.
2877 * "end" points to just after the name.
2878 * When "error" is FALSE do not give an error when not found.
2879 */
2880 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002881compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002882{
2883 type_T *type;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002884 char_u *name = NULL;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002885 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002886 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002887 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002888
2889 if (*(*arg + 1) == ':')
2890 {
2891 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002892 if (end <= *arg + 2)
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002893 {
2894 isntype_T isn_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002895
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002896 switch (**arg)
2897 {
2898 case 'g': isn_type = ISN_LOADGDICT; break;
2899 case 'w': isn_type = ISN_LOADWDICT; break;
2900 case 't': isn_type = ISN_LOADTDICT; break;
2901 case 'b': isn_type = ISN_LOADBDICT; break;
2902 default:
2903 semsg(_(e_namespace), *arg);
2904 goto theend;
2905 }
2906 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
2907 goto theend;
2908 res = OK;
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002909 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002910 else
2911 {
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002912 isntype_T isn_type = ISN_DROP;
2913
2914 name = vim_strnsave(*arg + 2, end - (*arg + 2));
2915 if (name == NULL)
2916 return FAIL;
2917
2918 switch (**arg)
2919 {
2920 case 'v': res = generate_LOADV(cctx, name, error);
2921 break;
2922 case 's': res = compile_load_scriptvar(cctx, name,
2923 NULL, NULL, error);
2924 break;
2925 case 'g': isn_type = ISN_LOADG; break;
2926 case 'w': isn_type = ISN_LOADW; break;
2927 case 't': isn_type = ISN_LOADT; break;
2928 case 'b': isn_type = ISN_LOADB; break;
2929 default: semsg(_(e_namespace), *arg);
2930 goto theend;
2931 }
2932 if (isn_type != ISN_DROP)
2933 {
2934 // Global, Buffer-local, Window-local and Tabpage-local
2935 // variables can be defined later, thus we don't check if it
2936 // exists, give error at runtime.
2937 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
2938 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002939 }
2940 }
2941 else
2942 {
2943 size_t len = end - *arg;
2944 int idx;
2945 int gen_load = FALSE;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002946 int gen_load_outer = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002947
2948 name = vim_strnsave(*arg, end - *arg);
2949 if (name == NULL)
2950 return FAIL;
2951
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002952 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002953 {
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002954 if (!gen_load_outer)
2955 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002956 }
2957 else
2958 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002959 lvar_T *lvar = lookup_local(*arg, len, cctx);
2960
2961 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002962 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002963 type = lvar->lv_type;
2964 idx = lvar->lv_idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002965 if (lvar->lv_from_outer)
2966 gen_load_outer = TRUE;
2967 else
2968 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002969 }
2970 else
2971 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02002972 // "var" can be script-local even without using "s:" if it
2973 // already exists.
2974 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2975 == SCRIPT_VERSION_VIM9
2976 || lookup_script(*arg, len) == OK)
2977 res = compile_load_scriptvar(cctx, name, *arg, &end,
2978 FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002979
Bram Moolenaara5565e42020-05-09 15:44:01 +02002980 // When the name starts with an uppercase letter or "x:" it
2981 // can be a user defined function.
2982 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2983 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002984 }
2985 }
2986 if (gen_load)
2987 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002988 if (gen_load_outer)
2989 res = generate_LOAD(cctx, ISN_LOADOUTER, idx, NULL, type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002990 }
2991
2992 *arg = end;
2993
2994theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002995 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002996 semsg(_(e_var_notfound), name);
2997 vim_free(name);
2998 return res;
2999}
3000
3001/*
3002 * Compile the argument expressions.
3003 * "arg" points to just after the "(" and is advanced to after the ")"
3004 */
3005 static int
3006compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
3007{
Bram Moolenaar2c330432020-04-13 14:41:35 +02003008 char_u *p = *arg;
3009 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003010
Bram Moolenaare6085c52020-04-12 20:19:16 +02003011 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003012 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003013 if (may_get_next_line(whitep, &p, cctx) == FAIL)
3014 goto failret;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003015 if (*p == ')')
3016 {
3017 *arg = p + 1;
3018 return OK;
3019 }
3020
Bram Moolenaara5565e42020-05-09 15:44:01 +02003021 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003022 return FAIL;
3023 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003024
3025 if (*p != ',' && *skipwhite(p) == ',')
3026 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02003027 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003028 p = skipwhite(p);
3029 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003030 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003031 {
3032 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003033 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02003034 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003035 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003036 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003037 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003038 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003039failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02003040 emsg(_(e_missing_close));
3041 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003042}
3043
3044/*
3045 * Compile a function call: name(arg1, arg2)
3046 * "arg" points to "name", "arg + varlen" to the "(".
3047 * "argcount_init" is 1 for "value->method()"
3048 * Instructions:
3049 * EVAL arg1
3050 * EVAL arg2
3051 * BCALL / DCALL / UCALL
3052 */
3053 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003054compile_call(
3055 char_u **arg,
3056 size_t varlen,
3057 cctx_T *cctx,
3058 ppconst_T *ppconst,
3059 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003060{
3061 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01003062 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003063 int argcount = argcount_init;
3064 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003065 char_u fname_buf[FLEN_FIXED + 1];
3066 char_u *tofree = NULL;
3067 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003068 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003069 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003070
Bram Moolenaara5565e42020-05-09 15:44:01 +02003071 // we can evaluate "has('name')" at compile time
3072 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
3073 {
3074 char_u *s = skipwhite(*arg + varlen + 1);
3075 typval_T argvars[2];
3076
3077 argvars[0].v_type = VAR_UNKNOWN;
3078 if (*s == '"')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003079 (void)eval_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003080 else if (*s == '\'')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003081 (void)eval_lit_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003082 s = skipwhite(s);
3083 if (*s == ')' && argvars[0].v_type == VAR_STRING)
3084 {
3085 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
3086
3087 *arg = s + 1;
3088 argvars[1].v_type = VAR_UNKNOWN;
3089 tv->v_type = VAR_NUMBER;
3090 tv->vval.v_number = 0;
3091 f_has(argvars, tv);
3092 clear_tv(&argvars[0]);
3093 ++ppconst->pp_used;
3094 return OK;
3095 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02003096 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003097 }
3098
3099 if (generate_ppconst(cctx, ppconst) == FAIL)
3100 return FAIL;
3101
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003102 if (varlen >= sizeof(namebuf))
3103 {
3104 semsg(_("E1011: name too long: %s"), name);
3105 return FAIL;
3106 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003107 vim_strncpy(namebuf, *arg, varlen);
3108 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003109
3110 *arg = skipwhite(*arg + varlen + 1);
3111 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003112 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003113
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003114 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003115 {
3116 int idx;
3117
3118 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003119 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003120 if (idx >= 0)
Bram Moolenaar389df252020-07-09 21:20:47 +02003121 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003122 else
3123 semsg(_(e_unknownfunc), namebuf);
3124 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003125 }
3126
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003127 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02003128 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003129 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003130 {
3131 res = generate_CALL(cctx, ufunc, argcount);
3132 goto theend;
3133 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003134
3135 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02003136 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003137 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02003138 if (STRNCMP(namebuf, "g:", 2) != 0
3139 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003140 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003141 garray_T *stack = &cctx->ctx_type_stack;
3142 type_T *type;
3143
3144 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3145 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003146 goto theend;
3147 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003148
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003149 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003150 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003151 if (STRNCMP(namebuf, "g:", 2) == 0)
3152 res = generate_UCALL(cctx, name, argcount);
3153 else
3154 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003155
3156theend:
3157 vim_free(tofree);
3158 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003159}
3160
3161// like NAMESPACE_CHAR but with 'a' and 'l'.
3162#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
3163
3164/*
3165 * Find the end of a variable or function name. Unlike find_name_end() this
3166 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003167 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003168 * Return a pointer to just after the name. Equal to "arg" if there is no
3169 * valid name.
3170 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003171 static char_u *
3172to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003173{
3174 char_u *p;
3175
3176 // Quick check for valid starting character.
3177 if (!eval_isnamec1(*arg))
3178 return arg;
3179
3180 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
3181 // Include a namespace such as "s:var" and "v:var". But "n:" is not
3182 // and can be used in slice "[n:]".
3183 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003184 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003185 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
3186 break;
3187 return p;
3188}
3189
3190/*
3191 * Like to_name_end() but also skip over a list or dict constant.
Bram Moolenaar1c991142020-07-04 13:15:31 +02003192 * This intentionally does not handle line continuation.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003193 */
3194 char_u *
3195to_name_const_end(char_u *arg)
3196{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003197 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003198 typval_T rettv;
3199
3200 if (p == arg && *arg == '[')
3201 {
3202
3203 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003204 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003205 p = arg;
3206 }
3207 else if (p == arg && *arg == '#' && arg[1] == '{')
3208 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01003209 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003210 ++p;
Bram Moolenaar8ea93902020-06-27 14:11:53 +02003211 if (eval_dict(&p, &rettv, NULL, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003212 p = arg;
3213 }
3214 else if (p == arg && *arg == '{')
3215 {
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003216 int ret = get_lambda_tv(&p, &rettv, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003217
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01003218 // Can be "{x -> ret}()".
3219 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003220 if (ret == NOTDONE)
Bram Moolenaar8ea93902020-06-27 14:11:53 +02003221 ret = eval_dict(&p, &rettv, NULL, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003222 if (ret != OK)
3223 p = arg;
3224 }
3225
3226 return p;
3227}
3228
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003229/*
3230 * parse a list: [expr, expr]
3231 * "*arg" points to the '['.
3232 */
3233 static int
3234compile_list(char_u **arg, cctx_T *cctx)
3235{
3236 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003237 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003238 int count = 0;
3239
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003240 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003241 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003242 if (may_get_next_line(whitep, &p, cctx) == FAIL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01003243 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003244 semsg(_(e_list_end), *arg);
3245 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003246 }
3247 if (*p == ']')
3248 {
3249 ++p;
3250 // Allow for following comment, after at least one space.
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003251 if (VIM_ISWHITE(*p) && *skipwhite(p) == '#')
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003252 p += STRLEN(p);
3253 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01003254 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003255 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003256 break;
3257 ++count;
3258 if (*p == ',')
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003259 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003260 ++p;
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003261 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
3262 {
3263 semsg(_(e_white_after), ",");
3264 return FAIL;
3265 }
3266 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003267 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003268 p = skipwhite(p);
3269 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003270 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003271
3272 generate_NEWLIST(cctx, count);
3273 return OK;
3274}
3275
3276/*
3277 * parse a lambda: {arg, arg -> expr}
3278 * "*arg" points to the '{'.
3279 */
3280 static int
3281compile_lambda(char_u **arg, cctx_T *cctx)
3282{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003283 typval_T rettv;
3284 ufunc_T *ufunc;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003285 evalarg_T evalarg;
3286
3287 CLEAR_FIELD(evalarg);
3288 evalarg.eval_flags = EVAL_EVALUATE;
3289 evalarg.eval_cctx = cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003290
3291 // Get the funcref in "rettv".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003292 if (get_lambda_tv(arg, &rettv, &evalarg) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003293 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003294
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003295 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003296 ++ufunc->uf_refcount;
3297 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003298 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003299
3300 // The function will have one line: "return {expr}".
3301 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003302 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003303
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02003304 clear_evalarg(&evalarg, NULL);
3305
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02003306 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02003307 return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003308
3309 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003310 return FAIL;
3311}
3312
3313/*
3314 * Compile a lamda call: expr->{lambda}(args)
3315 * "arg" points to the "{".
3316 */
3317 static int
3318compile_lambda_call(char_u **arg, cctx_T *cctx)
3319{
3320 ufunc_T *ufunc;
3321 typval_T rettv;
3322 int argcount = 1;
3323 int ret = FAIL;
3324
3325 // Get the funcref in "rettv".
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003326 if (get_lambda_tv(arg, &rettv, &EVALARG_EVALUATE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003327 return FAIL;
3328
3329 if (**arg != '(')
3330 {
3331 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01003332 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003333 else
3334 semsg(_(e_missing_paren), "lambda");
3335 clear_tv(&rettv);
3336 return FAIL;
3337 }
3338
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003339 ufunc = rettv.vval.v_partial->pt_func;
3340 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003341 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003342 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01003343
3344 // The function will have one line: "return {expr}".
3345 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003346 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003347
3348 // compile the arguments
3349 *arg = skipwhite(*arg + 1);
3350 if (compile_arguments(arg, cctx, &argcount) == OK)
3351 // call the compiled function
3352 ret = generate_CALL(cctx, ufunc, argcount);
3353
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003354 if (ret == FAIL)
3355 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003356 return ret;
3357}
3358
3359/*
3360 * parse a dict: {'key': val} or #{key: val}
3361 * "*arg" points to the '{'.
3362 */
3363 static int
3364compile_dict(char_u **arg, cctx_T *cctx, int literal)
3365{
3366 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaarf1a23682020-07-13 18:55:48 +02003367 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003368 int count = 0;
3369 dict_T *d = dict_alloc();
3370 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003371 char_u *whitep = *arg;
3372 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003373
3374 if (d == NULL)
3375 return FAIL;
3376 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003377 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003378 {
3379 char_u *key = NULL;
3380
Bram Moolenaar23c55272020-06-21 16:58:13 +02003381 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003382 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003383 *arg = NULL;
3384 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003385 }
3386
3387 if (**arg == '}')
3388 break;
3389
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003390 if (literal)
3391 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02003392 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003393
Bram Moolenaar2c330432020-04-13 14:41:35 +02003394 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003395 {
3396 semsg(_("E1014: Invalid key: %s"), *arg);
3397 return FAIL;
3398 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003399 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003400 if (generate_PUSHS(cctx, key) == FAIL)
3401 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003402 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003403 }
3404 else
3405 {
3406 isn_T *isn;
3407
Bram Moolenaara5565e42020-05-09 15:44:01 +02003408 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003409 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003410 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
3411 if (isn->isn_type == ISN_PUSHS)
3412 key = isn->isn_arg.string;
Bram Moolenaarf1a23682020-07-13 18:55:48 +02003413 else
3414 {
3415 type_T *keytype = ((type_T **)stack->ga_data)
3416 [stack->ga_len - 1];
3417 if (need_type(keytype, &t_string, -1, cctx, FALSE) == FAIL)
3418 return FAIL;
3419 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003420 }
3421
3422 // Check for duplicate keys, if using string keys.
3423 if (key != NULL)
3424 {
3425 item = dict_find(d, key, -1);
3426 if (item != NULL)
3427 {
3428 semsg(_(e_duplicate_key), key);
3429 goto failret;
3430 }
3431 item = dictitem_alloc(key);
3432 if (item != NULL)
3433 {
3434 item->di_tv.v_type = VAR_UNKNOWN;
3435 item->di_tv.v_lock = 0;
3436 if (dict_add(d, item) == FAIL)
3437 dictitem_free(item);
3438 }
3439 }
3440
3441 *arg = skipwhite(*arg);
3442 if (**arg != ':')
3443 {
3444 semsg(_(e_missing_dict_colon), *arg);
3445 return FAIL;
3446 }
3447
Bram Moolenaar2c330432020-04-13 14:41:35 +02003448 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003449 *arg = skipwhite(*arg + 1);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003450 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003451 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003452 *arg = NULL;
3453 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003454 }
3455
Bram Moolenaara5565e42020-05-09 15:44:01 +02003456 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003457 return FAIL;
3458 ++count;
3459
Bram Moolenaar2c330432020-04-13 14:41:35 +02003460 whitep = *arg;
Bram Moolenaar23c55272020-06-21 16:58:13 +02003461 *arg = skipwhite(*arg);
3462 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003463 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003464 *arg = NULL;
3465 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003466 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003467 if (**arg == '}')
3468 break;
3469 if (**arg != ',')
3470 {
3471 semsg(_(e_missing_dict_comma), *arg);
3472 goto failret;
3473 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003474 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003475 *arg = skipwhite(*arg + 1);
3476 }
3477
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003478 *arg = *arg + 1;
3479
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003480 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003481 p = skipwhite(*arg);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003482 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003483 *arg += STRLEN(*arg);
3484
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003485 dict_unref(d);
3486 return generate_NEWDICT(cctx, count);
3487
3488failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003489 if (*arg == NULL)
3490 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003491 dict_unref(d);
3492 return FAIL;
3493}
3494
3495/*
3496 * Compile "&option".
3497 */
3498 static int
3499compile_get_option(char_u **arg, cctx_T *cctx)
3500{
3501 typval_T rettv;
3502 char_u *start = *arg;
3503 int ret;
3504
3505 // parse the option and get the current value to get the type.
3506 rettv.v_type = VAR_UNKNOWN;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003507 ret = eval_option(arg, &rettv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003508 if (ret == OK)
3509 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003510 // include the '&' in the name, eval_option() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003511 char_u *name = vim_strnsave(start, *arg - start);
3512 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
3513
3514 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3515 vim_free(name);
3516 }
3517 clear_tv(&rettv);
3518
3519 return ret;
3520}
3521
3522/*
3523 * Compile "$VAR".
3524 */
3525 static int
3526compile_get_env(char_u **arg, cctx_T *cctx)
3527{
3528 char_u *start = *arg;
3529 int len;
3530 int ret;
3531 char_u *name;
3532
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003533 ++*arg;
3534 len = get_env_len(arg);
3535 if (len == 0)
3536 {
3537 semsg(_(e_syntax_at), start - 1);
3538 return FAIL;
3539 }
3540
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003541 // include the '$' in the name, eval_env_var() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003542 name = vim_strnsave(start, len + 1);
3543 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3544 vim_free(name);
3545 return ret;
3546}
3547
3548/*
3549 * Compile "@r".
3550 */
3551 static int
3552compile_get_register(char_u **arg, cctx_T *cctx)
3553{
3554 int ret;
3555
3556 ++*arg;
3557 if (**arg == NUL)
3558 {
3559 semsg(_(e_syntax_at), *arg - 1);
3560 return FAIL;
3561 }
3562 if (!valid_yank_reg(**arg, TRUE))
3563 {
3564 emsg_invreg(**arg);
3565 return FAIL;
3566 }
3567 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3568 ++*arg;
3569 return ret;
3570}
3571
3572/*
3573 * Apply leading '!', '-' and '+' to constant "rettv".
3574 */
3575 static int
3576apply_leader(typval_T *rettv, char_u *start, char_u *end)
3577{
3578 char_u *p = end;
3579
3580 // this works from end to start
3581 while (p > start)
3582 {
3583 --p;
3584 if (*p == '-' || *p == '+')
3585 {
3586 // only '-' has an effect, for '+' we only check the type
3587#ifdef FEAT_FLOAT
3588 if (rettv->v_type == VAR_FLOAT)
3589 {
3590 if (*p == '-')
3591 rettv->vval.v_float = -rettv->vval.v_float;
3592 }
3593 else
3594#endif
3595 {
3596 varnumber_T val;
3597 int error = FALSE;
3598
3599 // tv_get_number_chk() accepts a string, but we don't want that
3600 // here
3601 if (check_not_string(rettv) == FAIL)
3602 return FAIL;
3603 val = tv_get_number_chk(rettv, &error);
3604 clear_tv(rettv);
3605 if (error)
3606 return FAIL;
3607 if (*p == '-')
3608 val = -val;
3609 rettv->v_type = VAR_NUMBER;
3610 rettv->vval.v_number = val;
3611 }
3612 }
3613 else
3614 {
3615 int v = tv2bool(rettv);
3616
3617 // '!' is permissive in the type.
3618 clear_tv(rettv);
3619 rettv->v_type = VAR_BOOL;
3620 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3621 }
3622 }
3623 return OK;
3624}
3625
3626/*
3627 * Recognize v: variables that are constants and set "rettv".
3628 */
3629 static void
3630get_vim_constant(char_u **arg, typval_T *rettv)
3631{
3632 if (STRNCMP(*arg, "v:true", 6) == 0)
3633 {
3634 rettv->v_type = VAR_BOOL;
3635 rettv->vval.v_number = VVAL_TRUE;
3636 *arg += 6;
3637 }
3638 else if (STRNCMP(*arg, "v:false", 7) == 0)
3639 {
3640 rettv->v_type = VAR_BOOL;
3641 rettv->vval.v_number = VVAL_FALSE;
3642 *arg += 7;
3643 }
3644 else if (STRNCMP(*arg, "v:null", 6) == 0)
3645 {
3646 rettv->v_type = VAR_SPECIAL;
3647 rettv->vval.v_number = VVAL_NULL;
3648 *arg += 6;
3649 }
3650 else if (STRNCMP(*arg, "v:none", 6) == 0)
3651 {
3652 rettv->v_type = VAR_SPECIAL;
3653 rettv->vval.v_number = VVAL_NONE;
3654 *arg += 6;
3655 }
3656}
3657
Bram Moolenaar696ba232020-07-29 21:20:41 +02003658 exptype_T
Bram Moolenaar61a89812020-05-07 16:58:17 +02003659get_compare_type(char_u *p, int *len, int *type_is)
3660{
3661 exptype_T type = EXPR_UNKNOWN;
3662 int i;
3663
3664 switch (p[0])
3665 {
3666 case '=': if (p[1] == '=')
3667 type = EXPR_EQUAL;
3668 else if (p[1] == '~')
3669 type = EXPR_MATCH;
3670 break;
3671 case '!': if (p[1] == '=')
3672 type = EXPR_NEQUAL;
3673 else if (p[1] == '~')
3674 type = EXPR_NOMATCH;
3675 break;
3676 case '>': if (p[1] != '=')
3677 {
3678 type = EXPR_GREATER;
3679 *len = 1;
3680 }
3681 else
3682 type = EXPR_GEQUAL;
3683 break;
3684 case '<': if (p[1] != '=')
3685 {
3686 type = EXPR_SMALLER;
3687 *len = 1;
3688 }
3689 else
3690 type = EXPR_SEQUAL;
3691 break;
3692 case 'i': if (p[1] == 's')
3693 {
3694 // "is" and "isnot"; but not a prefix of a name
3695 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3696 *len = 5;
3697 i = p[*len];
3698 if (!isalnum(i) && i != '_')
3699 {
3700 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3701 *type_is = TRUE;
3702 }
3703 }
3704 break;
3705 }
3706 return type;
3707}
3708
3709/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003710 * Compile code to apply '-', '+' and '!'.
3711 */
3712 static int
3713compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3714{
3715 char_u *p = end;
3716
3717 // this works from end to start
3718 while (p > start)
3719 {
3720 --p;
3721 if (*p == '-' || *p == '+')
3722 {
3723 int negate = *p == '-';
3724 isn_T *isn;
3725
3726 // TODO: check type
3727 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3728 {
3729 --p;
3730 if (*p == '-')
3731 negate = !negate;
3732 }
3733 // only '-' has an effect, for '+' we only check the type
3734 if (negate)
3735 isn = generate_instr(cctx, ISN_NEGATENR);
3736 else
3737 isn = generate_instr(cctx, ISN_CHECKNR);
3738 if (isn == NULL)
3739 return FAIL;
3740 }
3741 else
3742 {
3743 int invert = TRUE;
3744
3745 while (p > start && p[-1] == '!')
3746 {
3747 --p;
3748 invert = !invert;
3749 }
3750 if (generate_2BOOL(cctx, invert) == FAIL)
3751 return FAIL;
3752 }
3753 }
3754 return OK;
3755}
3756
3757/*
3758 * Compile whatever comes after "name" or "name()".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003759 * Advances "*arg" only when something was recognized.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003760 */
3761 static int
3762compile_subscript(
3763 char_u **arg,
3764 cctx_T *cctx,
3765 char_u **start_leader,
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003766 char_u *end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003767 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003768{
3769 for (;;)
3770 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003771 char_u *p = skipwhite(*arg);
3772
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003773 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003774 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003775 char_u *next = peek_next_line_from_context(cctx);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003776
3777 // If a following line starts with "->{" or "->X" advance to that
3778 // line, so that a line break before "->" is allowed.
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003779 // Also if a following line starts with ".x".
3780 if (next != NULL &&
3781 ((next[0] == '-' && next[1] == '>'
3782 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003783 || (next[0] == '.' && eval_isdictc(next[1]))))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003784 {
3785 next = next_line_from_context(cctx, TRUE);
3786 if (next == NULL)
3787 return FAIL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003788 *arg = next;
3789 p = skipwhite(*arg);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003790 }
3791 }
3792
Bram Moolenaar2d6b20d2020-07-25 19:30:59 +02003793 // Do not skip over white space to find the "(", "exeucte 'x' ()" is
3794 // not a function call.
3795 if (**arg == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003796 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003797 garray_T *stack = &cctx->ctx_type_stack;
3798 type_T *type;
3799 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003800
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003801 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003802 return FAIL;
3803
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003804 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003805 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3806
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003807 *arg = skipwhite(p + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003808 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3809 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003810 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003811 return FAIL;
3812 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003813 else if (*p == '-' && p[1] == '>')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003814 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003815 char_u *pstart = p;
3816
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003817 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003818 return FAIL;
3819
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003820 // something->method()
3821 // Apply the '!', '-' and '+' first:
3822 // -1.0->func() works like (-1.0)->func()
3823 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3824 return FAIL;
3825 *start_leader = end_leader; // don't apply again later
3826
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003827 p += 2;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003828 *arg = skipwhite(p);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003829 // No line break supported right after "->".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003830 if (**arg == '{')
3831 {
3832 // lambda call: list->{lambda}
3833 if (compile_lambda_call(arg, cctx) == FAIL)
3834 return FAIL;
3835 }
3836 else
3837 {
3838 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003839 p = *arg;
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003840 if (!eval_isnamec1(*p))
3841 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003842 semsg(_(e_trailing_arg), pstart);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003843 return FAIL;
3844 }
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003845 if (ASCII_ISALPHA(*p) && p[1] == ':')
3846 p += 2;
3847 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003848 ;
3849 if (*p != '(')
3850 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003851 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003852 return FAIL;
3853 }
3854 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02003855 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003856 return FAIL;
3857 }
3858 }
Bram Moolenaarbadd8482020-07-31 22:38:17 +02003859 else if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003860 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003861 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003862 type_T **typep;
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003863 vartype_T vtype;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003864
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003865 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003866 // dict member: dict[key]
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003867 // string index: text[123]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003868 // TODO: blob index
3869 // TODO: more arguments
3870 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003871 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003872 return FAIL;
3873
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003874 ++p;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003875 *arg = skipwhite(p);
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003876 if (may_get_next_line_error(p, arg, cctx) == FAIL)
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003877 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003878 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003879 return FAIL;
3880
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003881 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3882 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003883 if (**arg != ']')
3884 {
3885 emsg(_(e_missbrac));
3886 return FAIL;
3887 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003888 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003889
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003890 // We can index a list and a dict. If we don't know the type
3891 // we can use the index value type.
3892 // TODO: If we don't know use an instruction to figure it out at
3893 // runtime.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003894 typep = ((type_T **)stack->ga_data) + stack->ga_len - 2;
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003895 vtype = (*typep)->tt_type;
3896 if (*typep == &t_any)
3897 {
3898 type_T *valtype = ((type_T **)stack->ga_data)
3899 [stack->ga_len - 1];
3900 if (valtype == &t_string)
3901 vtype = VAR_DICT;
3902 }
3903 if (vtype == VAR_DICT)
3904 {
3905 if ((*typep)->tt_type == VAR_DICT)
3906 *typep = (*typep)->tt_member;
Bram Moolenaar7892b952020-07-20 22:09:34 +02003907 else
3908 {
3909 if (need_type(*typep, &t_dict_any, -2, cctx, FALSE) == FAIL)
3910 return FAIL;
3911 *typep = &t_any;
3912 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003913 if (may_generate_2STRING(-1, cctx) == FAIL)
3914 return FAIL;
3915 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
3916 return FAIL;
3917 }
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003918 else if (vtype == VAR_STRING)
3919 {
3920 *typep = &t_number;
3921 if (generate_instr_drop(cctx, ISN_STRINDEX, 1) == FAIL)
3922 return FAIL;
3923 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003924 else if (vtype == VAR_LIST || *typep == &t_any)
Bram Moolenaarb13af502020-02-17 21:12:08 +01003925 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003926 if ((*typep)->tt_type == VAR_LIST)
3927 *typep = (*typep)->tt_member;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003928 if (generate_instr_drop(cctx, ISN_LISTINDEX, 1) == FAIL)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003929 return FAIL;
3930 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003931 else
3932 {
3933 emsg(_(e_listdictblobreq));
Bram Moolenaarb13af502020-02-17 21:12:08 +01003934 return FAIL;
3935 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003936 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003937 else if (*p == '.' && p[1] != '.')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003938 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003939 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003940 return FAIL;
3941
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003942 *arg = p + 1;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003943 if (may_get_next_line(*arg, arg, cctx) == FAIL)
3944 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003945 // dictionary member: dict.name
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003946 p = *arg;
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003947 if (eval_isdictc(*p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003948 while (eval_isnamec(*p))
3949 MB_PTR_ADV(p);
3950 if (p == *arg)
3951 {
3952 semsg(_(e_syntax_at), *arg);
3953 return FAIL;
3954 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003955 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003956 return FAIL;
3957 *arg = p;
3958 }
3959 else
3960 break;
3961 }
3962
3963 // TODO - see handle_subscript():
3964 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3965 // Don't do this when "Func" is already a partial that was bound
3966 // explicitly (pt_auto is FALSE).
3967
3968 return OK;
3969}
3970
3971/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003972 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
3973 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003974 *
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003975 * If the value is a constant "ppconst->pp_ret" will be set.
3976 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003977 *
3978 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003979 */
3980
3981/*
3982 * number number constant
3983 * 0zFFFFFFFF Blob constant
3984 * "string" string constant
3985 * 'string' literal string constant
3986 * &option-name option value
3987 * @r register contents
3988 * identifier variable value
3989 * function() function call
3990 * $VAR environment variable
3991 * (expression) nested expression
3992 * [expr, expr] List
3993 * {key: val, key: val} Dictionary
3994 * #{key: val, key: val} Dictionary with literal keys
3995 *
3996 * Also handle:
3997 * ! in front logical NOT
3998 * - in front unary minus
3999 * + in front unary plus (ignored)
4000 * trailing (arg) funcref/partial call
4001 * trailing [] subscript in String or List
4002 * trailing .name entry in Dictionary
4003 * trailing ->name() method call
4004 */
4005 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004006compile_expr7(
4007 char_u **arg,
4008 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004009 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004010{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004011 char_u *start_leader, *end_leader;
4012 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004013 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02004014 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004015
4016 /*
4017 * Skip '!', '-' and '+' characters. They are handled later.
4018 */
4019 start_leader = *arg;
4020 while (**arg == '!' || **arg == '-' || **arg == '+')
4021 *arg = skipwhite(*arg + 1);
4022 end_leader = *arg;
4023
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004024 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004025 switch (**arg)
4026 {
4027 /*
4028 * Number constant.
4029 */
4030 case '0': // also for blob starting with 0z
4031 case '1':
4032 case '2':
4033 case '3':
4034 case '4':
4035 case '5':
4036 case '6':
4037 case '7':
4038 case '8':
4039 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004040 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004041 return FAIL;
4042 break;
4043
4044 /*
4045 * String constant: "string".
4046 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004047 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048 return FAIL;
4049 break;
4050
4051 /*
4052 * Literal string constant: 'str''ing'.
4053 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004054 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004055 return FAIL;
4056 break;
4057
4058 /*
4059 * Constant Vim variable.
4060 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004061 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004062 ret = NOTDONE;
4063 break;
4064
4065 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004066 * "true" constant
4067 */
4068 case 't': if (STRNCMP(*arg, "true", 4) == 0
4069 && !eval_isnamec((*arg)[4]))
4070 {
4071 *arg += 4;
4072 rettv->v_type = VAR_BOOL;
4073 rettv->vval.v_number = VVAL_TRUE;
4074 }
4075 else
4076 ret = NOTDONE;
4077 break;
4078
4079 /*
4080 * "false" constant
4081 */
4082 case 'f': if (STRNCMP(*arg, "false", 5) == 0
4083 && !eval_isnamec((*arg)[5]))
4084 {
4085 *arg += 5;
4086 rettv->v_type = VAR_BOOL;
4087 rettv->vval.v_number = VVAL_FALSE;
4088 }
4089 else
4090 ret = NOTDONE;
4091 break;
4092
4093 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004094 * List: [expr, expr]
4095 */
4096 case '[': ret = compile_list(arg, cctx);
4097 break;
4098
4099 /*
4100 * Dictionary: #{key: val, key: val}
4101 */
4102 case '#': if ((*arg)[1] == '{')
4103 {
4104 ++*arg;
4105 ret = compile_dict(arg, cctx, TRUE);
4106 }
4107 else
4108 ret = NOTDONE;
4109 break;
4110
4111 /*
4112 * Lambda: {arg, arg -> expr}
4113 * Dictionary: {'key': val, 'key': val}
4114 */
4115 case '{': {
4116 char_u *start = skipwhite(*arg + 1);
4117
4118 // Find out what comes after the arguments.
4119 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02004120 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004121 if (ret != FAIL && *start == '>')
4122 ret = compile_lambda(arg, cctx);
4123 else
4124 ret = compile_dict(arg, cctx, FALSE);
4125 }
4126 break;
4127
4128 /*
4129 * Option value: &name
4130 */
4131 case '&': ret = compile_get_option(arg, cctx);
4132 break;
4133
4134 /*
4135 * Environment variable: $VAR.
4136 */
4137 case '$': ret = compile_get_env(arg, cctx);
4138 break;
4139
4140 /*
4141 * Register contents: @r.
4142 */
4143 case '@': ret = compile_get_register(arg, cctx);
4144 break;
4145 /*
4146 * nested expression: (expression).
4147 */
4148 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaar1c747212020-05-09 18:28:34 +02004149
4150 // recursive!
4151 if (ppconst->pp_used <= PPSIZE - 10)
4152 {
4153 ret = compile_expr1(arg, cctx, ppconst);
4154 }
4155 else
4156 {
4157 // Not enough space in ppconst, flush constants.
4158 if (generate_ppconst(cctx, ppconst) == FAIL)
4159 return FAIL;
4160 ret = compile_expr0(arg, cctx);
4161 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004162 *arg = skipwhite(*arg);
4163 if (**arg == ')')
4164 ++*arg;
4165 else if (ret == OK)
4166 {
4167 emsg(_(e_missing_close));
4168 ret = FAIL;
4169 }
4170 break;
4171
4172 default: ret = NOTDONE;
4173 break;
4174 }
4175 if (ret == FAIL)
4176 return FAIL;
4177
Bram Moolenaar1c747212020-05-09 18:28:34 +02004178 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004179 {
4180 // apply the '!', '-' and '+' before the constant
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004181 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004182 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004183 clear_tv(rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004184 return FAIL;
4185 }
4186 start_leader = end_leader; // don't apply again below
4187
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004188 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004189 clear_tv(rettv);
4190 else
4191 // A constant expression can possibly be handled compile time,
4192 // return the value instead of generating code.
4193 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004194 }
4195 else if (ret == NOTDONE)
4196 {
4197 char_u *p;
4198 int r;
4199
4200 if (!eval_isnamec1(**arg))
4201 {
4202 semsg(_("E1015: Name expected: %s"), *arg);
4203 return FAIL;
4204 }
4205
4206 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01004207 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004208 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02004209 {
4210 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
4211 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004212 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02004213 {
4214 if (generate_ppconst(cctx, ppconst) == FAIL)
4215 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004216 r = compile_load(arg, p, cctx, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004217 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004218 if (r == FAIL)
4219 return FAIL;
4220 }
4221
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004222 // Handle following "[]", ".member", etc.
4223 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004224 if (compile_subscript(arg, cctx, &start_leader, end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02004225 ppconst) == FAIL)
4226 return FAIL;
4227 if (ppconst->pp_used > 0)
4228 {
4229 // apply the '!', '-' and '+' before the constant
4230 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
4231 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
4232 return FAIL;
4233 return OK;
4234 }
4235 if (compile_leader(cctx, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004236 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004237 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004238}
4239
4240/*
4241 * * number multiplication
4242 * / number division
4243 * % number modulo
4244 */
4245 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004246compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004247{
4248 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004249 char_u *next;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004250 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004251
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004252 // get the first expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004253 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004254 return FAIL;
4255
4256 /*
4257 * Repeat computing, until no "*", "/" or "%" is following.
4258 */
4259 for (;;)
4260 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004261 op = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004262 if (*op != '*' && *op != '/' && *op != '%')
4263 break;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004264 if (next != NULL)
4265 {
4266 *arg = next_line_from_context(cctx, TRUE);
4267 op = skipwhite(*arg);
4268 }
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004269
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004270 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004271 {
4272 char_u buf[3];
4273
4274 vim_strncpy(buf, op, 1);
4275 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004276 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004277 }
4278 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004279 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004280 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004281
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004282 // get the second expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004283 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004284 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004285
4286 if (ppconst->pp_used == ppconst_used + 2
4287 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4288 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004289 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004290 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4291 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004292 varnumber_T res = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004293
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004294 // both are numbers: compute the result
4295 switch (*op)
4296 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004297 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004298 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004299 case '/': res = tv1->vval.v_number / tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004300 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004301 case '%': res = tv1->vval.v_number % tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004302 break;
4303 }
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004304 tv1->vval.v_number = res;
4305 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004306 }
4307 else
4308 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004309 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004310 generate_two_op(cctx, op);
4311 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004312 }
4313
4314 return OK;
4315}
4316
4317/*
4318 * + number addition
4319 * - number subtraction
4320 * .. string concatenation
4321 */
4322 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004323compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004324{
4325 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004326 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004327 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004328 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004329
4330 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004331 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004332 return FAIL;
4333
4334 /*
4335 * Repeat computing, until no "+", "-" or ".." is following.
4336 */
4337 for (;;)
4338 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004339 op = may_peek_next_line(cctx, *arg, &next);
4340 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004341 break;
4342 oplen = (*op == '.' ? 2 : 1);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004343 if (next != NULL)
4344 {
4345 *arg = next_line_from_context(cctx, TRUE);
4346 op = skipwhite(*arg);
4347 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004348
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004349 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004350 {
4351 char_u buf[3];
4352
4353 vim_strncpy(buf, op, oplen);
4354 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004355 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004356 }
4357
4358 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004359 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004360 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004361
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004362 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004363 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004364 return FAIL;
4365
Bram Moolenaara5565e42020-05-09 15:44:01 +02004366 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004367 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02004368 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
4369 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
4370 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4371 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004372 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004373 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4374 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004375
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004376 // concat/subtract/add constant numbers
4377 if (*op == '+')
4378 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
4379 else if (*op == '-')
4380 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
4381 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004382 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004383 // concatenate constant strings
4384 char_u *s1 = tv1->vval.v_string;
4385 char_u *s2 = tv2->vval.v_string;
4386 size_t len1 = STRLEN(s1);
4387
4388 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
4389 if (tv1->vval.v_string == NULL)
4390 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004391 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004392 return FAIL;
4393 }
4394 mch_memmove(tv1->vval.v_string, s1, len1);
4395 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004396 vim_free(s1);
4397 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004398 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004399 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004400 }
4401 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004402 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004403 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004404 if (*op == '.')
4405 {
4406 if (may_generate_2STRING(-2, cctx) == FAIL
4407 || may_generate_2STRING(-1, cctx) == FAIL)
4408 return FAIL;
4409 generate_instr_drop(cctx, ISN_CONCAT, 1);
4410 }
4411 else
4412 generate_two_op(cctx, op);
4413 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004414 }
4415
4416 return OK;
4417}
4418
4419/*
4420 * expr5a == expr5b
4421 * expr5a =~ expr5b
4422 * expr5a != expr5b
4423 * expr5a !~ expr5b
4424 * expr5a > expr5b
4425 * expr5a >= expr5b
4426 * expr5a < expr5b
4427 * expr5a <= expr5b
4428 * expr5a is expr5b
4429 * expr5a isnot expr5b
4430 *
4431 * Produces instructions:
4432 * EVAL expr5a Push result of "expr5a"
4433 * EVAL expr5b Push result of "expr5b"
4434 * COMPARE one of the compare instructions
4435 */
4436 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004437compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004438{
4439 exptype_T type = EXPR_UNKNOWN;
4440 char_u *p;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004441 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004442 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004443 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004444 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004445
4446 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004447 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004448 return FAIL;
4449
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004450 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004451 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004452
4453 /*
4454 * If there is a comparative operator, use it.
4455 */
4456 if (type != EXPR_UNKNOWN)
4457 {
4458 int ic = FALSE; // Default: do not ignore case
4459
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004460 if (next != NULL)
4461 {
4462 *arg = next_line_from_context(cctx, TRUE);
4463 p = skipwhite(*arg);
4464 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004465 if (type_is && (p[len] == '?' || p[len] == '#'))
4466 {
4467 semsg(_(e_invexpr2), *arg);
4468 return FAIL;
4469 }
4470 // extra question mark appended: ignore case
4471 if (p[len] == '?')
4472 {
4473 ic = TRUE;
4474 ++len;
4475 }
4476 // extra '#' appended: match case (ignored)
4477 else if (p[len] == '#')
4478 ++len;
4479 // nothing appended: match case
4480
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004481 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004482 {
4483 char_u buf[7];
4484
4485 vim_strncpy(buf, p, len);
4486 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004487 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004488 }
4489
4490 // get the second variable
4491 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004492 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004493 return FAIL;
4494
Bram Moolenaara5565e42020-05-09 15:44:01 +02004495 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004496 return FAIL;
4497
Bram Moolenaara5565e42020-05-09 15:44:01 +02004498 if (ppconst->pp_used == ppconst_used + 2)
4499 {
4500 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4501 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4502 int ret;
4503
4504 // Both sides are a constant, compute the result now.
4505 // First check for a valid combination of types, this is more
4506 // strict than typval_compare().
Bram Moolenaar543e6f32020-07-10 22:45:38 +02004507 if (check_compare_types(type, tv1, tv2) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004508 ret = FAIL;
4509 else
4510 {
4511 ret = typval_compare(tv1, tv2, type, ic);
4512 tv1->v_type = VAR_BOOL;
4513 tv1->vval.v_number = tv1->vval.v_number
4514 ? VVAL_TRUE : VVAL_FALSE;
4515 clear_tv(tv2);
4516 --ppconst->pp_used;
4517 }
4518 return ret;
4519 }
4520
4521 generate_ppconst(cctx, ppconst);
4522 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004523 }
4524
4525 return OK;
4526}
4527
Bram Moolenaar7f141552020-05-09 17:35:53 +02004528static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4529
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004530/*
4531 * Compile || or &&.
4532 */
4533 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004534compile_and_or(
4535 char_u **arg,
4536 cctx_T *cctx,
4537 char *op,
4538 ppconst_T *ppconst,
4539 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004540{
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004541 char_u *next;
4542 char_u *p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004543 int opchar = *op;
4544
4545 if (p[0] == opchar && p[1] == opchar)
4546 {
4547 garray_T *instr = &cctx->ctx_instr;
4548 garray_T end_ga;
4549
4550 /*
4551 * Repeat until there is no following "||" or "&&"
4552 */
4553 ga_init2(&end_ga, sizeof(int), 10);
4554 while (p[0] == opchar && p[1] == opchar)
4555 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004556 if (next != NULL)
4557 {
4558 *arg = next_line_from_context(cctx, TRUE);
4559 p = skipwhite(*arg);
4560 }
4561
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004562 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4563 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004564 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004565 return FAIL;
4566 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004567
Bram Moolenaara5565e42020-05-09 15:44:01 +02004568 // TODO: use ppconst if the value is a constant
4569 generate_ppconst(cctx, ppconst);
4570
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004571 if (ga_grow(&end_ga, 1) == FAIL)
4572 {
4573 ga_clear(&end_ga);
4574 return FAIL;
4575 }
4576 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4577 ++end_ga.ga_len;
4578 generate_JUMP(cctx, opchar == '|'
4579 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
4580
4581 // eval the next expression
4582 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004583 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004584 return FAIL;
4585
Bram Moolenaara5565e42020-05-09 15:44:01 +02004586 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4587 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004588 {
4589 ga_clear(&end_ga);
4590 return FAIL;
4591 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004592
4593 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004594 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004595 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004596
4597 // Fill in the end label in all jumps.
4598 while (end_ga.ga_len > 0)
4599 {
4600 isn_T *isn;
4601
4602 --end_ga.ga_len;
4603 isn = ((isn_T *)instr->ga_data)
4604 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4605 isn->isn_arg.jump.jump_where = instr->ga_len;
4606 }
4607 ga_clear(&end_ga);
4608 }
4609
4610 return OK;
4611}
4612
4613/*
4614 * expr4a && expr4a && expr4a logical AND
4615 *
4616 * Produces instructions:
4617 * EVAL expr4a Push result of "expr4a"
4618 * JUMP_AND_KEEP_IF_FALSE end
4619 * EVAL expr4b Push result of "expr4b"
4620 * JUMP_AND_KEEP_IF_FALSE end
4621 * EVAL expr4c Push result of "expr4c"
4622 * end:
4623 */
4624 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004625compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004626{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004627 int ppconst_used = ppconst->pp_used;
4628
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004629 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004630 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004631 return FAIL;
4632
4633 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004634 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004635}
4636
4637/*
4638 * expr3a || expr3b || expr3c logical OR
4639 *
4640 * Produces instructions:
4641 * EVAL expr3a Push result of "expr3a"
4642 * JUMP_AND_KEEP_IF_TRUE end
4643 * EVAL expr3b Push result of "expr3b"
4644 * JUMP_AND_KEEP_IF_TRUE end
4645 * EVAL expr3c Push result of "expr3c"
4646 * end:
4647 */
4648 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004649compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004650{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004651 int ppconst_used = ppconst->pp_used;
4652
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004653 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004654 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004655 return FAIL;
4656
4657 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004658 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004659}
4660
4661/*
4662 * Toplevel expression: expr2 ? expr1a : expr1b
4663 *
4664 * Produces instructions:
4665 * EVAL expr2 Push result of "expr"
4666 * JUMP_IF_FALSE alt jump if false
4667 * EVAL expr1a
4668 * JUMP_ALWAYS end
4669 * alt: EVAL expr1b
4670 * end:
4671 */
4672 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004673compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004674{
4675 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004676 int ppconst_used = ppconst->pp_used;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004677 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004678
Bram Moolenaar61a89812020-05-07 16:58:17 +02004679 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004680 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004681 return FAIL;
4682
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004683 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004684 if (*p == '?')
4685 {
4686 garray_T *instr = &cctx->ctx_instr;
4687 garray_T *stack = &cctx->ctx_type_stack;
4688 int alt_idx = instr->ga_len;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004689 int end_idx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004690 isn_T *isn;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004691 type_T *type1 = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004692 type_T *type2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004693 int has_const_expr = FALSE;
4694 int const_value = FALSE;
4695 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004696
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004697 if (next != NULL)
4698 {
4699 *arg = next_line_from_context(cctx, TRUE);
4700 p = skipwhite(*arg);
4701 }
4702
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004703 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4704 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004705 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004706 return FAIL;
4707 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004708
Bram Moolenaara5565e42020-05-09 15:44:01 +02004709 if (ppconst->pp_used == ppconst_used + 1)
4710 {
4711 // the condition is a constant, we know whether the ? or the :
4712 // expression is to be evaluated.
4713 has_const_expr = TRUE;
4714 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4715 clear_tv(&ppconst->pp_tv[ppconst_used]);
4716 --ppconst->pp_used;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004717 cctx->ctx_skip = save_skip == SKIP_YES || !const_value
4718 ? SKIP_YES : SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004719 }
4720 else
4721 {
4722 generate_ppconst(cctx, ppconst);
4723 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4724 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004725
4726 // evaluate the second expression; any type is accepted
4727 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004728 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004729 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004730 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004731 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004732
Bram Moolenaara5565e42020-05-09 15:44:01 +02004733 if (!has_const_expr)
4734 {
4735 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004736
Bram Moolenaara5565e42020-05-09 15:44:01 +02004737 // remember the type and drop it
4738 --stack->ga_len;
4739 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004740
Bram Moolenaara5565e42020-05-09 15:44:01 +02004741 end_idx = instr->ga_len;
4742 generate_JUMP(cctx, JUMP_ALWAYS, 0);
4743
4744 // jump here from JUMP_IF_FALSE
4745 isn = ((isn_T *)instr->ga_data) + alt_idx;
4746 isn->isn_arg.jump.jump_where = instr->ga_len;
4747 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004748
4749 // Check for the ":".
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004750 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004751 if (*p != ':')
4752 {
4753 emsg(_(e_missing_colon));
4754 return FAIL;
4755 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004756 if (next != NULL)
4757 {
4758 *arg = next_line_from_context(cctx, TRUE);
4759 p = skipwhite(*arg);
4760 }
4761
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004762 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4763 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004764 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004765 return FAIL;
4766 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004767
4768 // evaluate the third expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004769 if (has_const_expr)
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004770 cctx->ctx_skip = save_skip == SKIP_YES || const_value
4771 ? SKIP_YES : SKIP_NOT;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004772 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004773 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004774 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004775 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004776 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004777
Bram Moolenaara5565e42020-05-09 15:44:01 +02004778 if (!has_const_expr)
4779 {
4780 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004781
Bram Moolenaara5565e42020-05-09 15:44:01 +02004782 // If the types differ, the result has a more generic type.
4783 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4784 common_type(type1, type2, &type2, cctx->ctx_type_list);
4785
4786 // jump here from JUMP_ALWAYS
4787 isn = ((isn_T *)instr->ga_data) + end_idx;
4788 isn->isn_arg.jump.jump_where = instr->ga_len;
4789 }
4790
4791 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004792 }
4793 return OK;
4794}
4795
4796/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004797 * Toplevel expression.
4798 */
4799 static int
4800compile_expr0(char_u **arg, cctx_T *cctx)
4801{
4802 ppconst_T ppconst;
4803
4804 CLEAR_FIELD(ppconst);
4805 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4806 {
4807 clear_ppconst(&ppconst);
4808 return FAIL;
4809 }
4810 if (generate_ppconst(cctx, &ppconst) == FAIL)
4811 return FAIL;
4812 return OK;
4813}
4814
4815/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004816 * compile "return [expr]"
4817 */
4818 static char_u *
4819compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4820{
4821 char_u *p = arg;
4822 garray_T *stack = &cctx->ctx_type_stack;
4823 type_T *stack_type;
4824
4825 if (*p != NUL && *p != '|' && *p != '\n')
4826 {
4827 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02004828 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004829 return NULL;
4830
4831 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4832 if (set_return_type)
4833 cctx->ctx_ufunc->uf_ret_type = stack_type;
Bram Moolenaar05a55512020-07-05 15:52:19 +02004834 else
4835 {
4836 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
4837 && stack_type->tt_type != VAR_VOID
4838 && stack_type->tt_type != VAR_UNKNOWN)
4839 {
4840 emsg(_("E1096: Returning a value in a function without a return type"));
4841 return NULL;
4842 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02004843 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
4844 cctx, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004845 return NULL;
Bram Moolenaar05a55512020-07-05 15:52:19 +02004846 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004847 }
4848 else
4849 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004850 // "set_return_type" cannot be TRUE, only used for a lambda which
4851 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004852 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4853 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004854 {
4855 emsg(_("E1003: Missing return value"));
4856 return NULL;
4857 }
4858
4859 // No argument, return zero.
4860 generate_PUSHNR(cctx, 0);
4861 }
4862
4863 if (generate_instr(cctx, ISN_RETURN) == NULL)
4864 return NULL;
4865
4866 // "return val | endif" is possible
4867 return skipwhite(p);
4868}
4869
4870/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004871 * Get a line from the compilation context, compatible with exarg_T getline().
4872 * Return a pointer to the line in allocated memory.
4873 * Return NULL for end-of-file or some error.
4874 */
4875 static char_u *
4876exarg_getline(
4877 int c UNUSED,
4878 void *cookie,
4879 int indent UNUSED,
4880 int do_concat UNUSED)
4881{
4882 cctx_T *cctx = (cctx_T *)cookie;
4883
4884 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4885 {
4886 iemsg("Heredoc got to end");
4887 return NULL;
4888 }
4889 ++cctx->ctx_lnum;
4890 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4891 [cctx->ctx_lnum]);
4892}
4893
4894/*
4895 * Compile a nested :def command.
4896 */
4897 static char_u *
4898compile_nested_function(exarg_T *eap, cctx_T *cctx)
4899{
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004900 int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
Bram Moolenaar04b12692020-05-04 23:24:44 +02004901 char_u *name_start = eap->arg;
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004902 char_u *name_end = to_name_end(eap->arg, TRUE);
Bram Moolenaareef21022020-08-01 22:16:43 +02004903 char_u *lambda_name;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004904 lvar_T *lvar;
4905 ufunc_T *ufunc;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004906 int r;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004907
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004908 // Only g:Func() can use a namespace.
4909 if (name_start[1] == ':' && !is_global)
4910 {
4911 semsg(_(e_namespace), name_start);
4912 return NULL;
4913 }
Bram Moolenaareef21022020-08-01 22:16:43 +02004914 if (check_defined(name_start, name_end - name_start, cctx) == FAIL)
4915 return NULL;
4916
Bram Moolenaar04b12692020-05-04 23:24:44 +02004917 eap->arg = name_end;
4918 eap->getline = exarg_getline;
4919 eap->cookie = cctx;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004920 eap->skip = cctx->ctx_skip == SKIP_YES;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004921 eap->forceit = FALSE;
Bram Moolenaareef21022020-08-01 22:16:43 +02004922 lambda_name = get_lambda_name();
4923 ufunc = def_function(eap, lambda_name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02004924
Bram Moolenaar822ba242020-05-24 23:00:18 +02004925 if (ufunc == NULL)
4926 return NULL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02004927 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
Bram Moolenaar822ba242020-05-24 23:00:18 +02004928 && compile_def_function(ufunc, TRUE, cctx) == FAIL)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004929 return NULL;
4930
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004931 if (is_global)
4932 {
4933 char_u *func_name = vim_strnsave(name_start + 2,
4934 name_end - name_start - 2);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004935
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004936 if (func_name == NULL)
4937 r = FAIL;
4938 else
Bram Moolenaareef21022020-08-01 22:16:43 +02004939 r = generate_NEWFUNC(cctx, lambda_name, func_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004940 }
4941 else
4942 {
4943 // Define a local variable for the function reference.
4944 lvar = reserve_local(cctx, name_start, name_end - name_start,
4945 TRUE, ufunc->uf_func_type);
Bram Moolenaareef21022020-08-01 22:16:43 +02004946 if (lvar == NULL)
4947 return NULL;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004948 if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL)
4949 return NULL;
4950 r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
4951 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02004952
Bram Moolenaar61a89812020-05-07 16:58:17 +02004953 // TODO: warning for trailing text?
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004954 return r == FAIL ? NULL : (char_u *)"";
Bram Moolenaar04b12692020-05-04 23:24:44 +02004955}
4956
4957/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004958 * Return the length of an assignment operator, or zero if there isn't one.
4959 */
4960 int
4961assignment_len(char_u *p, int *heredoc)
4962{
4963 if (*p == '=')
4964 {
4965 if (p[1] == '<' && p[2] == '<')
4966 {
4967 *heredoc = TRUE;
4968 return 3;
4969 }
4970 return 1;
4971 }
4972 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4973 return 2;
4974 if (STRNCMP(p, "..=", 3) == 0)
4975 return 3;
4976 return 0;
4977}
4978
4979// words that cannot be used as a variable
4980static char *reserved[] = {
4981 "true",
4982 "false",
4983 NULL
4984};
4985
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004986typedef enum {
4987 dest_local,
4988 dest_option,
4989 dest_env,
4990 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004991 dest_buffer,
4992 dest_window,
4993 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004994 dest_vimvar,
4995 dest_script,
4996 dest_reg,
4997} assign_dest_T;
4998
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004999/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005000 * Generate the load instruction for "name".
5001 */
5002 static void
5003generate_loadvar(
5004 cctx_T *cctx,
5005 assign_dest_T dest,
5006 char_u *name,
5007 lvar_T *lvar,
5008 type_T *type)
5009{
5010 switch (dest)
5011 {
5012 case dest_option:
5013 // TODO: check the option exists
5014 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
5015 break;
5016 case dest_global:
5017 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
5018 break;
5019 case dest_buffer:
5020 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
5021 break;
5022 case dest_window:
5023 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
5024 break;
5025 case dest_tab:
5026 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
5027 break;
5028 case dest_script:
5029 compile_load_scriptvar(cctx,
5030 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
5031 break;
5032 case dest_env:
5033 // Include $ in the name here
5034 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
5035 break;
5036 case dest_reg:
5037 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
5038 break;
5039 case dest_vimvar:
5040 generate_LOADV(cctx, name + 2, TRUE);
5041 break;
5042 case dest_local:
5043 if (lvar->lv_from_outer)
5044 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx,
5045 NULL, type);
5046 else
5047 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
5048 break;
5049 }
5050}
5051
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005052 void
5053vim9_declare_error(char_u *name)
5054{
5055 char *scope = "";
5056
5057 switch (*name)
5058 {
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005059 case 'g': scope = _("global"); break;
5060 case 'b': scope = _("buffer"); break;
5061 case 'w': scope = _("window"); break;
5062 case 't': scope = _("tab"); break;
5063 case 'v': scope = "v:"; break;
5064 case '$': semsg(_(e_declare_env_var), name); return;
5065 default: return;
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005066 }
5067 semsg(_(e_declare_var), scope, name);
5068}
5069
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005070/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005071 * Compile declaration and assignment:
5072 * "let var", "let var = expr", "const var = expr" and "var = expr"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005073 * "arg" points to "var".
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005074 * Return NULL for an error.
5075 * Return "arg" if it does not look like a variable list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005076 */
5077 static char_u *
5078compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
5079{
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005080 char_u *var_start;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005081 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005082 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005083 char_u *ret = NULL;
5084 int var_count = 0;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005085 int var_idx;
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005086 int scriptvar_sid = 0;
5087 int scriptvar_idx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005088 int semicolon = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005089 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005090 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005091 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005092 int oplen = 0;
5093 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02005094 type_T *type = &t_any;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005095 type_T *member_type = &t_any;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005096 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005097 char_u *sp;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005098 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005099
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005100 // Skip over the "var" or "[var, var]" to get to any "=".
5101 p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
5102 if (p == NULL)
5103 return *arg == '[' ? arg : NULL;
5104
5105 if (var_count > 0 && is_decl)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005106 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02005107 // TODO: should we allow this, and figure out type inference from list
5108 // members?
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005109 emsg(_("E1092: Cannot use a list for a declaration"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005110 return NULL;
5111 }
5112
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005113 sp = p;
5114 p = skipwhite(p);
5115 op = p;
5116 oplen = assignment_len(p, &heredoc);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005117
5118 if (var_count > 0 && oplen == 0)
5119 // can be something like "[1, 2]->func()"
5120 return arg;
5121
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005122 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
5123 {
5124 char_u buf[4];
5125
5126 vim_strncpy(buf, op, oplen);
5127 semsg(_(e_white_both), buf);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005128 return NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02005129 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005130
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005131 if (heredoc)
5132 {
5133 list_T *l;
5134 listitem_T *li;
5135
5136 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02005137 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005138 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02005139 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005140
5141 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02005142 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005143 {
5144 generate_PUSHS(cctx, li->li_tv.vval.v_string);
5145 li->li_tv.vval.v_string = NULL;
5146 }
5147 generate_NEWLIST(cctx, l->lv_len);
5148 type = &t_list_string;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005149 member_type = &t_list_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005150 list_free(l);
5151 p += STRLEN(p);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005152 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005153 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005154 else if (var_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005155 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005156 // for "[var, var] = expr" evaluate the expression here, loop over the
5157 // list of variables below.
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02005158
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005159 p = skipwhite(op + oplen);
5160 if (compile_expr0(&p, cctx) == FAIL)
5161 return NULL;
5162 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005163
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005164 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005165 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005166 type_T *stacktype;
5167
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005168 stacktype = stack->ga_len == 0 ? &t_void
5169 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005170 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005171 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005172 emsg(_(e_cannot_use_void));
5173 goto theend;
5174 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005175 if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005176 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02005177 // TODO: check the length of a constant list here
Bram Moolenaar9af78762020-06-16 11:34:42 +02005178 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
5179 semicolon);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005180 }
5181 }
5182
5183 /*
5184 * Loop over variables in "[var, var] = expr".
5185 * For "var = expr" and "let var: type" this is done only once.
5186 */
5187 if (var_count > 0)
5188 var_start = skipwhite(arg + 1); // skip over the "["
5189 else
5190 var_start = arg;
5191 for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
5192 {
5193 char_u *var_end = skip_var_one(var_start, FALSE);
5194 size_t varlen;
5195 int new_local = FALSE;
5196 int opt_type;
5197 int opt_flags = 0;
5198 assign_dest_T dest = dest_local;
5199 int vimvaridx = -1;
5200 lvar_T *lvar = NULL;
5201 lvar_T arg_lvar;
5202 int has_type = FALSE;
5203 int has_index = FALSE;
5204 int instr_count = -1;
5205
5206 p = (*var_start == '&' || *var_start == '$'
5207 || *var_start == '@') ? var_start + 1 : var_start;
5208 p = to_name_end(p, TRUE);
5209
5210 // "a: type" is declaring variable "a" with a type, not "a:".
5211 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
5212 --var_end;
5213 if (is_decl && p == var_start + 2 && p[-1] == ':')
5214 --p;
5215
5216 varlen = p - var_start;
5217 vim_free(name);
5218 name = vim_strnsave(var_start, varlen);
5219 if (name == NULL)
5220 return NULL;
5221 if (!heredoc)
5222 type = &t_any;
5223
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005224 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005225 {
5226 if (*var_start == '&')
5227 {
5228 int cc;
5229 long numval;
5230
5231 dest = dest_option;
5232 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005233 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005234 emsg(_(e_const_option));
5235 goto theend;
5236 }
5237 if (is_decl)
5238 {
5239 semsg(_("E1052: Cannot declare an option: %s"), var_start);
5240 goto theend;
5241 }
5242 p = var_start;
5243 p = find_option_end(&p, &opt_flags);
5244 if (p == NULL)
5245 {
5246 // cannot happen?
5247 emsg(_(e_letunexp));
5248 goto theend;
5249 }
5250 cc = *p;
5251 *p = NUL;
5252 opt_type = get_option_value(var_start + 1, &numval,
5253 NULL, opt_flags);
5254 *p = cc;
5255 if (opt_type == -3)
5256 {
5257 semsg(_(e_unknown_option), var_start);
5258 goto theend;
5259 }
5260 if (opt_type == -2 || opt_type == 0)
5261 type = &t_string;
5262 else
5263 type = &t_number; // both number and boolean option
5264 }
5265 else if (*var_start == '$')
5266 {
5267 dest = dest_env;
5268 type = &t_string;
5269 if (is_decl)
5270 {
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005271 vim9_declare_error(name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005272 goto theend;
5273 }
5274 }
5275 else if (*var_start == '@')
5276 {
5277 if (!valid_yank_reg(var_start[1], TRUE))
5278 {
5279 emsg_invreg(var_start[1]);
5280 goto theend;
5281 }
5282 dest = dest_reg;
5283 type = &t_string;
5284 if (is_decl)
5285 {
5286 semsg(_("E1066: Cannot declare a register: %s"), name);
5287 goto theend;
5288 }
5289 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005290 else if (varlen > 1 && STRNCMP(var_start, "g:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005291 {
5292 dest = dest_global;
5293 if (is_decl)
5294 {
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005295 vim9_declare_error(name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005296 goto theend;
5297 }
5298 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005299 else if (varlen > 1 && STRNCMP(var_start, "b:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005300 {
5301 dest = dest_buffer;
5302 if (is_decl)
5303 {
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005304 vim9_declare_error(name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005305 goto theend;
5306 }
5307 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005308 else if (varlen > 1 && STRNCMP(var_start, "w:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005309 {
5310 dest = dest_window;
5311 if (is_decl)
5312 {
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005313 vim9_declare_error(name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005314 goto theend;
5315 }
5316 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005317 else if (varlen > 1 && STRNCMP(var_start, "t:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005318 {
5319 dest = dest_tab;
5320 if (is_decl)
5321 {
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005322 vim9_declare_error(name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005323 goto theend;
5324 }
5325 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005326 else if (varlen > 1 && STRNCMP(var_start, "v:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005327 {
5328 typval_T *vtv;
5329 int di_flags;
5330
5331 vimvaridx = find_vim_var(name + 2, &di_flags);
5332 if (vimvaridx < 0)
5333 {
5334 semsg(_(e_var_notfound), var_start);
5335 goto theend;
5336 }
5337 // We use the current value of "sandbox" here, is that OK?
5338 if (var_check_ro(di_flags, name, FALSE))
5339 goto theend;
5340 dest = dest_vimvar;
5341 vtv = get_vim_var_tv(vimvaridx);
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02005342 type = typval2type_vimvar(vtv, cctx->ctx_type_list);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005343 if (is_decl)
5344 {
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005345 vim9_declare_error(name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005346 goto theend;
5347 }
5348 }
5349 else
5350 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005351 int idx;
5352 imported_T *import = NULL;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005353
5354 for (idx = 0; reserved[idx] != NULL; ++idx)
5355 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005356 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005357 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005358 goto theend;
5359 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005360
5361 lvar = lookup_local(var_start, varlen, cctx);
5362 if (lvar == NULL)
5363 {
5364 CLEAR_FIELD(arg_lvar);
5365 if (lookup_arg(var_start, varlen,
5366 &arg_lvar.lv_idx, &arg_lvar.lv_type,
5367 &arg_lvar.lv_from_outer, cctx) == OK)
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005368 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005369 if (is_decl)
5370 {
5371 semsg(_(e_used_as_arg), name);
5372 goto theend;
5373 }
5374 lvar = &arg_lvar;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005375 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005376 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005377 if (lvar != NULL)
5378 {
5379 if (is_decl)
5380 {
5381 semsg(_("E1017: Variable already declared: %s"), name);
5382 goto theend;
5383 }
5384 else if (lvar->lv_const)
5385 {
5386 semsg(_("E1018: Cannot assign to a constant: %s"),
5387 name);
5388 goto theend;
5389 }
5390 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005391 else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005392 || lookup_script(var_start, varlen) == OK
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005393 || (import = find_imported(var_start, varlen, cctx))
5394 != NULL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005395 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005396 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5397
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005398 if (is_decl)
5399 {
Bram Moolenaar33afa242020-07-29 19:18:00 +02005400 if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0))
5401 semsg(_("E1101: Cannot declare a script variable in a function: %s"),
5402 name);
5403 else
5404 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005405 name);
5406 goto theend;
5407 }
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005408 dest = dest_script;
5409
5410 // existing script-local variables should have a type
5411 scriptvar_sid = current_sctx.sc_sid;
5412 if (import != NULL)
5413 scriptvar_sid = import->imp_sid;
5414 scriptvar_idx = get_script_item_idx(scriptvar_sid,
5415 rawname, TRUE);
5416 if (scriptvar_idx >= 0)
5417 {
5418 scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
5419 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
5420 + scriptvar_idx;
5421 type = sv->sv_type;
5422 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005423 }
5424 else if (name[1] == ':' && name[2] != NUL)
5425 {
5426 semsg(_("E1082: Cannot use a namespaced variable: %s"),
5427 name);
5428 goto theend;
5429 }
5430 else if (!is_decl)
5431 {
5432 semsg(_("E1089: unknown variable: %s"), name);
5433 goto theend;
5434 }
5435 }
5436 }
5437
5438 // handle "a:name" as a name, not index "name" on "a"
5439 if (varlen > 1 || var_start[varlen] != ':')
5440 p = var_end;
5441
5442 if (dest != dest_option)
5443 {
5444 if (is_decl && *p == ':')
5445 {
5446 // parse optional type: "let var: type = expr"
5447 if (!VIM_ISWHITE(p[1]))
5448 {
5449 semsg(_(e_white_after), ":");
5450 goto theend;
5451 }
5452 p = skipwhite(p + 1);
5453 type = parse_type(&p, cctx->ctx_type_list);
5454 has_type = TRUE;
5455 }
5456 else if (lvar != NULL)
5457 type = lvar->lv_type;
5458 }
5459
5460 if (oplen == 3 && !heredoc && dest != dest_global
5461 && type->tt_type != VAR_STRING
5462 && type->tt_type != VAR_ANY)
5463 {
5464 emsg(_("E1019: Can only concatenate to string"));
5465 goto theend;
5466 }
5467
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005468 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005469 {
5470 if (oplen > 1 && !heredoc)
5471 {
5472 // +=, /=, etc. require an existing variable
5473 semsg(_("E1020: cannot use an operator on a new variable: %s"),
5474 name);
5475 goto theend;
5476 }
5477
5478 // new local variable
5479 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
5480 goto theend;
5481 lvar = reserve_local(cctx, var_start, varlen,
5482 cmdidx == CMD_const, type);
5483 if (lvar == NULL)
5484 goto theend;
5485 new_local = TRUE;
5486 }
5487
5488 member_type = type;
5489 if (var_end > var_start + varlen)
5490 {
5491 // Something follows after the variable: "var[idx]".
5492 if (is_decl)
5493 {
5494 emsg(_("E1087: cannot use an index when declaring a variable"));
5495 goto theend;
5496 }
5497
5498 if (var_start[varlen] == '[')
5499 {
5500 has_index = TRUE;
5501 if (type->tt_member == NULL)
Bram Moolenaar2caa1592020-08-01 15:53:19 +02005502 member_type = &t_any;
5503 else
5504 member_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005505 }
5506 else
5507 {
5508 semsg("Not supported yet: %s", var_start);
5509 goto theend;
5510 }
5511 }
5512 else if (lvar == &arg_lvar)
5513 {
5514 semsg(_("E1090: Cannot assign to argument %s"), name);
5515 goto theend;
5516 }
5517
5518 if (!heredoc)
5519 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005520 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005521 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005522 if (oplen > 0 && var_count == 0)
5523 {
5524 // skip over the "=" and the expression
5525 p = skipwhite(op + oplen);
5526 compile_expr0(&p, cctx);
5527 }
5528 }
5529 else if (oplen > 0)
5530 {
5531 type_T *stacktype;
5532
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005533 // For "var = expr" evaluate the expression.
5534 if (var_count == 0)
5535 {
5536 int r;
5537
5538 // for "+=", "*=", "..=" etc. first load the current value
5539 if (*op != '=')
5540 {
5541 generate_loadvar(cctx, dest, name, lvar, type);
5542
5543 if (has_index)
5544 {
5545 // TODO: get member from list or dict
5546 emsg("Index with operation not supported yet");
5547 goto theend;
5548 }
5549 }
5550
5551 // Compile the expression. Temporarily hide the new local
5552 // variable here, it is not available to this expression.
5553 if (new_local)
5554 --cctx->ctx_locals.ga_len;
5555 instr_count = instr->ga_len;
5556 p = skipwhite(op + oplen);
5557 r = compile_expr0(&p, cctx);
5558 if (new_local)
5559 ++cctx->ctx_locals.ga_len;
5560 if (r == FAIL)
5561 goto theend;
5562 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02005563 else if (semicolon && var_idx == var_count - 1)
5564 {
5565 // For "[var; var] = expr" get the rest of the list
5566 if (generate_SLICE(cctx, var_count - 1) == FAIL)
5567 goto theend;
5568 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005569 else
5570 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005571 // For "[var, var] = expr" get the "var_idx" item from the
5572 // list.
5573 if (generate_GETITEM(cctx, var_idx) == FAIL)
5574 return FAIL;
5575 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005576
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005577 stacktype = stack->ga_len == 0 ? &t_void
Bram Moolenaar6802cce2020-07-19 15:49:49 +02005578 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005579 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005580 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005581 if (new_local && !has_type)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005582 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005583 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005584 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005585 emsg(_(e_cannot_use_void));
5586 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005587 }
5588 else
5589 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005590 // An empty list or dict has a &t_void member,
5591 // for a variable that implies &t_any.
5592 if (stacktype == &t_list_empty)
5593 lvar->lv_type = &t_list_any;
5594 else if (stacktype == &t_dict_empty)
5595 lvar->lv_type = &t_dict_any;
5596 else
5597 lvar->lv_type = stacktype;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005598 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005599 }
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005600 else
5601 {
5602 type_T *use_type = lvar->lv_type;
5603
5604 if (has_index)
5605 {
5606 use_type = use_type->tt_member;
5607 if (use_type == NULL)
5608 use_type = &t_void;
5609 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005610 if (need_type(stacktype, use_type, -1, cctx, FALSE)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005611 == FAIL)
5612 goto theend;
5613 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005614 }
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005615 else if (*p != '=' && need_type(stacktype, member_type, -1,
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005616 cctx, FALSE) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005617 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005618 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005619 else if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005620 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005621 emsg(_(e_const_req_value));
5622 goto theend;
5623 }
5624 else if (!has_type || dest == dest_option)
5625 {
5626 emsg(_(e_type_req));
5627 goto theend;
5628 }
5629 else
5630 {
5631 // variables are always initialized
5632 if (ga_grow(instr, 1) == FAIL)
5633 goto theend;
5634 switch (member_type->tt_type)
5635 {
5636 case VAR_BOOL:
5637 generate_PUSHBOOL(cctx, VVAL_FALSE);
5638 break;
5639 case VAR_FLOAT:
5640#ifdef FEAT_FLOAT
5641 generate_PUSHF(cctx, 0.0);
5642#endif
5643 break;
5644 case VAR_STRING:
5645 generate_PUSHS(cctx, NULL);
5646 break;
5647 case VAR_BLOB:
5648 generate_PUSHBLOB(cctx, NULL);
5649 break;
5650 case VAR_FUNC:
5651 generate_PUSHFUNC(cctx, NULL, &t_func_void);
5652 break;
5653 case VAR_LIST:
5654 generate_NEWLIST(cctx, 0);
5655 break;
5656 case VAR_DICT:
5657 generate_NEWDICT(cctx, 0);
5658 break;
5659 case VAR_JOB:
5660 generate_PUSHJOB(cctx, NULL);
5661 break;
5662 case VAR_CHANNEL:
5663 generate_PUSHCHANNEL(cctx, NULL);
5664 break;
5665 case VAR_NUMBER:
5666 case VAR_UNKNOWN:
5667 case VAR_ANY:
5668 case VAR_PARTIAL:
5669 case VAR_VOID:
5670 case VAR_SPECIAL: // cannot happen
5671 generate_PUSHNR(cctx, 0);
5672 break;
5673 }
5674 }
5675 if (var_count == 0)
5676 end = p;
5677 }
5678
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005679 // no need to parse more when skipping
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005680 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005681 break;
5682
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005683 if (oplen > 0 && *op != '=')
5684 {
5685 type_T *expected = &t_number;
5686 type_T *stacktype;
5687
5688 // TODO: if type is known use float or any operation
5689
5690 if (*op == '.')
5691 expected = &t_string;
5692 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005693 if (need_type(stacktype, expected, -1, cctx, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005694 goto theend;
5695
5696 if (*op == '.')
5697 generate_instr_drop(cctx, ISN_CONCAT, 1);
5698 else
5699 {
5700 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
5701
5702 if (isn == NULL)
5703 goto theend;
5704 switch (*op)
5705 {
5706 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
5707 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
5708 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
5709 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
5710 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
5711 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005712 }
5713 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005714
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005715 if (has_index)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005716 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005717 int r;
5718
5719 // Compile the "idx" in "var[idx]".
5720 if (new_local)
5721 --cctx->ctx_locals.ga_len;
5722 p = skipwhite(var_start + varlen + 1);
5723 r = compile_expr0(&p, cctx);
5724 if (new_local)
5725 ++cctx->ctx_locals.ga_len;
5726 if (r == FAIL)
5727 goto theend;
5728 if (*skipwhite(p) != ']')
5729 {
5730 emsg(_(e_missbrac));
5731 goto theend;
5732 }
Bram Moolenaar2caa1592020-08-01 15:53:19 +02005733 if (type == &t_any)
5734 {
5735 type_T *idx_type = ((type_T **)stack->ga_data)[
5736 stack->ga_len - 1];
5737 // Index on variable of unknown type: guess the type from the
5738 // index type: number is dict, otherwise dict.
5739 // TODO: should do the assignment at runtime
5740 if (idx_type->tt_type == VAR_NUMBER)
5741 type = &t_list_any;
5742 else
5743 type = &t_dict_any;
5744 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005745 if (type->tt_type == VAR_DICT
5746 && may_generate_2STRING(-1, cctx) == FAIL)
5747 goto theend;
5748 if (type->tt_type == VAR_LIST
5749 && ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005750 != VAR_NUMBER)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005751 {
5752 emsg(_(e_number_exp));
5753 goto theend;
5754 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005755
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005756 // Load the dict or list. On the stack we then have:
5757 // - value
5758 // - index
5759 // - variable
5760 generate_loadvar(cctx, dest, name, lvar, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005761
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005762 if (type->tt_type == VAR_LIST)
5763 {
5764 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL)
5765 return FAIL;
5766 }
5767 else if (type->tt_type == VAR_DICT)
5768 {
5769 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL)
5770 return FAIL;
5771 }
5772 else
5773 {
5774 emsg(_(e_listreq));
5775 goto theend;
5776 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005777 }
5778 else
5779 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005780 switch (dest)
5781 {
5782 case dest_option:
5783 generate_STOREOPT(cctx, name + 1, opt_flags);
5784 break;
5785 case dest_global:
5786 // include g: with the name, easier to execute that way
5787 generate_STORE(cctx, ISN_STOREG, 0, name);
5788 break;
5789 case dest_buffer:
5790 // include b: with the name, easier to execute that way
5791 generate_STORE(cctx, ISN_STOREB, 0, name);
5792 break;
5793 case dest_window:
5794 // include w: with the name, easier to execute that way
5795 generate_STORE(cctx, ISN_STOREW, 0, name);
5796 break;
5797 case dest_tab:
5798 // include t: with the name, easier to execute that way
5799 generate_STORE(cctx, ISN_STORET, 0, name);
5800 break;
5801 case dest_env:
5802 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5803 break;
5804 case dest_reg:
5805 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5806 break;
5807 case dest_vimvar:
5808 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5809 break;
5810 case dest_script:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005811 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005812 if (scriptvar_idx < 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005813 {
5814 char_u *name_s = name;
5815
5816 // Include s: in the name for store_var()
5817 if (name[1] != ':')
5818 {
5819 int len = (int)STRLEN(name) + 3;
5820
5821 name_s = alloc(len);
5822 if (name_s == NULL)
5823 name_s = name;
5824 else
5825 vim_snprintf((char *)name_s, len,
5826 "s:%s", name);
5827 }
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005828 generate_OLDSCRIPT(cctx, ISN_STORES, name_s,
5829 scriptvar_sid, type);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005830 if (name_s != name)
5831 vim_free(name_s);
5832 }
5833 else
5834 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005835 scriptvar_sid, scriptvar_idx, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005836 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005837 break;
5838 case dest_local:
5839 if (lvar != NULL)
5840 {
5841 isn_T *isn = ((isn_T *)instr->ga_data)
5842 + instr->ga_len - 1;
5843
5844 // optimization: turn "var = 123" from ISN_PUSHNR +
5845 // ISN_STORE into ISN_STORENR
5846 if (!lvar->lv_from_outer
5847 && instr->ga_len == instr_count + 1
5848 && isn->isn_type == ISN_PUSHNR)
5849 {
5850 varnumber_T val = isn->isn_arg.number;
5851
5852 isn->isn_type = ISN_STORENR;
5853 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
5854 isn->isn_arg.storenr.stnr_val = val;
5855 if (stack->ga_len > 0)
5856 --stack->ga_len;
5857 }
5858 else if (lvar->lv_from_outer)
5859 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005860 NULL);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005861 else
5862 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5863 }
5864 break;
5865 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005866 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005867
5868 if (var_idx + 1 < var_count)
5869 var_start = skipwhite(var_end + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005870 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005871
5872 // for "[var, var] = expr" drop the "expr" value
Bram Moolenaar9af78762020-06-16 11:34:42 +02005873 if (var_count > 0 && !semicolon)
5874 {
5875 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5876 goto theend;
5877 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005878
Bram Moolenaarb2097502020-07-19 17:17:02 +02005879 ret = skipwhite(end);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005880
5881theend:
5882 vim_free(name);
5883 return ret;
5884}
5885
5886/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005887 * Check if "name" can be "unlet".
5888 */
5889 int
5890check_vim9_unlet(char_u *name)
5891{
5892 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
5893 {
5894 semsg(_("E1081: Cannot unlet %s"), name);
5895 return FAIL;
5896 }
5897 return OK;
5898}
5899
5900/*
5901 * Callback passed to ex_unletlock().
5902 */
5903 static int
5904compile_unlet(
5905 lval_T *lvp,
5906 char_u *name_end,
5907 exarg_T *eap,
5908 int deep UNUSED,
5909 void *coookie)
5910{
5911 cctx_T *cctx = coookie;
5912
5913 if (lvp->ll_tv == NULL)
5914 {
5915 char_u *p = lvp->ll_name;
5916 int cc = *name_end;
5917 int ret = OK;
5918
5919 // Normal name. Only supports g:, w:, t: and b: namespaces.
5920 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005921 if (*p == '$')
5922 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
5923 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005924 ret = FAIL;
5925 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005926 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005927
5928 *name_end = cc;
5929 return ret;
5930 }
5931
5932 // TODO: unlet {list}[idx]
5933 // TODO: unlet {dict}[key]
5934 emsg("Sorry, :unlet not fully implemented yet");
5935 return FAIL;
5936}
5937
5938/*
5939 * compile "unlet var", "lock var" and "unlock var"
5940 * "arg" points to "var".
5941 */
5942 static char_u *
5943compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
5944{
5945 char_u *p = arg;
5946
5947 if (eap->cmdidx != CMD_unlet)
5948 {
5949 emsg("Sorry, :lock and unlock not implemented yet");
5950 return NULL;
5951 }
5952
5953 if (*p == '!')
5954 {
5955 p = skipwhite(p + 1);
5956 eap->forceit = TRUE;
5957 }
5958
5959 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
5960 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5961}
5962
5963/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005964 * Compile an :import command.
5965 */
5966 static char_u *
5967compile_import(char_u *arg, cctx_T *cctx)
5968{
Bram Moolenaar1c991142020-07-04 13:15:31 +02005969 return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005970}
5971
5972/*
5973 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
5974 */
5975 static int
5976compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
5977{
5978 garray_T *instr = &cctx->ctx_instr;
5979 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
5980
5981 if (endlabel == NULL)
5982 return FAIL;
5983 endlabel->el_next = *el;
5984 *el = endlabel;
5985 endlabel->el_end_label = instr->ga_len;
5986
5987 generate_JUMP(cctx, when, 0);
5988 return OK;
5989}
5990
5991 static void
5992compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
5993{
5994 garray_T *instr = &cctx->ctx_instr;
5995
5996 while (*el != NULL)
5997 {
5998 endlabel_T *cur = (*el);
5999 isn_T *isn;
6000
6001 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
6002 isn->isn_arg.jump.jump_where = instr->ga_len;
6003 *el = cur->el_next;
6004 vim_free(cur);
6005 }
6006}
6007
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006008 static void
6009compile_free_jump_to_end(endlabel_T **el)
6010{
6011 while (*el != NULL)
6012 {
6013 endlabel_T *cur = (*el);
6014
6015 *el = cur->el_next;
6016 vim_free(cur);
6017 }
6018}
6019
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006020/*
6021 * Create a new scope and set up the generic items.
6022 */
6023 static scope_T *
6024new_scope(cctx_T *cctx, scopetype_T type)
6025{
6026 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
6027
6028 if (scope == NULL)
6029 return NULL;
6030 scope->se_outer = cctx->ctx_scope;
6031 cctx->ctx_scope = scope;
6032 scope->se_type = type;
6033 scope->se_local_count = cctx->ctx_locals.ga_len;
6034 return scope;
6035}
6036
6037/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006038 * Free the current scope and go back to the outer scope.
6039 */
6040 static void
6041drop_scope(cctx_T *cctx)
6042{
6043 scope_T *scope = cctx->ctx_scope;
6044
6045 if (scope == NULL)
6046 {
6047 iemsg("calling drop_scope() without a scope");
6048 return;
6049 }
6050 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006051 switch (scope->se_type)
6052 {
6053 case IF_SCOPE:
6054 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
6055 case FOR_SCOPE:
6056 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
6057 case WHILE_SCOPE:
6058 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
6059 case TRY_SCOPE:
6060 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
6061 case NO_SCOPE:
6062 case BLOCK_SCOPE:
6063 break;
6064 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006065 vim_free(scope);
6066}
6067
6068/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006069 * compile "if expr"
6070 *
6071 * "if expr" Produces instructions:
6072 * EVAL expr Push result of "expr"
6073 * JUMP_IF_FALSE end
6074 * ... body ...
6075 * end:
6076 *
6077 * "if expr | else" Produces instructions:
6078 * EVAL expr Push result of "expr"
6079 * JUMP_IF_FALSE else
6080 * ... body ...
6081 * JUMP_ALWAYS end
6082 * else:
6083 * ... body ...
6084 * end:
6085 *
6086 * "if expr1 | elseif expr2 | else" Produces instructions:
6087 * EVAL expr Push result of "expr"
6088 * JUMP_IF_FALSE elseif
6089 * ... body ...
6090 * JUMP_ALWAYS end
6091 * elseif:
6092 * EVAL expr Push result of "expr"
6093 * JUMP_IF_FALSE else
6094 * ... body ...
6095 * JUMP_ALWAYS end
6096 * else:
6097 * ... body ...
6098 * end:
6099 */
6100 static char_u *
6101compile_if(char_u *arg, cctx_T *cctx)
6102{
6103 char_u *p = arg;
6104 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006105 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006106 scope_T *scope;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006107 skip_T skip_save = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006108 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006109
Bram Moolenaara5565e42020-05-09 15:44:01 +02006110 CLEAR_FIELD(ppconst);
6111 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006112 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006113 clear_ppconst(&ppconst);
6114 return NULL;
6115 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02006116 if (cctx->ctx_skip == SKIP_YES)
6117 clear_ppconst(&ppconst);
6118 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaara5565e42020-05-09 15:44:01 +02006119 {
6120 // The expression results in a constant.
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006121 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006122 clear_ppconst(&ppconst);
6123 }
6124 else
6125 {
6126 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006127 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006128 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006129 return NULL;
6130 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006131
6132 scope = new_scope(cctx, IF_SCOPE);
6133 if (scope == NULL)
6134 return NULL;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006135 scope->se_skip_save = skip_save;
6136 // "is_had_return" will be reset if any block does not end in :return
6137 scope->se_u.se_if.is_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006138
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006139 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006140 {
6141 // "where" is set when ":elseif", "else" or ":endif" is found
6142 scope->se_u.se_if.is_if_label = instr->ga_len;
6143 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
6144 }
6145 else
6146 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006147
6148 return p;
6149}
6150
6151 static char_u *
6152compile_elseif(char_u *arg, cctx_T *cctx)
6153{
6154 char_u *p = arg;
6155 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006156 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006157 isn_T *isn;
6158 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006159 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006160
6161 if (scope == NULL || scope->se_type != IF_SCOPE)
6162 {
6163 emsg(_(e_elseif_without_if));
6164 return NULL;
6165 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01006166 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006167 if (!cctx->ctx_had_return)
6168 scope->se_u.se_if.is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006169
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006170 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006171 {
6172 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006173 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006174 return NULL;
6175 // previous "if" or "elseif" jumps here
6176 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6177 isn->isn_arg.jump.jump_where = instr->ga_len;
6178 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006179
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006180 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02006181 CLEAR_FIELD(ppconst);
6182 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006183 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02006184 clear_ppconst(&ppconst);
6185 return NULL;
6186 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02006187 if (scope->se_skip_save == SKIP_YES)
6188 clear_ppconst(&ppconst);
6189 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaar7f141552020-05-09 17:35:53 +02006190 {
6191 // The expression results in a constant.
6192 // TODO: how about nesting?
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006193 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006194 clear_ppconst(&ppconst);
6195 scope->se_u.se_if.is_if_label = -1;
6196 }
6197 else
6198 {
6199 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006200 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006201 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006202 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006203
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006204 // "where" is set when ":elseif", "else" or ":endif" is found
6205 scope->se_u.se_if.is_if_label = instr->ga_len;
6206 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
6207 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006208
6209 return p;
6210}
6211
6212 static char_u *
6213compile_else(char_u *arg, cctx_T *cctx)
6214{
6215 char_u *p = arg;
6216 garray_T *instr = &cctx->ctx_instr;
6217 isn_T *isn;
6218 scope_T *scope = cctx->ctx_scope;
6219
6220 if (scope == NULL || scope->se_type != IF_SCOPE)
6221 {
6222 emsg(_(e_else_without_if));
6223 return NULL;
6224 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01006225 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006226 if (!cctx->ctx_had_return)
6227 scope->se_u.se_if.is_had_return = FALSE;
6228 scope->se_u.se_if.is_seen_else = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006229
Bram Moolenaarefd88552020-06-18 20:50:10 +02006230 if (scope->se_skip_save != SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006231 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02006232 // jump from previous block to the end, unless the else block is empty
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006233 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006234 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02006235 if (!cctx->ctx_had_return
6236 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
6237 JUMP_ALWAYS, cctx) == FAIL)
6238 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006239 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006240
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006241 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02006242 {
6243 if (scope->se_u.se_if.is_if_label >= 0)
6244 {
6245 // previous "if" or "elseif" jumps here
6246 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6247 isn->isn_arg.jump.jump_where = instr->ga_len;
6248 scope->se_u.se_if.is_if_label = -1;
6249 }
6250 }
6251
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006252 if (cctx->ctx_skip != SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02006253 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
6254 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006255
6256 return p;
6257}
6258
6259 static char_u *
6260compile_endif(char_u *arg, cctx_T *cctx)
6261{
6262 scope_T *scope = cctx->ctx_scope;
6263 ifscope_T *ifscope;
6264 garray_T *instr = &cctx->ctx_instr;
6265 isn_T *isn;
6266
6267 if (scope == NULL || scope->se_type != IF_SCOPE)
6268 {
6269 emsg(_(e_endif_without_if));
6270 return NULL;
6271 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006272 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006273 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006274 if (!cctx->ctx_had_return)
6275 ifscope->is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006276
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006277 if (scope->se_u.se_if.is_if_label >= 0)
6278 {
6279 // previous "if" or "elseif" jumps here
6280 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6281 isn->isn_arg.jump.jump_where = instr->ga_len;
6282 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006283 // Fill in the "end" label in jumps at the end of the blocks.
6284 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006285 cctx->ctx_skip = scope->se_skip_save;
6286
6287 // If all the blocks end in :return and there is an :else then the
6288 // had_return flag is set.
6289 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006290
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006291 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006292 return arg;
6293}
6294
6295/*
6296 * compile "for var in expr"
6297 *
6298 * Produces instructions:
6299 * PUSHNR -1
6300 * STORE loop-idx Set index to -1
6301 * EVAL expr Push result of "expr"
6302 * top: FOR loop-idx, end Increment index, use list on bottom of stack
6303 * - if beyond end, jump to "end"
6304 * - otherwise get item from list and push it
6305 * STORE var Store item in "var"
6306 * ... body ...
6307 * JUMP top Jump back to repeat
6308 * end: DROP Drop the result of "expr"
6309 *
6310 */
6311 static char_u *
6312compile_for(char_u *arg, cctx_T *cctx)
6313{
6314 char_u *p;
6315 size_t varlen;
6316 garray_T *instr = &cctx->ctx_instr;
6317 garray_T *stack = &cctx->ctx_type_stack;
6318 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006319 lvar_T *loop_lvar; // loop iteration variable
6320 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006321 type_T *vartype;
6322
6323 // TODO: list of variables: "for [key, value] in dict"
6324 // parse "var"
6325 for (p = arg; eval_isnamec1(*p); ++p)
6326 ;
6327 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006328 var_lvar = lookup_local(arg, varlen, cctx);
6329 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006330 {
6331 semsg(_("E1023: variable already defined: %s"), arg);
6332 return NULL;
6333 }
6334
6335 // consume "in"
6336 p = skipwhite(p);
6337 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
6338 {
6339 emsg(_(e_missing_in));
6340 return NULL;
6341 }
6342 p = skipwhite(p + 2);
6343
6344
6345 scope = new_scope(cctx, FOR_SCOPE);
6346 if (scope == NULL)
6347 return NULL;
6348
6349 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006350 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
6351 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006352 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006353 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006354 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006355 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006356 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006357
6358 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006359 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
6360 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006361 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006362 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006363 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006364 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006365 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006366
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006367 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006368
6369 // compile "expr", it remains on the stack until "endfor"
6370 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006371 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006372 {
6373 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006374 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006375 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006376
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02006377 // Now that we know the type of "var", check that it is a list, now or at
6378 // runtime.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006379 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02006380 if (need_type(vartype, &t_list_any, -1, cctx, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006381 {
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006382 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006383 return NULL;
6384 }
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02006385 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006386 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006387
6388 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006389 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006390
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006391 generate_FOR(cctx, loop_lvar->lv_idx);
6392 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006393
6394 return arg;
6395}
6396
6397/*
6398 * compile "endfor"
6399 */
6400 static char_u *
6401compile_endfor(char_u *arg, cctx_T *cctx)
6402{
6403 garray_T *instr = &cctx->ctx_instr;
6404 scope_T *scope = cctx->ctx_scope;
6405 forscope_T *forscope;
6406 isn_T *isn;
6407
6408 if (scope == NULL || scope->se_type != FOR_SCOPE)
6409 {
6410 emsg(_(e_for));
6411 return NULL;
6412 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006413 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006414 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006415 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006416
6417 // At end of ":for" scope jump back to the FOR instruction.
6418 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
6419
6420 // Fill in the "end" label in the FOR statement so it can jump here
6421 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
6422 isn->isn_arg.forloop.for_end = instr->ga_len;
6423
6424 // Fill in the "end" label any BREAK statements
6425 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
6426
6427 // Below the ":for" scope drop the "expr" list from the stack.
6428 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
6429 return NULL;
6430
6431 vim_free(scope);
6432
6433 return arg;
6434}
6435
6436/*
6437 * compile "while expr"
6438 *
6439 * Produces instructions:
6440 * top: EVAL expr Push result of "expr"
6441 * JUMP_IF_FALSE end jump if false
6442 * ... body ...
6443 * JUMP top Jump back to repeat
6444 * end:
6445 *
6446 */
6447 static char_u *
6448compile_while(char_u *arg, cctx_T *cctx)
6449{
6450 char_u *p = arg;
6451 garray_T *instr = &cctx->ctx_instr;
6452 scope_T *scope;
6453
6454 scope = new_scope(cctx, WHILE_SCOPE);
6455 if (scope == NULL)
6456 return NULL;
6457
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006458 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006459
6460 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02006461 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006462 return NULL;
6463
6464 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006465 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006466 JUMP_IF_FALSE, cctx) == FAIL)
6467 return FAIL;
6468
6469 return p;
6470}
6471
6472/*
6473 * compile "endwhile"
6474 */
6475 static char_u *
6476compile_endwhile(char_u *arg, cctx_T *cctx)
6477{
6478 scope_T *scope = cctx->ctx_scope;
6479
6480 if (scope == NULL || scope->se_type != WHILE_SCOPE)
6481 {
6482 emsg(_(e_while));
6483 return NULL;
6484 }
6485 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006486 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006487
6488 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006489 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006490
6491 // Fill in the "end" label in the WHILE statement so it can jump here.
6492 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006493 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006494
6495 vim_free(scope);
6496
6497 return arg;
6498}
6499
6500/*
6501 * compile "continue"
6502 */
6503 static char_u *
6504compile_continue(char_u *arg, cctx_T *cctx)
6505{
6506 scope_T *scope = cctx->ctx_scope;
6507
6508 for (;;)
6509 {
6510 if (scope == NULL)
6511 {
6512 emsg(_(e_continue));
6513 return NULL;
6514 }
6515 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
6516 break;
6517 scope = scope->se_outer;
6518 }
6519
6520 // Jump back to the FOR or WHILE instruction.
6521 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006522 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
6523 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006524 return arg;
6525}
6526
6527/*
6528 * compile "break"
6529 */
6530 static char_u *
6531compile_break(char_u *arg, cctx_T *cctx)
6532{
6533 scope_T *scope = cctx->ctx_scope;
6534 endlabel_T **el;
6535
6536 for (;;)
6537 {
6538 if (scope == NULL)
6539 {
6540 emsg(_(e_break));
6541 return NULL;
6542 }
6543 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
6544 break;
6545 scope = scope->se_outer;
6546 }
6547
6548 // Jump to the end of the FOR or WHILE loop.
6549 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006550 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006551 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006552 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006553 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
6554 return FAIL;
6555
6556 return arg;
6557}
6558
6559/*
6560 * compile "{" start of block
6561 */
6562 static char_u *
6563compile_block(char_u *arg, cctx_T *cctx)
6564{
6565 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6566 return NULL;
6567 return skipwhite(arg + 1);
6568}
6569
6570/*
6571 * compile end of block: drop one scope
6572 */
6573 static void
6574compile_endblock(cctx_T *cctx)
6575{
6576 scope_T *scope = cctx->ctx_scope;
6577
6578 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006579 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006580 vim_free(scope);
6581}
6582
6583/*
6584 * compile "try"
6585 * Creates a new scope for the try-endtry, pointing to the first catch and
6586 * finally.
6587 * Creates another scope for the "try" block itself.
6588 * TRY instruction sets up exception handling at runtime.
6589 *
6590 * "try"
6591 * TRY -> catch1, -> finally push trystack entry
6592 * ... try block
6593 * "throw {exception}"
6594 * EVAL {exception}
6595 * THROW create exception
6596 * ... try block
6597 * " catch {expr}"
6598 * JUMP -> finally
6599 * catch1: PUSH exeception
6600 * EVAL {expr}
6601 * MATCH
6602 * JUMP nomatch -> catch2
6603 * CATCH remove exception
6604 * ... catch block
6605 * " catch"
6606 * JUMP -> finally
6607 * catch2: CATCH remove exception
6608 * ... catch block
6609 * " finally"
6610 * finally:
6611 * ... finally block
6612 * " endtry"
6613 * ENDTRY pop trystack entry, may rethrow
6614 */
6615 static char_u *
6616compile_try(char_u *arg, cctx_T *cctx)
6617{
6618 garray_T *instr = &cctx->ctx_instr;
6619 scope_T *try_scope;
6620 scope_T *scope;
6621
6622 // scope that holds the jumps that go to catch/finally/endtry
6623 try_scope = new_scope(cctx, TRY_SCOPE);
6624 if (try_scope == NULL)
6625 return NULL;
6626
6627 // "catch" is set when the first ":catch" is found.
6628 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006629 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006630 if (generate_instr(cctx, ISN_TRY) == NULL)
6631 return NULL;
6632
6633 // scope for the try block itself
6634 scope = new_scope(cctx, BLOCK_SCOPE);
6635 if (scope == NULL)
6636 return NULL;
6637
6638 return arg;
6639}
6640
6641/*
6642 * compile "catch {expr}"
6643 */
6644 static char_u *
6645compile_catch(char_u *arg, cctx_T *cctx UNUSED)
6646{
6647 scope_T *scope = cctx->ctx_scope;
6648 garray_T *instr = &cctx->ctx_instr;
6649 char_u *p;
6650 isn_T *isn;
6651
6652 // end block scope from :try or :catch
6653 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6654 compile_endblock(cctx);
6655 scope = cctx->ctx_scope;
6656
6657 // Error if not in a :try scope
6658 if (scope == NULL || scope->se_type != TRY_SCOPE)
6659 {
6660 emsg(_(e_catch));
6661 return NULL;
6662 }
6663
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006664 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006665 {
6666 emsg(_("E1033: catch unreachable after catch-all"));
6667 return NULL;
6668 }
6669
6670 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006671 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006672 JUMP_ALWAYS, cctx) == FAIL)
6673 return NULL;
6674
6675 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006676 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006677 if (isn->isn_arg.try.try_catch == 0)
6678 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006679 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006680 {
6681 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006682 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006683 isn->isn_arg.jump.jump_where = instr->ga_len;
6684 }
6685
6686 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02006687 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006688 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006689 scope->se_u.se_try.ts_caught_all = TRUE;
6690 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006691 }
6692 else
6693 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006694 char_u *end;
6695 char_u *pat;
6696 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006697 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006698 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006699
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006700 // Push v:exception, push {expr} and MATCH
6701 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
6702
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006703 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006704 if (*end != *p)
6705 {
6706 semsg(_("E1067: Separator mismatch: %s"), p);
6707 vim_free(tofree);
6708 return FAIL;
6709 }
6710 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006711 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006712 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006713 len = (int)(end - tofree);
6714 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006715 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006716 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006717 if (pat == NULL)
6718 return FAIL;
6719 if (generate_PUSHS(cctx, pat) == FAIL)
6720 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006721
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006722 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
6723 return NULL;
6724
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006725 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006726 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
6727 return NULL;
6728 }
6729
6730 if (generate_instr(cctx, ISN_CATCH) == NULL)
6731 return NULL;
6732
6733 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6734 return NULL;
6735 return p;
6736}
6737
6738 static char_u *
6739compile_finally(char_u *arg, cctx_T *cctx)
6740{
6741 scope_T *scope = cctx->ctx_scope;
6742 garray_T *instr = &cctx->ctx_instr;
6743 isn_T *isn;
6744
6745 // end block scope from :try or :catch
6746 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6747 compile_endblock(cctx);
6748 scope = cctx->ctx_scope;
6749
6750 // Error if not in a :try scope
6751 if (scope == NULL || scope->se_type != TRY_SCOPE)
6752 {
6753 emsg(_(e_finally));
6754 return NULL;
6755 }
6756
6757 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006758 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006759 if (isn->isn_arg.try.try_finally != 0)
6760 {
6761 emsg(_(e_finally_dup));
6762 return NULL;
6763 }
6764
6765 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006766 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006767
Bram Moolenaar585fea72020-04-02 22:33:21 +02006768 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006769 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006770 {
6771 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006772 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006773 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaare8593122020-07-18 15:17:02 +02006774 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006775 }
6776
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006777 // TODO: set index in ts_finally_label jumps
6778
6779 return arg;
6780}
6781
6782 static char_u *
6783compile_endtry(char_u *arg, cctx_T *cctx)
6784{
6785 scope_T *scope = cctx->ctx_scope;
6786 garray_T *instr = &cctx->ctx_instr;
6787 isn_T *isn;
6788
6789 // end block scope from :catch or :finally
6790 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6791 compile_endblock(cctx);
6792 scope = cctx->ctx_scope;
6793
6794 // Error if not in a :try scope
6795 if (scope == NULL || scope->se_type != TRY_SCOPE)
6796 {
6797 if (scope == NULL)
6798 emsg(_(e_no_endtry));
6799 else if (scope->se_type == WHILE_SCOPE)
6800 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01006801 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006802 emsg(_(e_endfor));
6803 else
6804 emsg(_(e_endif));
6805 return NULL;
6806 }
6807
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006808 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006809 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
6810 {
6811 emsg(_("E1032: missing :catch or :finally"));
6812 return NULL;
6813 }
6814
6815 // Fill in the "end" label in jumps at the end of the blocks, if not done
6816 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006817 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006818
6819 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaare8593122020-07-18 15:17:02 +02006820 if (isn->isn_arg.try.try_catch == 0)
6821 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006822 if (isn->isn_arg.try.try_finally == 0)
6823 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaare8593122020-07-18 15:17:02 +02006824
6825 if (scope->se_u.se_try.ts_catch_label != 0)
6826 {
6827 // Last catch without match jumps here
6828 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
6829 isn->isn_arg.jump.jump_where = instr->ga_len;
6830 }
6831
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006832 compile_endblock(cctx);
6833
6834 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
6835 return NULL;
6836 return arg;
6837}
6838
6839/*
6840 * compile "throw {expr}"
6841 */
6842 static char_u *
6843compile_throw(char_u *arg, cctx_T *cctx UNUSED)
6844{
6845 char_u *p = skipwhite(arg);
6846
Bram Moolenaara5565e42020-05-09 15:44:01 +02006847 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006848 return NULL;
6849 if (may_generate_2STRING(-1, cctx) == FAIL)
6850 return NULL;
6851 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
6852 return NULL;
6853
6854 return p;
6855}
6856
6857/*
6858 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006859 * compile "echomsg expr"
6860 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01006861 * compile "execute expr"
6862 */
6863 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006864compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006865{
6866 char_u *p = arg;
6867 int count = 0;
6868
6869 for (;;)
6870 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006871 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006872 return NULL;
6873 ++count;
6874 p = skipwhite(p);
6875 if (ends_excmd(*p))
6876 break;
6877 }
6878
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006879 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
6880 generate_ECHO(cctx, cmdidx == CMD_echo, count);
6881 else if (cmdidx == CMD_execute)
6882 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
6883 else if (cmdidx == CMD_echomsg)
6884 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
6885 else
6886 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006887 return p;
6888}
6889
6890/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006891 * A command that is not compiled, execute with legacy code.
6892 */
6893 static char_u *
6894compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
6895{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006896 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006897 int has_expr = FALSE;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006898 char_u *nextcmd = (char_u *)"";
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006899
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006900 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006901 goto theend;
6902
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006903 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006904 {
6905 long argt = excmd_get_argt(eap->cmdidx);
6906 int usefilter = FALSE;
6907
6908 has_expr = argt & (EX_XFILE | EX_EXPAND);
6909
6910 // If the command can be followed by a bar, find the bar and truncate
6911 // it, so that the following command can be compiled.
6912 // The '|' is overwritten with a NUL, it is put back below.
6913 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
6914 && *eap->arg == '!')
6915 // :w !filter or :r !filter or :r! filter
6916 usefilter = TRUE;
6917 if ((argt & EX_TRLBAR) && !usefilter)
6918 {
6919 separate_nextcmd(eap);
6920 if (eap->nextcmd != NULL)
6921 nextcmd = eap->nextcmd;
6922 }
6923 }
6924
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006925 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
6926 {
6927 // expand filename in "syntax include [@group] filename"
6928 has_expr = TRUE;
6929 eap->arg = skipwhite(eap->arg + 7);
6930 if (*eap->arg == '@')
6931 eap->arg = skiptowhite(eap->arg);
6932 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006933
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006934 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006935 {
6936 int count = 0;
6937 char_u *start = skipwhite(line);
6938
6939 // :cmd xxx`=expr1`yyy`=expr2`zzz
6940 // PUSHS ":cmd xxx"
6941 // eval expr1
6942 // PUSHS "yyy"
6943 // eval expr2
6944 // PUSHS "zzz"
6945 // EXECCONCAT 5
6946 for (;;)
6947 {
6948 if (p > start)
6949 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02006950 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006951 ++count;
6952 }
6953 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006954 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006955 return NULL;
6956 may_generate_2STRING(-1, cctx);
6957 ++count;
6958 p = skipwhite(p);
6959 if (*p != '`')
6960 {
6961 emsg(_("E1083: missing backtick"));
6962 return NULL;
6963 }
6964 start = p + 1;
6965
6966 p = (char_u *)strstr((char *)start, "`=");
6967 if (p == NULL)
6968 {
6969 if (*skipwhite(start) != NUL)
6970 {
6971 generate_PUSHS(cctx, vim_strsave(start));
6972 ++count;
6973 }
6974 break;
6975 }
6976 }
6977 generate_EXECCONCAT(cctx, count);
6978 }
6979 else
6980 generate_EXEC(cctx, line);
6981
6982theend:
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006983 if (*nextcmd != NUL)
6984 {
6985 // the parser expects a pointer to the bar, put it back
6986 --nextcmd;
6987 *nextcmd = '|';
6988 }
6989
6990 return nextcmd;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006991}
6992
6993/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02006994 * Add a function to the list of :def functions.
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02006995 * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
Bram Moolenaar09689a02020-05-09 22:50:08 +02006996 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02006997 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02006998add_def_function(ufunc_T *ufunc)
6999{
7000 dfunc_T *dfunc;
7001
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007002 if (def_functions.ga_len == 0)
7003 {
7004 // The first position is not used, so that a zero uf_dfunc_idx means it
7005 // wasn't set.
7006 if (ga_grow(&def_functions, 1) == FAIL)
7007 return FAIL;
7008 ++def_functions.ga_len;
7009 }
7010
Bram Moolenaar09689a02020-05-09 22:50:08 +02007011 // Add the function to "def_functions".
7012 if (ga_grow(&def_functions, 1) == FAIL)
7013 return FAIL;
7014 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
7015 CLEAR_POINTER(dfunc);
7016 dfunc->df_idx = def_functions.ga_len;
7017 ufunc->uf_dfunc_idx = dfunc->df_idx;
7018 dfunc->df_ufunc = ufunc;
7019 ++def_functions.ga_len;
7020 return OK;
7021}
7022
7023/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007024 * After ex_function() has collected all the function lines: parse and compile
7025 * the lines into instructions.
7026 * Adds the function to "def_functions".
7027 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
7028 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007029 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007030 * This can be used recursively through compile_lambda(), which may reallocate
7031 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02007032 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007033 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02007034 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007035compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007036{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007037 char_u *line = NULL;
7038 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007039 char *errormsg = NULL; // error message
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007040 cctx_T cctx;
7041 garray_T *instr;
7042 int called_emsg_before = called_emsg;
7043 int ret = FAIL;
7044 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007045 int do_estack_push;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007046 int emsg_before = called_emsg;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007047 int new_def_function = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007048
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007049 // When using a function that was compiled before: Free old instructions.
7050 // Otherwise add a new entry in "def_functions".
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007051 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007052 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02007053 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7054 + ufunc->uf_dfunc_idx;
Bram Moolenaar09689a02020-05-09 22:50:08 +02007055 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007056 }
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007057 else
7058 {
7059 if (add_def_function(ufunc) == FAIL)
7060 return FAIL;
7061 new_def_function = TRUE;
7062 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007063
Bram Moolenaar985116a2020-07-12 17:31:09 +02007064 ufunc->uf_def_status = UF_COMPILING;
7065
Bram Moolenaara80faa82020-04-12 19:37:17 +02007066 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007067 cctx.ctx_ufunc = ufunc;
7068 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007069 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007070 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
7071 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
7072 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
7073 cctx.ctx_type_list = &ufunc->uf_type_list;
7074 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
7075 instr = &cctx.ctx_instr;
7076
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007077 // Set the context to the function, it may be compiled when called from
7078 // another script. Set the script version to the most modern one.
7079 // The line number will be set in next_line_from_context().
7080 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007081 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
7082
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007083 // Make sure error messages are OK.
7084 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
7085 if (do_estack_push)
7086 estack_push_ufunc(ufunc, 1);
7087
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007088 if (ufunc->uf_def_args.ga_len > 0)
7089 {
7090 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007091 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007092 int i;
7093 char_u *arg;
7094 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007095 int did_set_arg_type = FALSE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007096
7097 // Produce instructions for the default values of optional arguments.
7098 // Store the instruction index in uf_def_arg_idx[] so that we know
7099 // where to start when the function is called, depending on the number
7100 // of arguments.
7101 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
7102 if (ufunc->uf_def_arg_idx == NULL)
7103 goto erret;
7104 for (i = 0; i < count; ++i)
7105 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007106 garray_T *stack = &cctx.ctx_type_stack;
7107 type_T *val_type;
7108 int arg_idx = first_def_arg + i;
7109
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007110 ufunc->uf_def_arg_idx[i] = instr->ga_len;
7111 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02007112 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007113 goto erret;
7114
7115 // If no type specified use the type of the default value.
7116 // Otherwise check that the default value type matches the
7117 // specified type.
7118 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
7119 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007120 {
7121 did_set_arg_type = TRUE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007122 ufunc->uf_arg_types[arg_idx] = val_type;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007123 }
Bram Moolenaare30f64b2020-07-15 19:48:20 +02007124 else if (check_type(ufunc->uf_arg_types[arg_idx], val_type, FALSE)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007125 == FAIL)
7126 {
7127 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
7128 arg_idx + 1);
7129 goto erret;
7130 }
7131
7132 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007133 goto erret;
7134 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007135 ufunc->uf_def_arg_idx[count] = instr->ga_len;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007136
7137 if (did_set_arg_type)
7138 set_function_type(ufunc);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007139 }
7140
7141 /*
7142 * Loop over all the lines of the function and generate instructions.
7143 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007144 for (;;)
7145 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007146 exarg_T ea;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007147 int starts_with_colon = FALSE;
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007148 char_u *cmd;
Bram Moolenaar47e7d702020-07-05 18:18:42 +02007149 int save_msg_scroll = msg_scroll;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007150
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02007151 // Bail out on the first error to avoid a flood of errors and report
7152 // the right line number when inside try/catch.
7153 if (emsg_before != called_emsg)
7154 goto erret;
7155
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007156 if (line != NULL && *line == '|')
7157 // the line continues after a '|'
7158 ++line;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02007159 else if (line != NULL && *skipwhite(line) != NUL
Bram Moolenaar7a092242020-04-16 22:10:49 +02007160 && !(*line == '#' && (line == cctx.ctx_line_start
7161 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007162 {
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02007163 semsg(_(e_trailing_arg), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007164 goto erret;
7165 }
7166 else
7167 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02007168 line = next_line_from_context(&cctx, FALSE);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02007169 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007170 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007171 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007172 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007173 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007174
Bram Moolenaara80faa82020-04-12 19:37:17 +02007175 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007176 ea.cmdlinep = &line;
7177 ea.cmd = skipwhite(line);
7178
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007179 // Some things can be recognized by the first character.
7180 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007181 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007182 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007183 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007184 if (ea.cmd[1] != '{')
7185 {
7186 line = (char_u *)"";
7187 continue;
7188 }
7189 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007190
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007191 case '}':
7192 {
7193 // "}" ends a block scope
7194 scopetype_T stype = cctx.ctx_scope == NULL
7195 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007196
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007197 if (stype == BLOCK_SCOPE)
7198 {
7199 compile_endblock(&cctx);
7200 line = ea.cmd;
7201 }
7202 else
7203 {
7204 emsg(_("E1025: using } outside of a block scope"));
7205 goto erret;
7206 }
7207 if (line != NULL)
7208 line = skipwhite(ea.cmd + 1);
7209 continue;
7210 }
7211
7212 case '{':
7213 // "{" starts a block scope
7214 // "{'a': 1}->func() is something else
7215 if (ends_excmd(*skipwhite(ea.cmd + 1)))
7216 {
7217 line = compile_block(ea.cmd, &cctx);
7218 continue;
7219 }
7220 break;
7221
7222 case ':':
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007223 starts_with_colon = TRUE;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007224 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007225 }
7226
7227 /*
7228 * COMMAND MODIFIERS
7229 */
7230 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
7231 {
7232 if (errormsg != NULL)
7233 goto erret;
7234 // empty line or comment
7235 line = (char_u *)"";
7236 continue;
7237 }
Bram Moolenaar47e7d702020-07-05 18:18:42 +02007238 // TODO: use modifiers in the command
7239 undo_cmdmod(&ea, save_msg_scroll);
Bram Moolenaarb074e8b2020-07-11 13:40:45 +02007240 CLEAR_FIELD(cmdmod);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007241
7242 // Skip ":call" to get to the function name.
7243 if (checkforcmd(&ea.cmd, "call", 3))
7244 ea.cmd = skipwhite(ea.cmd);
7245
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007246 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007247 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007248 char_u *pskip;
7249
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007250 // Assuming the command starts with a variable or function name,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007251 // find what follows.
7252 // Skip over "var.member", "var[idx]" and the like.
7253 // Also "&opt = val", "$ENV = val" and "@r = val".
7254 pskip = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007255 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007256 p = to_name_end(pskip, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02007257 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007258 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007259 char_u *var_end;
7260 int oplen;
7261 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007262
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007263 var_end = find_name_end(pskip, NULL, NULL,
7264 FNE_CHECK_START | FNE_INCL_BR);
7265 oplen = assignment_len(skipwhite(var_end), &heredoc);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007266 if (oplen > 0)
7267 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02007268 size_t len = p - ea.cmd;
7269
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007270 // Recognize an assignment if we recognize the variable
7271 // name:
7272 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01007273 // "local = expr" where "local" is a local var.
7274 // "script = expr" where "script" is a script-local var.
7275 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007276 // "&opt = expr"
7277 // "$ENV = expr"
7278 // "@r = expr"
7279 if (*ea.cmd == '&'
7280 || *ea.cmd == '$'
7281 || *ea.cmd == '@'
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02007282 || ((len) > 2 && ea.cmd[1] == ':')
7283 || lookup_local(ea.cmd, len, &cctx) != NULL
7284 || lookup_arg(ea.cmd, len, NULL, NULL,
7285 NULL, &cctx) == OK
7286 || lookup_script(ea.cmd, len) == OK
7287 || find_imported(ea.cmd, len, &cctx) != NULL)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007288 {
7289 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007290 if (line == NULL || line == ea.cmd)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007291 goto erret;
7292 continue;
7293 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007294 }
7295 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007296
7297 if (*ea.cmd == '[')
7298 {
7299 // [var, var] = expr
7300 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
7301 if (line == NULL)
7302 goto erret;
7303 if (line != ea.cmd)
7304 continue;
7305 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007306 }
7307
7308 /*
7309 * COMMAND after range
Bram Moolenaar3d48e252020-07-15 14:15:52 +02007310 * 'text'->func() should not be confused with 'a mark
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007311 */
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007312 cmd = ea.cmd;
Bram Moolenaar3d48e252020-07-15 14:15:52 +02007313 if (*cmd != '\'')
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007314 {
Bram Moolenaar3d48e252020-07-15 14:15:52 +02007315 ea.cmd = skip_range(ea.cmd, NULL);
7316 if (ea.cmd > cmd && !starts_with_colon)
7317 {
7318 emsg(_(e_colon_required));
7319 goto erret;
7320 }
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007321 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007322 p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007323 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007324 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007325
7326 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
7327 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02007328 if (cctx.ctx_skip == SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007329 {
7330 line += STRLEN(line);
7331 continue;
7332 }
7333
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007334 // Expression or function call.
Bram Moolenaar007f9d62020-07-06 23:04:49 +02007335 if (ea.cmdidx != CMD_eval)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007336 {
Bram Moolenaar007f9d62020-07-06 23:04:49 +02007337 // CMD_let cannot happen, compile_assignment() above is used
7338 iemsg("Command from find_ex_command() not handled");
7339 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007340 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007341 }
7342
7343 p = skipwhite(p);
7344
Bram Moolenaar9b68c822020-06-18 19:31:08 +02007345 if (cctx.ctx_skip == SKIP_YES
Bram Moolenaar7e380032020-06-19 22:35:44 +02007346 && ea.cmdidx != CMD_if
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007347 && ea.cmdidx != CMD_elseif
7348 && ea.cmdidx != CMD_else
7349 && ea.cmdidx != CMD_endif)
7350 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007351 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007352 continue;
7353 }
7354
Bram Moolenaarefd88552020-06-18 20:50:10 +02007355 if (ea.cmdidx != CMD_elseif
7356 && ea.cmdidx != CMD_else
7357 && ea.cmdidx != CMD_endif
7358 && ea.cmdidx != CMD_endfor
7359 && ea.cmdidx != CMD_endwhile
7360 && ea.cmdidx != CMD_catch
7361 && ea.cmdidx != CMD_finally
7362 && ea.cmdidx != CMD_endtry)
7363 {
7364 if (cctx.ctx_had_return)
7365 {
7366 emsg(_("E1095: Unreachable code after :return"));
7367 goto erret;
7368 }
7369 }
7370
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007371 switch (ea.cmdidx)
7372 {
7373 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02007374 ea.arg = p;
7375 line = compile_nested_function(&ea, &cctx);
7376 break;
7377
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007378 case CMD_function:
Bram Moolenaar04b12692020-05-04 23:24:44 +02007379 emsg(_("E1086: Cannot use :function inside :def"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007380 goto erret;
7381
7382 case CMD_return:
7383 line = compile_return(p, set_return_type, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007384 cctx.ctx_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007385 break;
7386
7387 case CMD_let:
7388 case CMD_const:
7389 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007390 if (line == p)
7391 line = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007392 break;
7393
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007394 case CMD_unlet:
7395 case CMD_unlockvar:
7396 case CMD_lockvar:
7397 line = compile_unletlock(p, &ea, &cctx);
7398 break;
7399
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007400 case CMD_import:
7401 line = compile_import(p, &cctx);
7402 break;
7403
7404 case CMD_if:
7405 line = compile_if(p, &cctx);
7406 break;
7407 case CMD_elseif:
7408 line = compile_elseif(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007409 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007410 break;
7411 case CMD_else:
7412 line = compile_else(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007413 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007414 break;
7415 case CMD_endif:
7416 line = compile_endif(p, &cctx);
7417 break;
7418
7419 case CMD_while:
7420 line = compile_while(p, &cctx);
7421 break;
7422 case CMD_endwhile:
7423 line = compile_endwhile(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007424 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007425 break;
7426
7427 case CMD_for:
7428 line = compile_for(p, &cctx);
7429 break;
7430 case CMD_endfor:
7431 line = compile_endfor(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007432 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007433 break;
7434 case CMD_continue:
7435 line = compile_continue(p, &cctx);
7436 break;
7437 case CMD_break:
7438 line = compile_break(p, &cctx);
7439 break;
7440
7441 case CMD_try:
7442 line = compile_try(p, &cctx);
7443 break;
7444 case CMD_catch:
7445 line = compile_catch(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007446 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007447 break;
7448 case CMD_finally:
7449 line = compile_finally(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007450 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007451 break;
7452 case CMD_endtry:
7453 line = compile_endtry(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007454 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007455 break;
7456 case CMD_throw:
7457 line = compile_throw(p, &cctx);
7458 break;
7459
Bram Moolenaar007f9d62020-07-06 23:04:49 +02007460 case CMD_eval:
7461 if (compile_expr0(&p, &cctx) == FAIL)
7462 goto erret;
7463
7464 // drop the return value
7465 generate_instr_drop(&cctx, ISN_DROP, 1);
7466
7467 line = skipwhite(p);
7468 break;
7469
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007470 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007471 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01007472 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007473 case CMD_echomsg:
7474 case CMD_echoerr:
7475 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01007476 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007477
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007478 // TODO: other commands with an expression argument
7479
Bram Moolenaarae616492020-07-28 20:07:27 +02007480 case CMD_append:
7481 case CMD_change:
7482 case CMD_insert:
Bram Moolenaarf5a48012020-08-01 17:00:03 +02007483 case CMD_t:
Bram Moolenaarae616492020-07-28 20:07:27 +02007484 case CMD_xit:
7485 not_in_vim9(&ea);
7486 goto erret;
7487
Bram Moolenaar002262f2020-07-08 17:47:57 +02007488 case CMD_SIZE:
7489 semsg(_("E476: Invalid command: %s"), ea.cmd);
7490 goto erret;
7491
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007492 default:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007493 // Not recognized, execute with do_cmdline_cmd().
7494 ea.arg = p;
7495 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007496 break;
7497 }
7498 if (line == NULL)
7499 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02007500 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007501
7502 if (cctx.ctx_type_stack.ga_len < 0)
7503 {
7504 iemsg("Type stack underflow");
7505 goto erret;
7506 }
7507 }
7508
7509 if (cctx.ctx_scope != NULL)
7510 {
7511 if (cctx.ctx_scope->se_type == IF_SCOPE)
7512 emsg(_(e_endif));
7513 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
7514 emsg(_(e_endwhile));
7515 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
7516 emsg(_(e_endfor));
7517 else
7518 emsg(_("E1026: Missing }"));
7519 goto erret;
7520 }
7521
Bram Moolenaarefd88552020-06-18 20:50:10 +02007522 if (!cctx.ctx_had_return)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007523 {
7524 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
7525 {
7526 emsg(_("E1027: Missing return statement"));
7527 goto erret;
7528 }
7529
7530 // Return zero if there is no return at the end.
7531 generate_PUSHNR(&cctx, 0);
7532 generate_instr(&cctx, ISN_RETURN);
7533 }
7534
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007535 {
7536 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7537 + ufunc->uf_dfunc_idx;
7538 dfunc->df_deleted = FALSE;
7539 dfunc->df_instr = instr->ga_data;
7540 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007541 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02007542 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007543 if (cctx.ctx_outer_used)
7544 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007545 ufunc->uf_def_status = UF_COMPILED;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007546 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007547
7548 ret = OK;
7549
7550erret:
7551 if (ret == FAIL)
7552 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01007553 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007554 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7555 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007556
7557 for (idx = 0; idx < instr->ga_len; ++idx)
7558 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007559 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01007560
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007561 // If using the last entry in the table and it was added above, we
7562 // might as well remove it.
7563 if (!dfunc->df_deleted && new_def_function
Bram Moolenaar45a15082020-05-25 00:28:33 +02007564 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007565 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01007566 --def_functions.ga_len;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007567 ufunc->uf_dfunc_idx = 0;
7568 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007569 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007570
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007571 while (cctx.ctx_scope != NULL)
7572 drop_scope(&cctx);
7573
Bram Moolenaar20431c92020-03-20 18:39:46 +01007574 // Don't execute this function body.
7575 ga_clear_strings(&ufunc->uf_lines);
7576
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007577 if (errormsg != NULL)
7578 emsg(errormsg);
7579 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01007580 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007581 }
7582
7583 current_sctx = save_current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007584 if (do_estack_push)
7585 estack_pop();
7586
Bram Moolenaar20431c92020-03-20 18:39:46 +01007587 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007588 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007589 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02007590 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007591}
7592
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02007593 void
7594set_function_type(ufunc_T *ufunc)
7595{
7596 int varargs = ufunc->uf_va_name != NULL;
7597 int argcount = ufunc->uf_args.ga_len;
7598
7599 // Create a type for the function, with the return type and any
7600 // argument types.
7601 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
7602 // The type is included in "tt_args".
7603 if (argcount > 0 || varargs)
7604 {
7605 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
7606 argcount, &ufunc->uf_type_list);
7607 // Add argument types to the function type.
7608 if (func_type_add_arg_types(ufunc->uf_func_type,
7609 argcount + varargs,
7610 &ufunc->uf_type_list) == FAIL)
7611 return;
7612 ufunc->uf_func_type->tt_argcount = argcount + varargs;
7613 ufunc->uf_func_type->tt_min_argcount =
7614 argcount - ufunc->uf_def_args.ga_len;
7615 if (ufunc->uf_arg_types == NULL)
7616 {
7617 int i;
7618
7619 // lambda does not have argument types.
7620 for (i = 0; i < argcount; ++i)
7621 ufunc->uf_func_type->tt_args[i] = &t_any;
7622 }
7623 else
7624 mch_memmove(ufunc->uf_func_type->tt_args,
7625 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
7626 if (varargs)
7627 {
7628 ufunc->uf_func_type->tt_args[argcount] =
7629 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
7630 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
7631 }
7632 }
7633 else
7634 // No arguments, can use a predefined type.
7635 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
7636 argcount, &ufunc->uf_type_list);
7637}
7638
7639
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007640/*
7641 * Delete an instruction, free what it contains.
7642 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01007643 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007644delete_instr(isn_T *isn)
7645{
7646 switch (isn->isn_type)
7647 {
7648 case ISN_EXEC:
7649 case ISN_LOADENV:
7650 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02007651 case ISN_LOADB:
7652 case ISN_LOADW:
7653 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007654 case ISN_LOADOPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007655 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007656 case ISN_PUSHEXC:
7657 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007658 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007659 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02007660 case ISN_STOREB:
7661 case ISN_STOREW:
7662 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007663 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007664 vim_free(isn->isn_arg.string);
7665 break;
7666
7667 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007668 case ISN_STORES:
7669 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007670 break;
7671
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007672 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02007673 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007674 vim_free(isn->isn_arg.unlet.ul_name);
7675 break;
7676
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007677 case ISN_STOREOPT:
7678 vim_free(isn->isn_arg.storeopt.so_name);
7679 break;
7680
7681 case ISN_PUSHBLOB: // push blob isn_arg.blob
7682 blob_unref(isn->isn_arg.blob);
7683 break;
7684
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007685 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007686#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007687 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007688#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007689 break;
7690
7691 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007692#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007693 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007694#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007695 break;
7696
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007697 case ISN_UCALL:
7698 vim_free(isn->isn_arg.ufunc.cuf_name);
7699 break;
7700
Bram Moolenaar221fcc72020-05-05 19:46:20 +02007701 case ISN_FUNCREF:
7702 {
7703 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7704 + isn->isn_arg.funcref.fr_func;
7705 func_ptr_unref(dfunc->df_ufunc);
7706 }
7707 break;
7708
Bram Moolenaar38ddf332020-07-31 22:05:04 +02007709 case ISN_NEWFUNC:
Bram Moolenaarce658352020-07-31 23:47:12 +02007710 {
7711 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
7712 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
7713
7714 if (ufunc != NULL)
7715 {
7716 // Clear uf_dfunc_idx so that the function is deleted.
7717 clear_def_function(ufunc);
7718 ufunc->uf_dfunc_idx = 0;
7719 func_ptr_unref(ufunc);
7720 }
7721
7722 vim_free(lambda);
7723 vim_free(isn->isn_arg.newfunc.nf_global);
7724 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02007725 break;
7726
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007727 case ISN_2BOOL:
7728 case ISN_2STRING:
7729 case ISN_ADDBLOB:
7730 case ISN_ADDLIST:
7731 case ISN_BCALL:
7732 case ISN_CATCH:
7733 case ISN_CHECKNR:
7734 case ISN_CHECKTYPE:
Bram Moolenaar9af78762020-06-16 11:34:42 +02007735 case ISN_CHECKLEN:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007736 case ISN_COMPAREANY:
7737 case ISN_COMPAREBLOB:
7738 case ISN_COMPAREBOOL:
7739 case ISN_COMPAREDICT:
7740 case ISN_COMPAREFLOAT:
7741 case ISN_COMPAREFUNC:
7742 case ISN_COMPARELIST:
7743 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007744 case ISN_COMPARESPECIAL:
7745 case ISN_COMPARESTRING:
7746 case ISN_CONCAT:
7747 case ISN_DCALL:
Bram Moolenaar389df252020-07-09 21:20:47 +02007748 case ISN_SHUFFLE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007749 case ISN_DROP:
7750 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007751 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007752 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007753 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007754 case ISN_EXECCONCAT:
7755 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007756 case ISN_FOR:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02007757 case ISN_LISTINDEX:
7758 case ISN_STRINDEX:
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007759 case ISN_GETITEM:
Bram Moolenaar9af78762020-06-16 11:34:42 +02007760 case ISN_SLICE:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007761 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007762 case ISN_JUMP:
7763 case ISN_LOAD:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007764 case ISN_LOADBDICT:
7765 case ISN_LOADGDICT:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007766 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007767 case ISN_LOADREG:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007768 case ISN_LOADSCRIPT:
7769 case ISN_LOADTDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007770 case ISN_LOADV:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007771 case ISN_LOADWDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007772 case ISN_NEGATENR:
7773 case ISN_NEWDICT:
7774 case ISN_NEWLIST:
7775 case ISN_OPNR:
7776 case ISN_OPFLOAT:
7777 case ISN_OPANY:
7778 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02007779 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007780 case ISN_PUSHF:
7781 case ISN_PUSHNR:
7782 case ISN_PUSHBOOL:
7783 case ISN_PUSHSPEC:
7784 case ISN_RETURN:
7785 case ISN_STORE:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02007786 case ISN_STOREOUTER:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007787 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007788 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007789 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007790 case ISN_STORESCRIPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007791 case ISN_STOREDICT:
7792 case ISN_STORELIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007793 case ISN_THROW:
7794 case ISN_TRY:
7795 // nothing allocated
7796 break;
7797 }
7798}
7799
7800/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01007801 * Free all instructions for "dfunc".
7802 */
7803 static void
7804delete_def_function_contents(dfunc_T *dfunc)
7805{
7806 int idx;
7807
7808 ga_clear(&dfunc->df_def_args_isn);
7809
7810 if (dfunc->df_instr != NULL)
7811 {
7812 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
7813 delete_instr(dfunc->df_instr + idx);
7814 VIM_CLEAR(dfunc->df_instr);
7815 }
7816
7817 dfunc->df_deleted = TRUE;
7818}
7819
7820/*
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007821 * When a user function is deleted, clear the contents of any associated def
7822 * function. The position in def_functions can be re-used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007823 */
7824 void
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007825clear_def_function(ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007826{
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007827 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007828 {
7829 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7830 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007831
Bram Moolenaar20431c92020-03-20 18:39:46 +01007832 delete_def_function_contents(dfunc);
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007833 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007834 }
7835}
7836
7837#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01007838/*
7839 * Free all functions defined with ":def".
7840 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007841 void
7842free_def_functions(void)
7843{
Bram Moolenaar20431c92020-03-20 18:39:46 +01007844 int idx;
7845
7846 for (idx = 0; idx < def_functions.ga_len; ++idx)
7847 {
7848 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
7849
7850 delete_def_function_contents(dfunc);
7851 }
7852
7853 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007854}
7855#endif
7856
7857
7858#endif // FEAT_EVAL