blob: 01af95e74426ee4d4df407ff34b77d555c0b1c50 [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
26/*
27 * Chain of jump instructions where the end label needs to be set.
28 */
29typedef struct endlabel_S endlabel_T;
30struct endlabel_S {
31 endlabel_T *el_next; // chain end_label locations
32 int el_end_label; // instruction idx where to set end
33};
34
35/*
36 * info specific for the scope of :if / elseif / else
37 */
38typedef struct {
39 int is_if_label; // instruction idx at IF or ELSEIF
40 endlabel_T *is_end_label; // instructions to set end label
41} ifscope_T;
42
43/*
44 * info specific for the scope of :while
45 */
46typedef struct {
47 int ws_top_label; // instruction idx at WHILE
48 endlabel_T *ws_end_label; // instructions to set end
49} whilescope_T;
50
51/*
52 * info specific for the scope of :for
53 */
54typedef struct {
55 int fs_top_label; // instruction idx at FOR
56 endlabel_T *fs_end_label; // break instructions
57} forscope_T;
58
59/*
60 * info specific for the scope of :try
61 */
62typedef struct {
63 int ts_try_label; // instruction idx at TRY
64 endlabel_T *ts_end_label; // jump to :finally or :endtry
65 int ts_catch_label; // instruction idx of last CATCH
66 int ts_caught_all; // "catch" without argument encountered
67} tryscope_T;
68
69typedef enum {
70 NO_SCOPE,
71 IF_SCOPE,
72 WHILE_SCOPE,
73 FOR_SCOPE,
74 TRY_SCOPE,
75 BLOCK_SCOPE
76} scopetype_T;
77
78/*
79 * Info for one scope, pointed to by "ctx_scope".
80 */
81typedef struct scope_S scope_T;
82struct scope_S {
83 scope_T *se_outer; // scope containing this one
84 scopetype_T se_type;
85 int se_local_count; // ctx_locals.ga_len before scope
86 union {
87 ifscope_T se_if;
88 whilescope_T se_while;
89 forscope_T se_for;
90 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +010091 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010092};
93
94/*
95 * Entry for "ctx_locals". Used for arguments and local variables.
96 */
97typedef struct {
98 char_u *lv_name;
99 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200100 int lv_idx; // index of the variable on the stack
101 int lv_from_outer; // when TRUE using ctx_outer scope
102 int lv_const; // when TRUE cannot be assigned to
103 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100104} lvar_T;
105
106/*
107 * Context for compiling lines of Vim script.
108 * Stores info about the local variables and condition stack.
109 */
110struct cctx_S {
111 ufunc_T *ctx_ufunc; // current function
112 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200113 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100114 garray_T ctx_instr; // generated instructions
115
116 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200117 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100118
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200119 int ctx_closure_count; // number of closures created in the
120 // function
121
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100122 garray_T ctx_imports; // imported items
123
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100124 int ctx_skip; // when TRUE skip commands, when FALSE skip
125 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100126 scope_T *ctx_scope; // current scope, NULL at toplevel
127
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200128 cctx_T *ctx_outer; // outer scope for lambda or nested
129 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200130 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200131
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100132 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200133 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100134};
135
136static char e_var_notfound[] = N_("E1001: variable not found: %s");
137static char e_syntax_at[] = N_("E1002: Syntax error at %s");
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +0200138static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100139
Bram Moolenaar20431c92020-03-20 18:39:46 +0100140static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200141static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100142
143/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200144 * Lookup variable "name" in the local scope and return it.
145 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200147 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100148lookup_local(char_u *name, size_t len, cctx_T *cctx)
149{
150 int idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200151 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100153 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200154 return NULL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200155
156 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100157 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
158 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200159 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100160 if (STRNCMP(name, lvar->lv_name, len) == 0
161 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200162 {
163 lvar->lv_from_outer = FALSE;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200164 return lvar;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200165 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100166 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200167
168 // Find local in outer function scope.
169 if (cctx->ctx_outer != NULL)
170 {
171 lvar = lookup_local(name, len, cctx->ctx_outer);
172 if (lvar != NULL)
173 {
174 // TODO: are there situations we should not mark the outer scope as
175 // used?
176 cctx->ctx_outer_used = TRUE;
177 lvar->lv_from_outer = TRUE;
178 return lvar;
179 }
180 }
181
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200182 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100183}
184
185/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200186 * Lookup an argument in the current function and an enclosing function.
187 * Returns the argument index in "idxp"
188 * Returns the argument type in "type"
189 * Sets "gen_load_outer" to TRUE if found in outer scope.
190 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100191 */
192 static int
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200193lookup_arg(
194 char_u *name,
195 size_t len,
196 int *idxp,
197 type_T **type,
198 int *gen_load_outer,
199 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100200{
201 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200202 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100203
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100204 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200205 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100206 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
207 {
208 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
209
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200210 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
211 {
212 if (idxp != NULL)
213 {
214 // Arguments are located above the frame pointer. One further
215 // if there is a vararg argument
216 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
217 + STACK_FRAME_SIZE)
218 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
219
220 if (cctx->ctx_ufunc->uf_arg_types != NULL)
221 *type = cctx->ctx_ufunc->uf_arg_types[idx];
222 else
223 *type = &t_any;
224 }
225 return OK;
226 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100227 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100228
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200229 va_name = cctx->ctx_ufunc->uf_va_name;
230 if (va_name != NULL
231 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
232 {
233 if (idxp != NULL)
234 {
235 // varargs is always the last argument
236 *idxp = -STACK_FRAME_SIZE - 1;
237 *type = cctx->ctx_ufunc->uf_va_type;
238 }
239 return OK;
240 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100241
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200242 if (cctx->ctx_outer != NULL)
243 {
244 // Lookup the name for an argument of the outer function.
245 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
246 == OK)
247 {
248 *gen_load_outer = TRUE;
249 return OK;
250 }
251 }
252
253 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100254}
255
256/*
257 * Lookup a variable in the current script.
258 * Returns OK or FAIL.
259 */
260 static int
261lookup_script(char_u *name, size_t len)
262{
263 int cc;
264 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
265 dictitem_T *di;
266
267 cc = name[len];
268 name[len] = NUL;
269 di = find_var_in_ht(ht, 0, name, TRUE);
270 name[len] = cc;
271 return di == NULL ? FAIL: OK;
272}
273
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100274/*
275 * Check if "p[len]" is already defined, either in script "import_sid" or in
276 * compilation context "cctx".
277 * Return FAIL and give an error if it defined.
278 */
279 int
280check_defined(char_u *p, int len, cctx_T *cctx)
281{
282 if (lookup_script(p, len) == OK
283 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200284 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100285 || find_imported(p, len, cctx) != NULL)))
286 {
287 semsg("E1073: imported name already defined: %s", p);
288 return FAIL;
289 }
290 return OK;
291}
292
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200293/*
294 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
295 * be freed later.
296 */
297 static type_T *
298alloc_type(garray_T *type_gap)
299{
300 type_T *type;
301
302 if (ga_grow(type_gap, 1) == FAIL)
303 return NULL;
304 type = ALLOC_CLEAR_ONE(type_T);
305 if (type != NULL)
306 {
307 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
308 ++type_gap->ga_len;
309 }
310 return type;
311}
312
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100313 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200314get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100315{
316 type_T *type;
317
318 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200319 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100320 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200321 if (member_type->tt_type == VAR_VOID
322 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100323 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100324 if (member_type->tt_type == VAR_BOOL)
325 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100326 if (member_type->tt_type == VAR_NUMBER)
327 return &t_list_number;
328 if (member_type->tt_type == VAR_STRING)
329 return &t_list_string;
330
331 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200332 type = alloc_type(type_gap);
333 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100334 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100335 type->tt_type = VAR_LIST;
336 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200337 type->tt_argcount = 0;
338 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100339 return type;
340}
341
342 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200343get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100344{
345 type_T *type;
346
347 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200348 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100349 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200350 if (member_type->tt_type == VAR_VOID
351 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100352 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100353 if (member_type->tt_type == VAR_BOOL)
354 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100355 if (member_type->tt_type == VAR_NUMBER)
356 return &t_dict_number;
357 if (member_type->tt_type == VAR_STRING)
358 return &t_dict_string;
359
360 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200361 type = alloc_type(type_gap);
362 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100363 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100364 type->tt_type = VAR_DICT;
365 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200366 type->tt_argcount = 0;
367 type->tt_args = NULL;
368 return type;
369}
370
371/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200372 * Allocate a new type for a function.
373 */
374 static type_T *
375alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
376{
377 type_T *type = alloc_type(type_gap);
378
379 if (type == NULL)
380 return &t_any;
381 type->tt_type = VAR_FUNC;
382 type->tt_member = ret_type;
383 type->tt_argcount = argcount;
384 type->tt_args = NULL;
385 return type;
386}
387
388/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200389 * Get a function type, based on the return type "ret_type".
390 * If "argcount" is -1 or 0 a predefined type can be used.
391 * If "argcount" > 0 always create a new type, so that arguments can be added.
392 */
393 static type_T *
394get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
395{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200396 // recognize commonly used types
397 if (argcount <= 0)
398 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200399 if (ret_type == &t_unknown)
400 {
401 // (argcount == 0) is not possible
402 return &t_func_unknown;
403 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200404 if (ret_type == &t_void)
405 {
406 if (argcount == 0)
407 return &t_func_0_void;
408 else
409 return &t_func_void;
410 }
411 if (ret_type == &t_any)
412 {
413 if (argcount == 0)
414 return &t_func_0_any;
415 else
416 return &t_func_any;
417 }
418 if (ret_type == &t_number)
419 {
420 if (argcount == 0)
421 return &t_func_0_number;
422 else
423 return &t_func_number;
424 }
425 if (ret_type == &t_string)
426 {
427 if (argcount == 0)
428 return &t_func_0_string;
429 else
430 return &t_func_string;
431 }
432 }
433
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200434 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100435}
436
Bram Moolenaara8c17702020-04-01 21:17:24 +0200437/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200438 * For a function type, reserve space for "argcount" argument types (including
439 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200440 */
441 static int
442func_type_add_arg_types(
443 type_T *functype,
444 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200445 garray_T *type_gap)
446{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200447 // To make it easy to free the space needed for the argument types, add the
448 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200449 if (ga_grow(type_gap, 1) == FAIL)
450 return FAIL;
451 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
452 if (functype->tt_args == NULL)
453 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200454 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
455 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200456 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200457 return OK;
458}
459
460/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200461 * Return the type_T for a typval. Only for primitive types.
462 */
Bram Moolenaar34db91f2020-06-13 19:00:10 +0200463 type_T *
Bram Moolenaara8c17702020-04-01 21:17:24 +0200464typval2type(typval_T *tv)
465{
466 if (tv->v_type == VAR_NUMBER)
467 return &t_number;
468 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200469 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200470 if (tv->v_type == VAR_STRING)
471 return &t_string;
472 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
473 return &t_list_string;
474 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
475 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200476 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200477}
478
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200479 static void
480type_mismatch(type_T *expected, type_T *actual)
481{
482 char *tofree1, *tofree2;
483
484 semsg(_("E1013: type mismatch, expected %s but got %s"),
485 type_name(expected, &tofree1), type_name(actual, &tofree2));
486 vim_free(tofree1);
487 vim_free(tofree2);
488}
489
490 static void
491arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
492{
493 char *tofree1, *tofree2;
494
495 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
496 argidx,
497 type_name(expected, &tofree1), type_name(actual, &tofree2));
498 vim_free(tofree1);
499 vim_free(tofree2);
500}
501
502/*
503 * Check if the expected and actual types match.
504 * Does not allow for assigning "any" to a specific type.
505 */
Bram Moolenaar34db91f2020-06-13 19:00:10 +0200506 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200507check_type(type_T *expected, type_T *actual, int give_msg)
508{
509 int ret = OK;
510
511 // When expected is "unknown" we accept any actual type.
512 // When expected is "any" we accept any actual type except "void".
513 if (expected->tt_type != VAR_UNKNOWN
514 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
515
516 {
517 if (expected->tt_type != actual->tt_type)
518 {
519 if (give_msg)
520 type_mismatch(expected, actual);
521 return FAIL;
522 }
523 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
524 {
525 // "unknown" is used for an empty list or dict
526 if (actual->tt_member != &t_unknown)
527 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
528 }
529 else if (expected->tt_type == VAR_FUNC)
530 {
531 if (expected->tt_member != &t_unknown)
532 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
533 if (ret == OK && expected->tt_argcount != -1
534 && (actual->tt_argcount < expected->tt_min_argcount
535 || actual->tt_argcount > expected->tt_argcount))
536 ret = FAIL;
537 }
538 if (ret == FAIL && give_msg)
539 type_mismatch(expected, actual);
540 }
541 return ret;
542}
543
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100544/////////////////////////////////////////////////////////////////////
545// Following generate_ functions expect the caller to call ga_grow().
546
Bram Moolenaar080457c2020-03-03 21:53:32 +0100547#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
548#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
549
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100550/*
551 * Generate an instruction without arguments.
552 * Returns a pointer to the new instruction, NULL if failed.
553 */
554 static isn_T *
555generate_instr(cctx_T *cctx, isntype_T isn_type)
556{
557 garray_T *instr = &cctx->ctx_instr;
558 isn_T *isn;
559
Bram Moolenaar080457c2020-03-03 21:53:32 +0100560 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100561 if (ga_grow(instr, 1) == FAIL)
562 return NULL;
563 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
564 isn->isn_type = isn_type;
565 isn->isn_lnum = cctx->ctx_lnum + 1;
566 ++instr->ga_len;
567
568 return isn;
569}
570
571/*
572 * Generate an instruction without arguments.
573 * "drop" will be removed from the stack.
574 * Returns a pointer to the new instruction, NULL if failed.
575 */
576 static isn_T *
577generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
578{
579 garray_T *stack = &cctx->ctx_type_stack;
580
Bram Moolenaar080457c2020-03-03 21:53:32 +0100581 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100582 stack->ga_len -= drop;
583 return generate_instr(cctx, isn_type);
584}
585
586/*
587 * Generate instruction "isn_type" and put "type" on the type stack.
588 */
589 static isn_T *
590generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
591{
592 isn_T *isn;
593 garray_T *stack = &cctx->ctx_type_stack;
594
595 if ((isn = generate_instr(cctx, isn_type)) == NULL)
596 return NULL;
597
598 if (ga_grow(stack, 1) == FAIL)
599 return NULL;
600 ((type_T **)stack->ga_data)[stack->ga_len] = type;
601 ++stack->ga_len;
602
603 return isn;
604}
605
606/*
607 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
608 */
609 static int
610may_generate_2STRING(int offset, cctx_T *cctx)
611{
612 isn_T *isn;
613 garray_T *stack = &cctx->ctx_type_stack;
614 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
615
616 if ((*type)->tt_type == VAR_STRING)
617 return OK;
618 *type = &t_string;
619
620 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
621 return FAIL;
622 isn->isn_arg.number = offset;
623
624 return OK;
625}
626
627 static int
628check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
629{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200630 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100631 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200632 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100633 {
634 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100635 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100636 else
637 semsg(_("E1036: %c requires number or float arguments"), *op);
638 return FAIL;
639 }
640 return OK;
641}
642
643/*
644 * Generate an instruction with two arguments. The instruction depends on the
645 * type of the arguments.
646 */
647 static int
648generate_two_op(cctx_T *cctx, char_u *op)
649{
650 garray_T *stack = &cctx->ctx_type_stack;
651 type_T *type1;
652 type_T *type2;
653 vartype_T vartype;
654 isn_T *isn;
655
Bram Moolenaar080457c2020-03-03 21:53:32 +0100656 RETURN_OK_IF_SKIP(cctx);
657
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100658 // Get the known type of the two items on the stack. If they are matching
659 // use a type-specific instruction. Otherwise fall back to runtime type
660 // checking.
661 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
662 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200663 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100664 if (type1->tt_type == type2->tt_type
665 && (type1->tt_type == VAR_NUMBER
666 || type1->tt_type == VAR_LIST
667#ifdef FEAT_FLOAT
668 || type1->tt_type == VAR_FLOAT
669#endif
670 || type1->tt_type == VAR_BLOB))
671 vartype = type1->tt_type;
672
673 switch (*op)
674 {
675 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200676 && type1->tt_type != VAR_ANY
677 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100678 && check_number_or_float(
679 type1->tt_type, type2->tt_type, op) == FAIL)
680 return FAIL;
681 isn = generate_instr_drop(cctx,
682 vartype == VAR_NUMBER ? ISN_OPNR
683 : vartype == VAR_LIST ? ISN_ADDLIST
684 : vartype == VAR_BLOB ? ISN_ADDBLOB
685#ifdef FEAT_FLOAT
686 : vartype == VAR_FLOAT ? ISN_OPFLOAT
687#endif
688 : ISN_OPANY, 1);
689 if (isn != NULL)
690 isn->isn_arg.op.op_type = EXPR_ADD;
691 break;
692
693 case '-':
694 case '*':
695 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
696 op) == FAIL)
697 return FAIL;
698 if (vartype == VAR_NUMBER)
699 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
700#ifdef FEAT_FLOAT
701 else if (vartype == VAR_FLOAT)
702 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
703#endif
704 else
705 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
706 if (isn != NULL)
707 isn->isn_arg.op.op_type = *op == '*'
708 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
709 break;
710
Bram Moolenaar4c683752020-04-05 21:38:23 +0200711 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100712 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200713 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100714 && type2->tt_type != VAR_NUMBER))
715 {
716 emsg(_("E1035: % requires number arguments"));
717 return FAIL;
718 }
719 isn = generate_instr_drop(cctx,
720 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
721 if (isn != NULL)
722 isn->isn_arg.op.op_type = EXPR_REM;
723 break;
724 }
725
726 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200727 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100728 {
729 type_T *type = &t_any;
730
731#ifdef FEAT_FLOAT
732 // float+number and number+float results in float
733 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
734 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
735 type = &t_float;
736#endif
737 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
738 }
739
740 return OK;
741}
742
743/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200744 * Get the instruction to use for comparing "type1" with "type2"
745 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200747 static isntype_T
748get_compare_isn(exptype_T exptype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100749{
750 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100751
Bram Moolenaar4c683752020-04-05 21:38:23 +0200752 if (type1 == VAR_UNKNOWN)
753 type1 = VAR_ANY;
754 if (type2 == VAR_UNKNOWN)
755 type2 = VAR_ANY;
756
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100757 if (type1 == type2)
758 {
759 switch (type1)
760 {
761 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
762 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
763 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
764 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
765 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
766 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
767 case VAR_LIST: isntype = ISN_COMPARELIST; break;
768 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
769 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100770 default: isntype = ISN_COMPAREANY; break;
771 }
772 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200773 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100774 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
775 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
776 isntype = ISN_COMPAREANY;
777
778 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
779 && (isntype == ISN_COMPAREBOOL
780 || isntype == ISN_COMPARESPECIAL
781 || isntype == ISN_COMPARENR
782 || isntype == ISN_COMPAREFLOAT))
783 {
784 semsg(_("E1037: Cannot use \"%s\" with %s"),
785 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200786 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100787 }
788 if (isntype == ISN_DROP
789 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
790 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
791 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
792 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
793 && exptype != EXPR_IS && exptype != EXPR_ISNOT
794 && (type1 == VAR_BLOB || type2 == VAR_BLOB
795 || type1 == VAR_LIST || type2 == VAR_LIST))))
796 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100797 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100798 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200799 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100800 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200801 return isntype;
802}
803
804/*
805 * Generate an ISN_COMPARE* instruction with a boolean result.
806 */
807 static int
808generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
809{
810 isntype_T isntype;
811 isn_T *isn;
812 garray_T *stack = &cctx->ctx_type_stack;
813 vartype_T type1;
814 vartype_T type2;
815
816 RETURN_OK_IF_SKIP(cctx);
817
818 // Get the known type of the two items on the stack. If they are matching
819 // use a type-specific instruction. Otherwise fall back to runtime type
820 // checking.
821 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
822 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
823 isntype = get_compare_isn(exptype, type1, type2);
824 if (isntype == ISN_DROP)
825 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100826
827 if ((isn = generate_instr(cctx, isntype)) == NULL)
828 return FAIL;
829 isn->isn_arg.op.op_type = exptype;
830 isn->isn_arg.op.op_ic = ic;
831
832 // takes two arguments, puts one bool back
833 if (stack->ga_len >= 2)
834 {
835 --stack->ga_len;
836 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
837 }
838
839 return OK;
840}
841
842/*
843 * Generate an ISN_2BOOL instruction.
844 */
845 static int
846generate_2BOOL(cctx_T *cctx, int invert)
847{
848 isn_T *isn;
849 garray_T *stack = &cctx->ctx_type_stack;
850
Bram Moolenaar080457c2020-03-03 21:53:32 +0100851 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100852 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
853 return FAIL;
854 isn->isn_arg.number = invert;
855
856 // type becomes bool
857 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
858
859 return OK;
860}
861
862 static int
863generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
864{
865 isn_T *isn;
866 garray_T *stack = &cctx->ctx_type_stack;
867
Bram Moolenaar080457c2020-03-03 21:53:32 +0100868 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100869 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
870 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +0200871 // TODO: whole type, e.g. for a function also arg and return types
872 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100873 isn->isn_arg.type.ct_off = offset;
874
875 // type becomes vartype
Bram Moolenaar5adc55c2020-05-02 23:12:58 +0200876 ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100877
878 return OK;
879}
880
881/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200882 * Check that
883 * - "actual" is "expected" type or
884 * - "actual" is a type that can be "expected" type: add a runtime check; or
885 * - return FAIL.
886 */
887 static int
888need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
889{
890 if (check_type(expected, actual, FALSE) == OK)
891 return OK;
892 if (actual->tt_type != VAR_ANY
893 && actual->tt_type != VAR_UNKNOWN
894 && !(actual->tt_type == VAR_FUNC
895 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
896 {
897 type_mismatch(expected, actual);
898 return FAIL;
899 }
900 generate_TYPECHECK(cctx, expected, offset);
901 return OK;
902}
903
904/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100905 * Generate an ISN_PUSHNR instruction.
906 */
907 static int
908generate_PUSHNR(cctx_T *cctx, varnumber_T number)
909{
910 isn_T *isn;
911
Bram Moolenaar080457c2020-03-03 21:53:32 +0100912 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100913 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
914 return FAIL;
915 isn->isn_arg.number = number;
916
917 return OK;
918}
919
920/*
921 * Generate an ISN_PUSHBOOL instruction.
922 */
923 static int
924generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
925{
926 isn_T *isn;
927
Bram Moolenaar080457c2020-03-03 21:53:32 +0100928 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100929 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
930 return FAIL;
931 isn->isn_arg.number = number;
932
933 return OK;
934}
935
936/*
937 * Generate an ISN_PUSHSPEC instruction.
938 */
939 static int
940generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
941{
942 isn_T *isn;
943
Bram Moolenaar080457c2020-03-03 21:53:32 +0100944 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100945 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
946 return FAIL;
947 isn->isn_arg.number = number;
948
949 return OK;
950}
951
952#ifdef FEAT_FLOAT
953/*
954 * Generate an ISN_PUSHF instruction.
955 */
956 static int
957generate_PUSHF(cctx_T *cctx, float_T fnumber)
958{
959 isn_T *isn;
960
Bram Moolenaar080457c2020-03-03 21:53:32 +0100961 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100962 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
963 return FAIL;
964 isn->isn_arg.fnumber = fnumber;
965
966 return OK;
967}
968#endif
969
970/*
971 * Generate an ISN_PUSHS instruction.
972 * Consumes "str".
973 */
974 static int
975generate_PUSHS(cctx_T *cctx, char_u *str)
976{
977 isn_T *isn;
978
Bram Moolenaar080457c2020-03-03 21:53:32 +0100979 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100980 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
981 return FAIL;
982 isn->isn_arg.string = str;
983
984 return OK;
985}
986
987/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100988 * Generate an ISN_PUSHCHANNEL instruction.
989 * Consumes "channel".
990 */
991 static int
992generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
993{
994 isn_T *isn;
995
Bram Moolenaar080457c2020-03-03 21:53:32 +0100996 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100997 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
998 return FAIL;
999 isn->isn_arg.channel = channel;
1000
1001 return OK;
1002}
1003
1004/*
1005 * Generate an ISN_PUSHJOB instruction.
1006 * Consumes "job".
1007 */
1008 static int
1009generate_PUSHJOB(cctx_T *cctx, job_T *job)
1010{
1011 isn_T *isn;
1012
Bram Moolenaar080457c2020-03-03 21:53:32 +01001013 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001014 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001015 return FAIL;
1016 isn->isn_arg.job = job;
1017
1018 return OK;
1019}
1020
1021/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001022 * Generate an ISN_PUSHBLOB instruction.
1023 * Consumes "blob".
1024 */
1025 static int
1026generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1027{
1028 isn_T *isn;
1029
Bram Moolenaar080457c2020-03-03 21:53:32 +01001030 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001031 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1032 return FAIL;
1033 isn->isn_arg.blob = blob;
1034
1035 return OK;
1036}
1037
1038/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001039 * Generate an ISN_PUSHFUNC instruction with name "name".
1040 * Consumes "name".
1041 */
1042 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001043generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001044{
1045 isn_T *isn;
1046
Bram Moolenaar080457c2020-03-03 21:53:32 +01001047 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001048 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001049 return FAIL;
1050 isn->isn_arg.string = name;
1051
1052 return OK;
1053}
1054
1055/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001056 * Generate an ISN_STORE instruction.
1057 */
1058 static int
1059generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1060{
1061 isn_T *isn;
1062
Bram Moolenaar080457c2020-03-03 21:53:32 +01001063 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001064 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1065 return FAIL;
1066 if (name != NULL)
1067 isn->isn_arg.string = vim_strsave(name);
1068 else
1069 isn->isn_arg.number = idx;
1070
1071 return OK;
1072}
1073
1074/*
1075 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1076 */
1077 static int
1078generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1079{
1080 isn_T *isn;
1081
Bram Moolenaar080457c2020-03-03 21:53:32 +01001082 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1084 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001085 isn->isn_arg.storenr.stnr_idx = idx;
1086 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001087
1088 return OK;
1089}
1090
1091/*
1092 * Generate an ISN_STOREOPT instruction
1093 */
1094 static int
1095generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1096{
1097 isn_T *isn;
1098
Bram Moolenaar080457c2020-03-03 21:53:32 +01001099 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001100 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
1101 return FAIL;
1102 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1103 isn->isn_arg.storeopt.so_flags = opt_flags;
1104
1105 return OK;
1106}
1107
1108/*
1109 * Generate an ISN_LOAD or similar instruction.
1110 */
1111 static int
1112generate_LOAD(
1113 cctx_T *cctx,
1114 isntype_T isn_type,
1115 int idx,
1116 char_u *name,
1117 type_T *type)
1118{
1119 isn_T *isn;
1120
Bram Moolenaar080457c2020-03-03 21:53:32 +01001121 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001122 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1123 return FAIL;
1124 if (name != NULL)
1125 isn->isn_arg.string = vim_strsave(name);
1126 else
1127 isn->isn_arg.number = idx;
1128
1129 return OK;
1130}
1131
1132/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001133 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001134 */
1135 static int
1136generate_LOADV(
1137 cctx_T *cctx,
1138 char_u *name,
1139 int error)
1140{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001141 int di_flags;
1142 int vidx = find_vim_var(name, &di_flags);
1143 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001144
Bram Moolenaar080457c2020-03-03 21:53:32 +01001145 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001146 if (vidx < 0)
1147 {
1148 if (error)
1149 semsg(_(e_var_notfound), name);
1150 return FAIL;
1151 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001152 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001153
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001154 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001155}
1156
1157/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001158 * Generate an ISN_UNLET instruction.
1159 */
1160 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001161generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001162{
1163 isn_T *isn;
1164
1165 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001166 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001167 return FAIL;
1168 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1169 isn->isn_arg.unlet.ul_forceit = forceit;
1170
1171 return OK;
1172}
1173
1174/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001175 * Generate an ISN_LOADS instruction.
1176 */
1177 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001178generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001179 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001180 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001181 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001182 int sid,
1183 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001184{
1185 isn_T *isn;
1186
Bram Moolenaar080457c2020-03-03 21:53:32 +01001187 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001188 if (isn_type == ISN_LOADS)
1189 isn = generate_instr_type(cctx, isn_type, type);
1190 else
1191 isn = generate_instr_drop(cctx, isn_type, 1);
1192 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001193 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001194 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1195 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001196
1197 return OK;
1198}
1199
1200/*
1201 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1202 */
1203 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001204generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001205 cctx_T *cctx,
1206 isntype_T isn_type,
1207 int sid,
1208 int idx,
1209 type_T *type)
1210{
1211 isn_T *isn;
1212
Bram Moolenaar080457c2020-03-03 21:53:32 +01001213 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001214 if (isn_type == ISN_LOADSCRIPT)
1215 isn = generate_instr_type(cctx, isn_type, type);
1216 else
1217 isn = generate_instr_drop(cctx, isn_type, 1);
1218 if (isn == NULL)
1219 return FAIL;
1220 isn->isn_arg.script.script_sid = sid;
1221 isn->isn_arg.script.script_idx = idx;
1222 return OK;
1223}
1224
1225/*
1226 * Generate an ISN_NEWLIST instruction.
1227 */
1228 static int
1229generate_NEWLIST(cctx_T *cctx, int count)
1230{
1231 isn_T *isn;
1232 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233 type_T *type;
1234 type_T *member;
1235
Bram Moolenaar080457c2020-03-03 21:53:32 +01001236 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001237 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1238 return FAIL;
1239 isn->isn_arg.number = count;
1240
1241 // drop the value types
1242 stack->ga_len -= count;
1243
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001244 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001245 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001246 if (count > 0)
1247 member = ((type_T **)stack->ga_data)[stack->ga_len];
1248 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001249 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001250 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001251
1252 // add the list type to the type stack
1253 if (ga_grow(stack, 1) == FAIL)
1254 return FAIL;
1255 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1256 ++stack->ga_len;
1257
1258 return OK;
1259}
1260
1261/*
1262 * Generate an ISN_NEWDICT instruction.
1263 */
1264 static int
1265generate_NEWDICT(cctx_T *cctx, int count)
1266{
1267 isn_T *isn;
1268 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001269 type_T *type;
1270 type_T *member;
1271
Bram Moolenaar080457c2020-03-03 21:53:32 +01001272 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001273 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1274 return FAIL;
1275 isn->isn_arg.number = count;
1276
1277 // drop the key and value types
1278 stack->ga_len -= 2 * count;
1279
Bram Moolenaar436472f2020-02-20 22:54:43 +01001280 // Use the first value type for the list member type. Use "void" for an
1281 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001282 if (count > 0)
1283 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1284 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001285 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001286 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001287
1288 // add the dict type to the type stack
1289 if (ga_grow(stack, 1) == FAIL)
1290 return FAIL;
1291 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1292 ++stack->ga_len;
1293
1294 return OK;
1295}
1296
1297/*
1298 * Generate an ISN_FUNCREF instruction.
1299 */
1300 static int
1301generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1302{
1303 isn_T *isn;
1304 garray_T *stack = &cctx->ctx_type_stack;
1305
Bram Moolenaar080457c2020-03-03 21:53:32 +01001306 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001307 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1308 return FAIL;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001309 isn->isn_arg.funcref.fr_func = dfunc_idx;
1310 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001311
1312 if (ga_grow(stack, 1) == FAIL)
1313 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001314 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001315 // TODO: argument and return types
1316 ++stack->ga_len;
1317
1318 return OK;
1319}
1320
1321/*
1322 * Generate an ISN_JUMP instruction.
1323 */
1324 static int
1325generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1326{
1327 isn_T *isn;
1328 garray_T *stack = &cctx->ctx_type_stack;
1329
Bram Moolenaar080457c2020-03-03 21:53:32 +01001330 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001331 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1332 return FAIL;
1333 isn->isn_arg.jump.jump_when = when;
1334 isn->isn_arg.jump.jump_where = where;
1335
1336 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1337 --stack->ga_len;
1338
1339 return OK;
1340}
1341
1342 static int
1343generate_FOR(cctx_T *cctx, int loop_idx)
1344{
1345 isn_T *isn;
1346 garray_T *stack = &cctx->ctx_type_stack;
1347
Bram Moolenaar080457c2020-03-03 21:53:32 +01001348 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001349 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1350 return FAIL;
1351 isn->isn_arg.forloop.for_idx = loop_idx;
1352
1353 if (ga_grow(stack, 1) == FAIL)
1354 return FAIL;
1355 // type doesn't matter, will be stored next
1356 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1357 ++stack->ga_len;
1358
1359 return OK;
1360}
1361
1362/*
1363 * Generate an ISN_BCALL instruction.
1364 * Return FAIL if the number of arguments is wrong.
1365 */
1366 static int
1367generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1368{
1369 isn_T *isn;
1370 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001371 type_T *argtypes[MAX_FUNC_ARGS];
1372 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001373
Bram Moolenaar080457c2020-03-03 21:53:32 +01001374 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001375 if (check_internal_func(func_idx, argcount) == FAIL)
1376 return FAIL;
1377
1378 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1379 return FAIL;
1380 isn->isn_arg.bfunc.cbf_idx = func_idx;
1381 isn->isn_arg.bfunc.cbf_argcount = argcount;
1382
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001383 for (i = 0; i < argcount; ++i)
1384 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1385
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001386 stack->ga_len -= argcount; // drop the arguments
1387 if (ga_grow(stack, 1) == FAIL)
1388 return FAIL;
1389 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001390 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391 ++stack->ga_len; // add return value
1392
1393 return OK;
1394}
1395
1396/*
1397 * Generate an ISN_DCALL or ISN_UCALL instruction.
1398 * Return FAIL if the number of arguments is wrong.
1399 */
1400 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001401generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001402{
1403 isn_T *isn;
1404 garray_T *stack = &cctx->ctx_type_stack;
1405 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001406 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001407
Bram Moolenaar080457c2020-03-03 21:53:32 +01001408 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001409 if (argcount > regular_args && !has_varargs(ufunc))
1410 {
1411 semsg(_(e_toomanyarg), ufunc->uf_name);
1412 return FAIL;
1413 }
1414 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1415 {
1416 semsg(_(e_toofewarg), ufunc->uf_name);
1417 return FAIL;
1418 }
1419
Bram Moolenaar822ba242020-05-24 23:00:18 +02001420 if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001421 {
1422 int i;
1423
1424 for (i = 0; i < argcount; ++i)
1425 {
1426 type_T *expected;
1427 type_T *actual;
1428
1429 if (i < regular_args)
1430 {
1431 if (ufunc->uf_arg_types == NULL)
1432 continue;
1433 expected = ufunc->uf_arg_types[i];
1434 }
1435 else
1436 expected = ufunc->uf_va_type->tt_member;
1437 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001438 if (need_type(actual, expected, -argcount + i, cctx) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001439 {
1440 arg_type_mismatch(expected, actual, i + 1);
1441 return FAIL;
1442 }
1443 }
Bram Moolenaar822ba242020-05-24 23:00:18 +02001444 if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED)
Bram Moolenaar45a15082020-05-25 00:28:33 +02001445 if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02001446 return FAIL;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001447 }
1448
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001449 if ((isn = generate_instr(cctx,
Bram Moolenaar822ba242020-05-24 23:00:18 +02001450 ufunc->uf_dfunc_idx != UF_NOT_COMPILED ? ISN_DCALL
1451 : ISN_UCALL)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001452 return FAIL;
Bram Moolenaar822ba242020-05-24 23:00:18 +02001453 if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001454 {
1455 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1456 isn->isn_arg.dfunc.cdf_argcount = argcount;
1457 }
1458 else
1459 {
1460 // A user function may be deleted and redefined later, can't use the
1461 // ufunc pointer, need to look it up again at runtime.
1462 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1463 isn->isn_arg.ufunc.cuf_argcount = argcount;
1464 }
1465
1466 stack->ga_len -= argcount; // drop the arguments
1467 if (ga_grow(stack, 1) == FAIL)
1468 return FAIL;
1469 // add return value
1470 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1471 ++stack->ga_len;
1472
1473 return OK;
1474}
1475
1476/*
1477 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1478 */
1479 static int
1480generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1481{
1482 isn_T *isn;
1483 garray_T *stack = &cctx->ctx_type_stack;
1484
Bram Moolenaar080457c2020-03-03 21:53:32 +01001485 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001486 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1487 return FAIL;
1488 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1489 isn->isn_arg.ufunc.cuf_argcount = argcount;
1490
1491 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001492 if (ga_grow(stack, 1) == FAIL)
1493 return FAIL;
1494 // add return value
1495 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1496 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001497
1498 return OK;
1499}
1500
1501/*
1502 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001503 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001504 */
1505 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001506generate_PCALL(
1507 cctx_T *cctx,
1508 int argcount,
1509 char_u *name,
1510 type_T *type,
1511 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001512{
1513 isn_T *isn;
1514 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001515 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001516
Bram Moolenaar080457c2020-03-03 21:53:32 +01001517 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001518
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001519 if (type->tt_type == VAR_ANY)
1520 ret_type = &t_any;
1521 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001522 {
1523 if (type->tt_argcount != -1)
1524 {
1525 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1526
1527 if (argcount < type->tt_min_argcount - varargs)
1528 {
1529 semsg(_(e_toofewarg), "[reference]");
1530 return FAIL;
1531 }
1532 if (!varargs && argcount > type->tt_argcount)
1533 {
1534 semsg(_(e_toomanyarg), "[reference]");
1535 return FAIL;
1536 }
1537 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001538 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001539 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001540 else
1541 {
1542 semsg(_("E1085: Not a callable type: %s"), name);
1543 return FAIL;
1544 }
1545
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001546 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1547 return FAIL;
1548 isn->isn_arg.pfunc.cpf_top = at_top;
1549 isn->isn_arg.pfunc.cpf_argcount = argcount;
1550
1551 stack->ga_len -= argcount; // drop the arguments
1552
1553 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001554 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001555
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001556 // If partial is above the arguments it must be cleared and replaced with
1557 // the return value.
1558 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1559 return FAIL;
1560
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001561 return OK;
1562}
1563
1564/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001565 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001566 */
1567 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001568generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001569{
1570 isn_T *isn;
1571 garray_T *stack = &cctx->ctx_type_stack;
1572 type_T *type;
1573
Bram Moolenaar080457c2020-03-03 21:53:32 +01001574 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001575 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001576 return FAIL;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001577 isn->isn_arg.string = vim_strnsave(name, len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001578
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001579 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001580 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001581 if (type->tt_type != VAR_DICT && type != &t_any)
1582 {
1583 emsg(_(e_dictreq));
1584 return FAIL;
1585 }
1586 // change dict type to dict member type
1587 if (type->tt_type == VAR_DICT)
1588 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001589
1590 return OK;
1591}
1592
1593/*
1594 * Generate an ISN_ECHO instruction.
1595 */
1596 static int
1597generate_ECHO(cctx_T *cctx, int with_white, int count)
1598{
1599 isn_T *isn;
1600
Bram Moolenaar080457c2020-03-03 21:53:32 +01001601 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001602 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1603 return FAIL;
1604 isn->isn_arg.echo.echo_with_white = with_white;
1605 isn->isn_arg.echo.echo_count = count;
1606
1607 return OK;
1608}
1609
Bram Moolenaarad39c092020-02-26 18:23:43 +01001610/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001611 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001612 */
1613 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001614generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001615{
1616 isn_T *isn;
1617
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001618 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001619 return FAIL;
1620 isn->isn_arg.number = count;
1621
1622 return OK;
1623}
1624
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001625 static int
1626generate_EXEC(cctx_T *cctx, char_u *line)
1627{
1628 isn_T *isn;
1629
Bram Moolenaar080457c2020-03-03 21:53:32 +01001630 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001631 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1632 return FAIL;
1633 isn->isn_arg.string = vim_strsave(line);
1634 return OK;
1635}
1636
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001637 static int
1638generate_EXECCONCAT(cctx_T *cctx, int count)
1639{
1640 isn_T *isn;
1641
1642 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1643 return FAIL;
1644 isn->isn_arg.number = count;
1645 return OK;
1646}
1647
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001648/*
1649 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001650 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001651 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001652 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001653reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1654{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001655 lvar_T *lvar;
1656
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001657 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001658 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001659 emsg_namelen(_(e_used_as_arg), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001660 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001661 }
1662
1663 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001664 return NULL;
1665 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001666
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001667 // Every local variable uses the next entry on the stack. We could re-use
1668 // the last ones when leaving a scope, but then variables used in a closure
1669 // might get overwritten. To keep things simple do not re-use stack
1670 // entries. This is less efficient, but memory is cheap these days.
1671 lvar->lv_idx = cctx->ctx_locals_count++;
1672
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001673 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001674 lvar->lv_const = isConst;
1675 lvar->lv_type = type;
1676
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001677 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001678}
1679
1680/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001681 * Remove local variables above "new_top".
1682 */
1683 static void
1684unwind_locals(cctx_T *cctx, int new_top)
1685{
1686 if (cctx->ctx_locals.ga_len > new_top)
1687 {
1688 int idx;
1689 lvar_T *lvar;
1690
1691 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1692 {
1693 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1694 vim_free(lvar->lv_name);
1695 }
1696 }
1697 cctx->ctx_locals.ga_len = new_top;
1698}
1699
1700/*
1701 * Free all local variables.
1702 */
1703 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001704free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001705{
1706 unwind_locals(cctx, 0);
1707 ga_clear(&cctx->ctx_locals);
1708}
1709
1710/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001711 * Skip over a type definition and return a pointer to just after it.
1712 */
1713 char_u *
1714skip_type(char_u *start)
1715{
1716 char_u *p = start;
1717
1718 while (ASCII_ISALNUM(*p) || *p == '_')
1719 ++p;
1720
1721 // Skip over "<type>"; this is permissive about white space.
1722 if (*skipwhite(p) == '<')
1723 {
1724 p = skipwhite(p);
1725 p = skip_type(skipwhite(p + 1));
1726 p = skipwhite(p);
1727 if (*p == '>')
1728 ++p;
1729 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001730 else if (*p == '(' && STRNCMP("func", start, 4) == 0)
1731 {
1732 // handle func(args): type
1733 ++p;
1734 while (*p != ')' && *p != NUL)
1735 {
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001736 char_u *sp = p;
1737
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001738 p = skip_type(p);
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001739 if (p == sp)
1740 return p; // syntax error
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001741 if (*p == ',')
1742 p = skipwhite(p + 1);
1743 }
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001744 if (*p == ')')
1745 {
1746 if (p[1] == ':')
1747 p = skip_type(skipwhite(p + 2));
1748 else
1749 p = skipwhite(p + 1);
1750 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001751 }
1752
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001753 return p;
1754}
1755
1756/*
1757 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001758 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001759 * Returns NULL in case of failure.
1760 */
1761 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001762parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001763{
1764 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001765 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001766
1767 if (**arg != '<')
1768 {
1769 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001770 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001771 else
1772 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001773 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001774 }
1775 *arg = skipwhite(*arg + 1);
1776
Bram Moolenaard77a8522020-04-03 21:59:57 +02001777 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001778
1779 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001780 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001781 {
1782 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001783 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001784 }
1785 ++*arg;
1786
1787 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001788 return get_list_type(member_type, type_gap);
1789 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001790}
1791
1792/*
1793 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001794 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001795 */
1796 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001797parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001798{
1799 char_u *p = *arg;
1800 size_t len;
1801
1802 // skip over the first word
1803 while (ASCII_ISALNUM(*p) || *p == '_')
1804 ++p;
1805 len = p - *arg;
1806
1807 switch (**arg)
1808 {
1809 case 'a':
1810 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1811 {
1812 *arg += len;
1813 return &t_any;
1814 }
1815 break;
1816 case 'b':
1817 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1818 {
1819 *arg += len;
1820 return &t_bool;
1821 }
1822 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1823 {
1824 *arg += len;
1825 return &t_blob;
1826 }
1827 break;
1828 case 'c':
1829 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1830 {
1831 *arg += len;
1832 return &t_channel;
1833 }
1834 break;
1835 case 'd':
1836 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1837 {
1838 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001839 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001840 }
1841 break;
1842 case 'f':
1843 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1844 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001845#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001846 *arg += len;
1847 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001848#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001849 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001850 return &t_any;
1851#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001852 }
1853 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1854 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001855 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001856 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001857 int argcount = -1;
1858 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001859 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001860 type_T *arg_type[MAX_FUNC_ARGS + 1];
1861
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001862 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001863 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001864 if (**arg == '(')
1865 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001866 // "func" may or may not return a value, "func()" does
1867 // not return a value.
1868 ret_type = &t_void;
1869
Bram Moolenaard77a8522020-04-03 21:59:57 +02001870 p = ++*arg;
1871 argcount = 0;
1872 while (*p != NUL && *p != ')')
1873 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001874 if (*p == '?')
1875 {
1876 if (first_optional == -1)
1877 first_optional = argcount;
1878 ++p;
1879 }
1880 else if (first_optional != -1)
1881 {
1882 emsg(_("E1007: mandatory argument after optional argument"));
1883 return &t_any;
1884 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001885 else if (STRNCMP(p, "...", 3) == 0)
1886 {
1887 flags |= TTFLAG_VARARGS;
1888 p += 3;
1889 }
1890
1891 arg_type[argcount++] = parse_type(&p, type_gap);
1892
1893 // Nothing comes after "...{type}".
1894 if (flags & TTFLAG_VARARGS)
1895 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001896
Bram Moolenaard77a8522020-04-03 21:59:57 +02001897 if (*p != ',' && *skipwhite(p) == ',')
1898 {
1899 semsg(_(e_no_white_before), ",");
1900 return &t_any;
1901 }
1902 if (*p == ',')
1903 {
1904 ++p;
1905 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001906 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001907 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001908 return &t_any;
1909 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001910 }
1911 p = skipwhite(p);
1912 if (argcount == MAX_FUNC_ARGS)
1913 {
1914 emsg(_("E740: Too many argument types"));
1915 return &t_any;
1916 }
1917 }
1918
1919 p = skipwhite(p);
1920 if (*p != ')')
1921 {
1922 emsg(_(e_missing_close));
1923 return &t_any;
1924 }
1925 *arg = p + 1;
1926 }
1927 if (**arg == ':')
1928 {
1929 // parse return type
1930 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001931 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001932 semsg(_(e_white_after), ":");
1933 *arg = skipwhite(*arg);
1934 ret_type = parse_type(arg, type_gap);
1935 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001936 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001937 type = get_func_type(ret_type, argcount, type_gap);
1938 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001939 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001940 type = alloc_func_type(ret_type, argcount, type_gap);
1941 type->tt_flags = flags;
1942 if (argcount > 0)
1943 {
1944 type->tt_argcount = argcount;
1945 type->tt_min_argcount = first_optional == -1
1946 ? argcount : first_optional;
1947 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001948 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001949 return &t_any;
1950 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001951 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001952 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001953 }
1954 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001955 }
1956 break;
1957 case 'j':
1958 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1959 {
1960 *arg += len;
1961 return &t_job;
1962 }
1963 break;
1964 case 'l':
1965 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1966 {
1967 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001968 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001969 }
1970 break;
1971 case 'n':
1972 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1973 {
1974 *arg += len;
1975 return &t_number;
1976 }
1977 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001978 case 's':
1979 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1980 {
1981 *arg += len;
1982 return &t_string;
1983 }
1984 break;
1985 case 'v':
1986 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1987 {
1988 *arg += len;
1989 return &t_void;
1990 }
1991 break;
1992 }
1993
1994 semsg(_("E1010: Type not recognized: %s"), *arg);
1995 return &t_any;
1996}
1997
1998/*
1999 * Check if "type1" and "type2" are exactly the same.
2000 */
2001 static int
2002equal_type(type_T *type1, type_T *type2)
2003{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002004 int i;
2005
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002006 if (type1->tt_type != type2->tt_type)
2007 return FALSE;
2008 switch (type1->tt_type)
2009 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002010 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02002011 case VAR_ANY:
2012 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002013 case VAR_SPECIAL:
2014 case VAR_BOOL:
2015 case VAR_NUMBER:
2016 case VAR_FLOAT:
2017 case VAR_STRING:
2018 case VAR_BLOB:
2019 case VAR_JOB:
2020 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002021 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002022 case VAR_LIST:
2023 case VAR_DICT:
2024 return equal_type(type1->tt_member, type2->tt_member);
2025 case VAR_FUNC:
2026 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002027 if (!equal_type(type1->tt_member, type2->tt_member)
2028 || type1->tt_argcount != type2->tt_argcount)
2029 return FALSE;
2030 if (type1->tt_argcount < 0
2031 || type1->tt_args == NULL || type2->tt_args == NULL)
2032 return TRUE;
2033 for (i = 0; i < type1->tt_argcount; ++i)
2034 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
2035 return FALSE;
2036 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002037 }
2038 return TRUE;
2039}
2040
2041/*
2042 * Find the common type of "type1" and "type2" and put it in "dest".
2043 * "type2" and "dest" may be the same.
2044 */
2045 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02002046common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002047{
2048 if (equal_type(type1, type2))
2049 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002050 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002051 return;
2052 }
2053
2054 if (type1->tt_type == type2->tt_type)
2055 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002056 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
2057 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002058 type_T *common;
2059
Bram Moolenaard77a8522020-04-03 21:59:57 +02002060 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002061 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002062 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002063 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002064 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002065 return;
2066 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002067 if (type1->tt_type == VAR_FUNC)
2068 {
2069 type_T *common;
2070
2071 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
2072 if (type1->tt_argcount == type2->tt_argcount
2073 && type1->tt_argcount >= 0)
2074 {
2075 int argcount = type1->tt_argcount;
2076 int i;
2077
2078 *dest = alloc_func_type(common, argcount, type_gap);
2079 if (type1->tt_args != NULL && type2->tt_args != NULL)
2080 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02002081 if (func_type_add_arg_types(*dest, argcount,
2082 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002083 for (i = 0; i < argcount; ++i)
2084 common_type(type1->tt_args[i], type2->tt_args[i],
2085 &(*dest)->tt_args[i], type_gap);
2086 }
2087 }
2088 else
2089 *dest = alloc_func_type(common, -1, type_gap);
2090 return;
2091 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002092 }
2093
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002094 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002095}
2096
2097 char *
2098vartype_name(vartype_T type)
2099{
2100 switch (type)
2101 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002102 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002103 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002104 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002105 case VAR_SPECIAL: return "special";
2106 case VAR_BOOL: return "bool";
2107 case VAR_NUMBER: return "number";
2108 case VAR_FLOAT: return "float";
2109 case VAR_STRING: return "string";
2110 case VAR_BLOB: return "blob";
2111 case VAR_JOB: return "job";
2112 case VAR_CHANNEL: return "channel";
2113 case VAR_LIST: return "list";
2114 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002115
2116 case VAR_FUNC:
2117 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002118 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02002119 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002120}
2121
2122/*
2123 * Return the name of a type.
2124 * The result may be in allocated memory, in which case "tofree" is set.
2125 */
2126 char *
2127type_name(type_T *type, char **tofree)
2128{
2129 char *name = vartype_name(type->tt_type);
2130
2131 *tofree = NULL;
2132 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
2133 {
2134 char *member_free;
2135 char *member_name = type_name(type->tt_member, &member_free);
2136 size_t len;
2137
2138 len = STRLEN(name) + STRLEN(member_name) + 3;
2139 *tofree = alloc(len);
2140 if (*tofree != NULL)
2141 {
2142 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
2143 vim_free(member_free);
2144 return *tofree;
2145 }
2146 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002147 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002148 {
2149 garray_T ga;
2150 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002151 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002152
2153 ga_init2(&ga, 1, 100);
2154 if (ga_grow(&ga, 20) == FAIL)
2155 return "[unknown]";
2156 *tofree = ga.ga_data;
2157 STRCPY(ga.ga_data, "func(");
2158 ga.ga_len += 5;
2159
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002160 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002161 {
2162 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002163 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002164 int len;
2165
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002166 if (type->tt_args == NULL)
2167 arg_type = "[unknown]";
2168 else
2169 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002170 if (i > 0)
2171 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002172 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002173 ga.ga_len += 2;
2174 }
2175 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002176 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002177 {
2178 vim_free(arg_free);
2179 return "[unknown]";
2180 }
2181 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002182 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002183 {
2184 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
2185 ga.ga_len += 3;
2186 }
2187 else if (i >= type->tt_min_argcount)
2188 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002189 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002190 ga.ga_len += len;
2191 vim_free(arg_free);
2192 }
2193
2194 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002195 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002196 else
2197 {
2198 char *ret_free;
2199 char *ret_name = type_name(type->tt_member, &ret_free);
2200 int len;
2201
2202 len = (int)STRLEN(ret_name) + 4;
2203 if (ga_grow(&ga, len) == FAIL)
2204 {
2205 vim_free(ret_free);
2206 return "[unknown]";
2207 }
2208 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002209 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
2210 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002211 vim_free(ret_free);
2212 }
2213 return ga.ga_data;
2214 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002215
2216 return name;
2217}
2218
2219/*
2220 * Find "name" in script-local items of script "sid".
2221 * Returns the index in "sn_var_vals" if found.
2222 * If found but not in "sn_var_vals" returns -1.
2223 * If not found returns -2.
2224 */
2225 int
2226get_script_item_idx(int sid, char_u *name, int check_writable)
2227{
2228 hashtab_T *ht;
2229 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002230 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 int idx;
2232
2233 // First look the name up in the hashtable.
2234 if (sid <= 0 || sid > script_items.ga_len)
2235 return -1;
2236 ht = &SCRIPT_VARS(sid);
2237 di = find_var_in_ht(ht, 0, name, TRUE);
2238 if (di == NULL)
2239 return -2;
2240
2241 // Now find the svar_T index in sn_var_vals.
2242 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2243 {
2244 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2245
2246 if (sv->sv_tv == &di->di_tv)
2247 {
2248 if (check_writable && sv->sv_const)
2249 semsg(_(e_readonlyvar), name);
2250 return idx;
2251 }
2252 }
2253 return -1;
2254}
2255
2256/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02002257 * Find "name" in imported items of the current script or in "cctx" if not
2258 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002259 */
2260 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002261find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002262{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002263 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002264 int idx;
2265
2266 if (cctx != NULL)
2267 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2268 {
2269 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2270 + idx;
2271
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002272 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2273 : STRLEN(import->imp_name) == len
2274 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002275 return import;
2276 }
2277
2278 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2279 {
2280 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2281
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002282 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2283 : STRLEN(import->imp_name) == len
2284 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002285 return import;
2286 }
2287 return NULL;
2288}
2289
2290/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002291 * Free all imported variables.
2292 */
2293 static void
2294free_imported(cctx_T *cctx)
2295{
2296 int idx;
2297
2298 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2299 {
2300 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2301
2302 vim_free(import->imp_name);
2303 }
2304 ga_clear(&cctx->ctx_imports);
2305}
2306
2307/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002308 * Get the next line of the function from "cctx".
2309 * Returns NULL when at the end.
2310 */
2311 static char_u *
2312next_line_from_context(cctx_T *cctx)
2313{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002314 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002315
2316 do
2317 {
2318 ++cctx->ctx_lnum;
2319 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002320 {
2321 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002322 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002323 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002324 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002325 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02002326 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002327 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002328 return line;
2329}
2330
2331/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002332 * Return TRUE if "p" points at a "#" but not at "#{".
2333 */
2334 static int
2335comment_start(char_u *p)
2336{
2337 return p[0] == '#' && p[1] != '{';
2338}
2339
2340/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002341 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002342 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002343 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2344 */
2345 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002346may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002347{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002348 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002349 {
2350 char_u *next = next_line_from_context(cctx);
2351
2352 if (next == NULL)
2353 return FAIL;
2354 *arg = skipwhite(next);
2355 }
2356 return OK;
2357}
2358
Bram Moolenaara5565e42020-05-09 15:44:01 +02002359// Structure passed between the compile_expr* functions to keep track of
2360// constants that have been parsed but for which no code was produced yet. If
2361// possible expressions on these constants are applied at compile time. If
2362// that is not possible, the code to push the constants needs to be generated
2363// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002364// Using 50 should be more than enough of 5 levels of ().
2365#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002366typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002367 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002368 int pp_used; // active entries in pp_tv[]
2369} ppconst_T;
2370
Bram Moolenaar1c747212020-05-09 18:28:34 +02002371static int compile_expr0(char_u **arg, cctx_T *cctx);
2372static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2373
Bram Moolenaara5565e42020-05-09 15:44:01 +02002374/*
2375 * Generate a PUSH instruction for "tv".
2376 * "tv" will be consumed or cleared.
2377 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2378 */
2379 static int
2380generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2381{
2382 if (tv != NULL)
2383 {
2384 switch (tv->v_type)
2385 {
2386 case VAR_UNKNOWN:
2387 break;
2388 case VAR_BOOL:
2389 generate_PUSHBOOL(cctx, tv->vval.v_number);
2390 break;
2391 case VAR_SPECIAL:
2392 generate_PUSHSPEC(cctx, tv->vval.v_number);
2393 break;
2394 case VAR_NUMBER:
2395 generate_PUSHNR(cctx, tv->vval.v_number);
2396 break;
2397#ifdef FEAT_FLOAT
2398 case VAR_FLOAT:
2399 generate_PUSHF(cctx, tv->vval.v_float);
2400 break;
2401#endif
2402 case VAR_BLOB:
2403 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2404 tv->vval.v_blob = NULL;
2405 break;
2406 case VAR_STRING:
2407 generate_PUSHS(cctx, tv->vval.v_string);
2408 tv->vval.v_string = NULL;
2409 break;
2410 default:
2411 iemsg("constant type not supported");
2412 clear_tv(tv);
2413 return FAIL;
2414 }
2415 tv->v_type = VAR_UNKNOWN;
2416 }
2417 return OK;
2418}
2419
2420/*
2421 * Generate code for any ppconst entries.
2422 */
2423 static int
2424generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2425{
2426 int i;
2427 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002428 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002429
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002430 cctx->ctx_skip = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002431 for (i = 0; i < ppconst->pp_used; ++i)
2432 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2433 ret = FAIL;
2434 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002435 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002436 return ret;
2437}
2438
2439/*
2440 * Clear ppconst constants. Used when failing.
2441 */
2442 static void
2443clear_ppconst(ppconst_T *ppconst)
2444{
2445 int i;
2446
2447 for (i = 0; i < ppconst->pp_used; ++i)
2448 clear_tv(&ppconst->pp_tv[i]);
2449 ppconst->pp_used = 0;
2450}
2451
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002452/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002453 * Generate an instruction to load script-local variable "name", without the
2454 * leading "s:".
2455 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002456 */
2457 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002458compile_load_scriptvar(
2459 cctx_T *cctx,
2460 char_u *name, // variable NUL terminated
2461 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002462 char_u **end, // end of variable
2463 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002464{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002465 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002466 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2467 imported_T *import;
2468
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002469 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002470 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002471 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002472 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2473 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002474 }
2475 if (idx >= 0)
2476 {
2477 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2478
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002479 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002480 current_sctx.sc_sid, idx, sv->sv_type);
2481 return OK;
2482 }
2483
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002484 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002485 if (import != NULL)
2486 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002487 if (import->imp_all)
2488 {
2489 char_u *p = skipwhite(*end);
2490 int name_len;
2491 ufunc_T *ufunc;
2492 type_T *type;
2493
2494 // Used "import * as Name", need to lookup the member.
2495 if (*p != '.')
2496 {
2497 semsg(_("E1060: expected dot after name: %s"), start);
2498 return FAIL;
2499 }
2500 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002501 if (VIM_ISWHITE(*p))
2502 {
2503 emsg(_("E1074: no white space allowed after dot"));
2504 return FAIL;
2505 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002506
2507 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2508 // TODO: what if it is a function?
2509 if (idx < 0)
2510 return FAIL;
2511 *end = p;
2512
2513 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2514 import->imp_sid,
2515 idx,
2516 type);
2517 }
2518 else
2519 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002520 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002521 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2522 import->imp_sid,
2523 import->imp_var_vals_idx,
2524 import->imp_type);
2525 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002526 return OK;
2527 }
2528
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002529 if (error)
2530 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002531 return FAIL;
2532}
2533
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002534 static int
2535generate_funcref(cctx_T *cctx, char_u *name)
2536{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002537 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002538
2539 if (ufunc == NULL)
2540 return FAIL;
2541
2542 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2543}
2544
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002545/*
2546 * Compile a variable name into a load instruction.
2547 * "end" points to just after the name.
2548 * When "error" is FALSE do not give an error when not found.
2549 */
2550 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002551compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002552{
2553 type_T *type;
2554 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002555 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002556 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002557 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002558
2559 if (*(*arg + 1) == ':')
2560 {
2561 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002562 if (end <= *arg + 2)
2563 name = vim_strsave((char_u *)"[empty]");
2564 else
2565 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002566 if (name == NULL)
2567 return FAIL;
2568
2569 if (**arg == 'v')
2570 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002571 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002572 }
2573 else if (**arg == 'g')
2574 {
2575 // Global variables can be defined later, thus we don't check if it
2576 // exists, give error at runtime.
2577 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2578 }
2579 else if (**arg == 's')
2580 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002581 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002582 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002583 else if (**arg == 'b')
2584 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002585 // Buffer-local variables can be defined later, thus we don't check
2586 // if it exists, give error at runtime.
2587 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002588 }
2589 else if (**arg == 'w')
2590 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002591 // Window-local variables can be defined later, thus we don't check
2592 // if it exists, give error at runtime.
2593 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002594 }
2595 else if (**arg == 't')
2596 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002597 // Tabpage-local variables can be defined later, thus we don't
2598 // check if it exists, give error at runtime.
2599 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002600 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002601 else
2602 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002603 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002604 goto theend;
2605 }
2606 }
2607 else
2608 {
2609 size_t len = end - *arg;
2610 int idx;
2611 int gen_load = FALSE;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002612 int gen_load_outer = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002613
2614 name = vim_strnsave(*arg, end - *arg);
2615 if (name == NULL)
2616 return FAIL;
2617
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002618 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002619 {
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002620 if (!gen_load_outer)
2621 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002622 }
2623 else
2624 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002625 lvar_T *lvar = lookup_local(*arg, len, cctx);
2626
2627 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002628 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002629 type = lvar->lv_type;
2630 idx = lvar->lv_idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002631 if (lvar->lv_from_outer)
2632 gen_load_outer = TRUE;
2633 else
2634 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002635 }
2636 else
2637 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02002638 // "var" can be script-local even without using "s:" if it
2639 // already exists.
2640 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2641 == SCRIPT_VERSION_VIM9
2642 || lookup_script(*arg, len) == OK)
2643 res = compile_load_scriptvar(cctx, name, *arg, &end,
2644 FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002645
Bram Moolenaara5565e42020-05-09 15:44:01 +02002646 // When the name starts with an uppercase letter or "x:" it
2647 // can be a user defined function.
2648 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2649 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002650 }
2651 }
2652 if (gen_load)
2653 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002654 if (gen_load_outer)
2655 res = generate_LOAD(cctx, ISN_LOADOUTER, idx, NULL, type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002656 }
2657
2658 *arg = end;
2659
2660theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002661 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002662 semsg(_(e_var_notfound), name);
2663 vim_free(name);
2664 return res;
2665}
2666
2667/*
2668 * Compile the argument expressions.
2669 * "arg" points to just after the "(" and is advanced to after the ")"
2670 */
2671 static int
2672compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2673{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002674 char_u *p = *arg;
2675 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002676
Bram Moolenaare6085c52020-04-12 20:19:16 +02002677 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002678 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002679 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002680 {
2681 p = next_line_from_context(cctx);
2682 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002683 goto failret;
2684 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002685 p = skipwhite(p);
2686 }
2687 if (*p == ')')
2688 {
2689 *arg = p + 1;
2690 return OK;
2691 }
2692
Bram Moolenaara5565e42020-05-09 15:44:01 +02002693 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002694 return FAIL;
2695 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002696
2697 if (*p != ',' && *skipwhite(p) == ',')
2698 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002699 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002700 p = skipwhite(p);
2701 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002702 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002703 {
2704 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002705 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002706 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002707 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002708 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002709 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002710 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002711failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002712 emsg(_(e_missing_close));
2713 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002714}
2715
2716/*
2717 * Compile a function call: name(arg1, arg2)
2718 * "arg" points to "name", "arg + varlen" to the "(".
2719 * "argcount_init" is 1 for "value->method()"
2720 * Instructions:
2721 * EVAL arg1
2722 * EVAL arg2
2723 * BCALL / DCALL / UCALL
2724 */
2725 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02002726compile_call(
2727 char_u **arg,
2728 size_t varlen,
2729 cctx_T *cctx,
2730 ppconst_T *ppconst,
2731 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002732{
2733 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002734 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002735 int argcount = argcount_init;
2736 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002737 char_u fname_buf[FLEN_FIXED + 1];
2738 char_u *tofree = NULL;
2739 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002740 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002741 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002742
Bram Moolenaara5565e42020-05-09 15:44:01 +02002743 // we can evaluate "has('name')" at compile time
2744 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
2745 {
2746 char_u *s = skipwhite(*arg + varlen + 1);
2747 typval_T argvars[2];
2748
2749 argvars[0].v_type = VAR_UNKNOWN;
2750 if (*s == '"')
2751 (void)get_string_tv(&s, &argvars[0], TRUE);
2752 else if (*s == '\'')
2753 (void)get_lit_string_tv(&s, &argvars[0], TRUE);
2754 s = skipwhite(s);
2755 if (*s == ')' && argvars[0].v_type == VAR_STRING)
2756 {
2757 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
2758
2759 *arg = s + 1;
2760 argvars[1].v_type = VAR_UNKNOWN;
2761 tv->v_type = VAR_NUMBER;
2762 tv->vval.v_number = 0;
2763 f_has(argvars, tv);
2764 clear_tv(&argvars[0]);
2765 ++ppconst->pp_used;
2766 return OK;
2767 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002768 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002769 }
2770
2771 if (generate_ppconst(cctx, ppconst) == FAIL)
2772 return FAIL;
2773
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002774 if (varlen >= sizeof(namebuf))
2775 {
2776 semsg(_("E1011: name too long: %s"), name);
2777 return FAIL;
2778 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002779 vim_strncpy(namebuf, *arg, varlen);
2780 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002781
2782 *arg = skipwhite(*arg + varlen + 1);
2783 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002784 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002785
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002786 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002787 {
2788 int idx;
2789
2790 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002791 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002792 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002793 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002794 else
2795 semsg(_(e_unknownfunc), namebuf);
2796 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002797 }
2798
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002799 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002800 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002801 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002802 {
2803 res = generate_CALL(cctx, ufunc, argcount);
2804 goto theend;
2805 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002806
2807 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002808 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002809 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002810 if (STRNCMP(namebuf, "g:", 2) != 0
2811 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002812 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002813 garray_T *stack = &cctx->ctx_type_stack;
2814 type_T *type;
2815
2816 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2817 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002818 goto theend;
2819 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002820
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002821 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002822 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002823 if (STRNCMP(namebuf, "g:", 2) == 0)
2824 res = generate_UCALL(cctx, name, argcount);
2825 else
2826 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002827
2828theend:
2829 vim_free(tofree);
2830 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002831}
2832
2833// like NAMESPACE_CHAR but with 'a' and 'l'.
2834#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2835
2836/*
2837 * Find the end of a variable or function name. Unlike find_name_end() this
2838 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002839 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002840 * Return a pointer to just after the name. Equal to "arg" if there is no
2841 * valid name.
2842 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002843 static char_u *
2844to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002845{
2846 char_u *p;
2847
2848 // Quick check for valid starting character.
2849 if (!eval_isnamec1(*arg))
2850 return arg;
2851
2852 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2853 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2854 // and can be used in slice "[n:]".
2855 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002856 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002857 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2858 break;
2859 return p;
2860}
2861
2862/*
2863 * Like to_name_end() but also skip over a list or dict constant.
2864 */
2865 char_u *
2866to_name_const_end(char_u *arg)
2867{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002868 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002869 typval_T rettv;
2870
2871 if (p == arg && *arg == '[')
2872 {
2873
2874 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar32e35112020-05-14 22:41:15 +02002875 if (get_list_tv(&p, &rettv, 0, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002876 p = arg;
2877 }
2878 else if (p == arg && *arg == '#' && arg[1] == '{')
2879 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002880 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002881 ++p;
Bram Moolenaar32e35112020-05-14 22:41:15 +02002882 if (eval_dict(&p, &rettv, 0, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002883 p = arg;
2884 }
2885 else if (p == arg && *arg == '{')
2886 {
2887 int ret = get_lambda_tv(&p, &rettv, FALSE);
2888
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002889 // Can be "{x -> ret}()".
2890 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002891 if (ret == NOTDONE)
Bram Moolenaar32e35112020-05-14 22:41:15 +02002892 ret = eval_dict(&p, &rettv, 0, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002893 if (ret != OK)
2894 p = arg;
2895 }
2896
2897 return p;
2898}
2899
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002900/*
2901 * parse a list: [expr, expr]
2902 * "*arg" points to the '['.
2903 */
2904 static int
2905compile_list(char_u **arg, cctx_T *cctx)
2906{
2907 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002908 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002909 int count = 0;
2910
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002911 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002912 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002913 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002914 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002915 p = next_line_from_context(cctx);
2916 if (p == NULL)
2917 {
2918 semsg(_(e_list_end), *arg);
2919 return FAIL;
2920 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002921 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002922 p = skipwhite(p);
2923 }
2924 if (*p == ']')
2925 {
2926 ++p;
2927 // Allow for following comment, after at least one space.
2928 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2929 p += STRLEN(p);
2930 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002931 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02002932 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002933 break;
2934 ++count;
2935 if (*p == ',')
2936 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002937 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002938 p = skipwhite(p);
2939 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002940 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002941
2942 generate_NEWLIST(cctx, count);
2943 return OK;
2944}
2945
2946/*
2947 * parse a lambda: {arg, arg -> expr}
2948 * "*arg" points to the '{'.
2949 */
2950 static int
2951compile_lambda(char_u **arg, cctx_T *cctx)
2952{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002953 typval_T rettv;
2954 ufunc_T *ufunc;
2955
2956 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002957 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002958 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002959
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002960 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002961 ++ufunc->uf_refcount;
2962 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002963 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002964
2965 // The function will have one line: "return {expr}".
2966 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002967 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002968
2969 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002970 return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002971 return FAIL;
2972}
2973
2974/*
2975 * Compile a lamda call: expr->{lambda}(args)
2976 * "arg" points to the "{".
2977 */
2978 static int
2979compile_lambda_call(char_u **arg, cctx_T *cctx)
2980{
2981 ufunc_T *ufunc;
2982 typval_T rettv;
2983 int argcount = 1;
2984 int ret = FAIL;
2985
2986 // Get the funcref in "rettv".
2987 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2988 return FAIL;
2989
2990 if (**arg != '(')
2991 {
2992 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002993 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002994 else
2995 semsg(_(e_missing_paren), "lambda");
2996 clear_tv(&rettv);
2997 return FAIL;
2998 }
2999
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003000 ufunc = rettv.vval.v_partial->pt_func;
3001 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003002 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003003 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01003004
3005 // The function will have one line: "return {expr}".
3006 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003007 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003008
3009 // compile the arguments
3010 *arg = skipwhite(*arg + 1);
3011 if (compile_arguments(arg, cctx, &argcount) == OK)
3012 // call the compiled function
3013 ret = generate_CALL(cctx, ufunc, argcount);
3014
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003015 return ret;
3016}
3017
3018/*
3019 * parse a dict: {'key': val} or #{key: val}
3020 * "*arg" points to the '{'.
3021 */
3022 static int
3023compile_dict(char_u **arg, cctx_T *cctx, int literal)
3024{
3025 garray_T *instr = &cctx->ctx_instr;
3026 int count = 0;
3027 dict_T *d = dict_alloc();
3028 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003029 char_u *whitep = *arg;
3030 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003031
3032 if (d == NULL)
3033 return FAIL;
3034 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003035 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003036 {
3037 char_u *key = NULL;
3038
Bram Moolenaar2c330432020-04-13 14:41:35 +02003039 while (**arg == NUL || (literal && **arg == '"')
3040 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003041 {
3042 *arg = next_line_from_context(cctx);
3043 if (*arg == NULL)
3044 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003045 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003046 *arg = skipwhite(*arg);
3047 }
3048
3049 if (**arg == '}')
3050 break;
3051
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003052 if (literal)
3053 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02003054 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003055
Bram Moolenaar2c330432020-04-13 14:41:35 +02003056 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003057 {
3058 semsg(_("E1014: Invalid key: %s"), *arg);
3059 return FAIL;
3060 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003061 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003062 if (generate_PUSHS(cctx, key) == FAIL)
3063 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003064 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003065 }
3066 else
3067 {
3068 isn_T *isn;
3069
Bram Moolenaara5565e42020-05-09 15:44:01 +02003070 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003071 return FAIL;
3072 // TODO: check type is string
3073 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
3074 if (isn->isn_type == ISN_PUSHS)
3075 key = isn->isn_arg.string;
3076 }
3077
3078 // Check for duplicate keys, if using string keys.
3079 if (key != NULL)
3080 {
3081 item = dict_find(d, key, -1);
3082 if (item != NULL)
3083 {
3084 semsg(_(e_duplicate_key), key);
3085 goto failret;
3086 }
3087 item = dictitem_alloc(key);
3088 if (item != NULL)
3089 {
3090 item->di_tv.v_type = VAR_UNKNOWN;
3091 item->di_tv.v_lock = 0;
3092 if (dict_add(d, item) == FAIL)
3093 dictitem_free(item);
3094 }
3095 }
3096
3097 *arg = skipwhite(*arg);
3098 if (**arg != ':')
3099 {
3100 semsg(_(e_missing_dict_colon), *arg);
3101 return FAIL;
3102 }
3103
Bram Moolenaar2c330432020-04-13 14:41:35 +02003104 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003105 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003106 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003107 {
3108 *arg = next_line_from_context(cctx);
3109 if (*arg == NULL)
3110 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003111 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003112 *arg = skipwhite(*arg);
3113 }
3114
Bram Moolenaara5565e42020-05-09 15:44:01 +02003115 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003116 return FAIL;
3117 ++count;
3118
Bram Moolenaar2c330432020-04-13 14:41:35 +02003119 whitep = *arg;
3120 p = skipwhite(*arg);
3121 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003122 {
3123 *arg = next_line_from_context(cctx);
3124 if (*arg == NULL)
3125 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003126 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003127 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003128 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003129 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003130 if (**arg == '}')
3131 break;
3132 if (**arg != ',')
3133 {
3134 semsg(_(e_missing_dict_comma), *arg);
3135 goto failret;
3136 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003137 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003138 *arg = skipwhite(*arg + 1);
3139 }
3140
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003141 *arg = *arg + 1;
3142
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003143 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003144 p = skipwhite(*arg);
3145 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003146 *arg += STRLEN(*arg);
3147
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003148 dict_unref(d);
3149 return generate_NEWDICT(cctx, count);
3150
3151failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003152 if (*arg == NULL)
3153 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003154 dict_unref(d);
3155 return FAIL;
3156}
3157
3158/*
3159 * Compile "&option".
3160 */
3161 static int
3162compile_get_option(char_u **arg, cctx_T *cctx)
3163{
3164 typval_T rettv;
3165 char_u *start = *arg;
3166 int ret;
3167
3168 // parse the option and get the current value to get the type.
3169 rettv.v_type = VAR_UNKNOWN;
3170 ret = get_option_tv(arg, &rettv, TRUE);
3171 if (ret == OK)
3172 {
3173 // include the '&' in the name, get_option_tv() expects it.
3174 char_u *name = vim_strnsave(start, *arg - start);
3175 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
3176
3177 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3178 vim_free(name);
3179 }
3180 clear_tv(&rettv);
3181
3182 return ret;
3183}
3184
3185/*
3186 * Compile "$VAR".
3187 */
3188 static int
3189compile_get_env(char_u **arg, cctx_T *cctx)
3190{
3191 char_u *start = *arg;
3192 int len;
3193 int ret;
3194 char_u *name;
3195
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003196 ++*arg;
3197 len = get_env_len(arg);
3198 if (len == 0)
3199 {
3200 semsg(_(e_syntax_at), start - 1);
3201 return FAIL;
3202 }
3203
3204 // include the '$' in the name, get_env_tv() expects it.
3205 name = vim_strnsave(start, len + 1);
3206 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3207 vim_free(name);
3208 return ret;
3209}
3210
3211/*
3212 * Compile "@r".
3213 */
3214 static int
3215compile_get_register(char_u **arg, cctx_T *cctx)
3216{
3217 int ret;
3218
3219 ++*arg;
3220 if (**arg == NUL)
3221 {
3222 semsg(_(e_syntax_at), *arg - 1);
3223 return FAIL;
3224 }
3225 if (!valid_yank_reg(**arg, TRUE))
3226 {
3227 emsg_invreg(**arg);
3228 return FAIL;
3229 }
3230 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3231 ++*arg;
3232 return ret;
3233}
3234
3235/*
3236 * Apply leading '!', '-' and '+' to constant "rettv".
3237 */
3238 static int
3239apply_leader(typval_T *rettv, char_u *start, char_u *end)
3240{
3241 char_u *p = end;
3242
3243 // this works from end to start
3244 while (p > start)
3245 {
3246 --p;
3247 if (*p == '-' || *p == '+')
3248 {
3249 // only '-' has an effect, for '+' we only check the type
3250#ifdef FEAT_FLOAT
3251 if (rettv->v_type == VAR_FLOAT)
3252 {
3253 if (*p == '-')
3254 rettv->vval.v_float = -rettv->vval.v_float;
3255 }
3256 else
3257#endif
3258 {
3259 varnumber_T val;
3260 int error = FALSE;
3261
3262 // tv_get_number_chk() accepts a string, but we don't want that
3263 // here
3264 if (check_not_string(rettv) == FAIL)
3265 return FAIL;
3266 val = tv_get_number_chk(rettv, &error);
3267 clear_tv(rettv);
3268 if (error)
3269 return FAIL;
3270 if (*p == '-')
3271 val = -val;
3272 rettv->v_type = VAR_NUMBER;
3273 rettv->vval.v_number = val;
3274 }
3275 }
3276 else
3277 {
3278 int v = tv2bool(rettv);
3279
3280 // '!' is permissive in the type.
3281 clear_tv(rettv);
3282 rettv->v_type = VAR_BOOL;
3283 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3284 }
3285 }
3286 return OK;
3287}
3288
3289/*
3290 * Recognize v: variables that are constants and set "rettv".
3291 */
3292 static void
3293get_vim_constant(char_u **arg, typval_T *rettv)
3294{
3295 if (STRNCMP(*arg, "v:true", 6) == 0)
3296 {
3297 rettv->v_type = VAR_BOOL;
3298 rettv->vval.v_number = VVAL_TRUE;
3299 *arg += 6;
3300 }
3301 else if (STRNCMP(*arg, "v:false", 7) == 0)
3302 {
3303 rettv->v_type = VAR_BOOL;
3304 rettv->vval.v_number = VVAL_FALSE;
3305 *arg += 7;
3306 }
3307 else if (STRNCMP(*arg, "v:null", 6) == 0)
3308 {
3309 rettv->v_type = VAR_SPECIAL;
3310 rettv->vval.v_number = VVAL_NULL;
3311 *arg += 6;
3312 }
3313 else if (STRNCMP(*arg, "v:none", 6) == 0)
3314 {
3315 rettv->v_type = VAR_SPECIAL;
3316 rettv->vval.v_number = VVAL_NONE;
3317 *arg += 6;
3318 }
3319}
3320
Bram Moolenaar61a89812020-05-07 16:58:17 +02003321 static exptype_T
3322get_compare_type(char_u *p, int *len, int *type_is)
3323{
3324 exptype_T type = EXPR_UNKNOWN;
3325 int i;
3326
3327 switch (p[0])
3328 {
3329 case '=': if (p[1] == '=')
3330 type = EXPR_EQUAL;
3331 else if (p[1] == '~')
3332 type = EXPR_MATCH;
3333 break;
3334 case '!': if (p[1] == '=')
3335 type = EXPR_NEQUAL;
3336 else if (p[1] == '~')
3337 type = EXPR_NOMATCH;
3338 break;
3339 case '>': if (p[1] != '=')
3340 {
3341 type = EXPR_GREATER;
3342 *len = 1;
3343 }
3344 else
3345 type = EXPR_GEQUAL;
3346 break;
3347 case '<': if (p[1] != '=')
3348 {
3349 type = EXPR_SMALLER;
3350 *len = 1;
3351 }
3352 else
3353 type = EXPR_SEQUAL;
3354 break;
3355 case 'i': if (p[1] == 's')
3356 {
3357 // "is" and "isnot"; but not a prefix of a name
3358 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3359 *len = 5;
3360 i = p[*len];
3361 if (!isalnum(i) && i != '_')
3362 {
3363 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3364 *type_is = TRUE;
3365 }
3366 }
3367 break;
3368 }
3369 return type;
3370}
3371
3372/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003373 * Compile code to apply '-', '+' and '!'.
3374 */
3375 static int
3376compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3377{
3378 char_u *p = end;
3379
3380 // this works from end to start
3381 while (p > start)
3382 {
3383 --p;
3384 if (*p == '-' || *p == '+')
3385 {
3386 int negate = *p == '-';
3387 isn_T *isn;
3388
3389 // TODO: check type
3390 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3391 {
3392 --p;
3393 if (*p == '-')
3394 negate = !negate;
3395 }
3396 // only '-' has an effect, for '+' we only check the type
3397 if (negate)
3398 isn = generate_instr(cctx, ISN_NEGATENR);
3399 else
3400 isn = generate_instr(cctx, ISN_CHECKNR);
3401 if (isn == NULL)
3402 return FAIL;
3403 }
3404 else
3405 {
3406 int invert = TRUE;
3407
3408 while (p > start && p[-1] == '!')
3409 {
3410 --p;
3411 invert = !invert;
3412 }
3413 if (generate_2BOOL(cctx, invert) == FAIL)
3414 return FAIL;
3415 }
3416 }
3417 return OK;
3418}
3419
3420/*
3421 * Compile whatever comes after "name" or "name()".
3422 */
3423 static int
3424compile_subscript(
3425 char_u **arg,
3426 cctx_T *cctx,
3427 char_u **start_leader,
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003428 char_u *end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003429 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003430{
3431 for (;;)
3432 {
3433 if (**arg == '(')
3434 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003435 garray_T *stack = &cctx->ctx_type_stack;
3436 type_T *type;
3437 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003438
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003439 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003440 return FAIL;
3441
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003442 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003443 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3444
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003445 *arg = skipwhite(*arg + 1);
3446 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3447 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003448 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003449 return FAIL;
3450 }
3451 else if (**arg == '-' && (*arg)[1] == '>')
3452 {
3453 char_u *p;
3454
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003455 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003456 return FAIL;
3457
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003458 // something->method()
3459 // Apply the '!', '-' and '+' first:
3460 // -1.0->func() works like (-1.0)->func()
3461 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3462 return FAIL;
3463 *start_leader = end_leader; // don't apply again later
3464
3465 *arg = skipwhite(*arg + 2);
3466 if (**arg == '{')
3467 {
3468 // lambda call: list->{lambda}
3469 if (compile_lambda_call(arg, cctx) == FAIL)
3470 return FAIL;
3471 }
3472 else
3473 {
3474 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003475 p = *arg;
3476 if (ASCII_ISALPHA(*p) && p[1] == ':')
3477 p += 2;
3478 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003479 ;
3480 if (*p != '(')
3481 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003482 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003483 return FAIL;
3484 }
3485 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02003486 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003487 return FAIL;
3488 }
3489 }
3490 else if (**arg == '[')
3491 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003492 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003493 type_T **typep;
3494
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003495 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003496 // dict member: dict[key]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003497 // TODO: blob index
3498 // TODO: more arguments
3499 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003500 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003501 return FAIL;
3502
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003503 *arg = skipwhite(*arg + 1);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003504 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003505 return FAIL;
3506
3507 if (**arg != ']')
3508 {
3509 emsg(_(e_missbrac));
3510 return FAIL;
3511 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003512 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003513
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003514 typep = ((type_T **)stack->ga_data) + stack->ga_len - 2;
3515 if ((*typep)->tt_type == VAR_LIST || (*typep) == &t_any)
Bram Moolenaarb13af502020-02-17 21:12:08 +01003516 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003517 if ((*typep)->tt_type == VAR_LIST)
3518 *typep = (*typep)->tt_member;
3519 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3520 return FAIL;
3521 }
3522 else if ((*typep)->tt_type == VAR_DICT)
3523 {
3524 *typep = (*typep)->tt_member;
3525 if (may_generate_2STRING(-1, cctx) == FAIL)
3526 return FAIL;
3527 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
3528 return FAIL;
3529 }
3530 else
3531 {
3532 emsg(_(e_listdictblobreq));
Bram Moolenaarb13af502020-02-17 21:12:08 +01003533 return FAIL;
3534 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003535 }
3536 else if (**arg == '.' && (*arg)[1] != '.')
3537 {
3538 char_u *p;
3539
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003540 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003541 return FAIL;
3542
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003543 ++*arg;
3544 p = *arg;
3545 // dictionary member: dict.name
3546 if (eval_isnamec1(*p))
3547 while (eval_isnamec(*p))
3548 MB_PTR_ADV(p);
3549 if (p == *arg)
3550 {
3551 semsg(_(e_syntax_at), *arg);
3552 return FAIL;
3553 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003554 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003555 return FAIL;
3556 *arg = p;
3557 }
3558 else
3559 break;
3560 }
3561
3562 // TODO - see handle_subscript():
3563 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3564 // Don't do this when "Func" is already a partial that was bound
3565 // explicitly (pt_auto is FALSE).
3566
3567 return OK;
3568}
3569
3570/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003571 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
3572 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003573 *
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003574 * If the value is a constant "ppconst->pp_ret" will be set.
3575 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003576 *
3577 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003578 */
3579
3580/*
3581 * number number constant
3582 * 0zFFFFFFFF Blob constant
3583 * "string" string constant
3584 * 'string' literal string constant
3585 * &option-name option value
3586 * @r register contents
3587 * identifier variable value
3588 * function() function call
3589 * $VAR environment variable
3590 * (expression) nested expression
3591 * [expr, expr] List
3592 * {key: val, key: val} Dictionary
3593 * #{key: val, key: val} Dictionary with literal keys
3594 *
3595 * Also handle:
3596 * ! in front logical NOT
3597 * - in front unary minus
3598 * + in front unary plus (ignored)
3599 * trailing (arg) funcref/partial call
3600 * trailing [] subscript in String or List
3601 * trailing .name entry in Dictionary
3602 * trailing ->name() method call
3603 */
3604 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003605compile_expr7(
3606 char_u **arg,
3607 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003608 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003609{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003610 char_u *start_leader, *end_leader;
3611 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003612 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02003613 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003614
3615 /*
3616 * Skip '!', '-' and '+' characters. They are handled later.
3617 */
3618 start_leader = *arg;
3619 while (**arg == '!' || **arg == '-' || **arg == '+')
3620 *arg = skipwhite(*arg + 1);
3621 end_leader = *arg;
3622
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003623 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003624 switch (**arg)
3625 {
3626 /*
3627 * Number constant.
3628 */
3629 case '0': // also for blob starting with 0z
3630 case '1':
3631 case '2':
3632 case '3':
3633 case '4':
3634 case '5':
3635 case '6':
3636 case '7':
3637 case '8':
3638 case '9':
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003639 case '.': if (get_number_tv(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003640 return FAIL;
3641 break;
3642
3643 /*
3644 * String constant: "string".
3645 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003646 case '"': if (get_string_tv(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003647 return FAIL;
3648 break;
3649
3650 /*
3651 * Literal string constant: 'str''ing'.
3652 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003653 case '\'': if (get_lit_string_tv(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003654 return FAIL;
3655 break;
3656
3657 /*
3658 * Constant Vim variable.
3659 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003660 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003661 ret = NOTDONE;
3662 break;
3663
3664 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02003665 * "true" constant
3666 */
3667 case 't': if (STRNCMP(*arg, "true", 4) == 0
3668 && !eval_isnamec((*arg)[4]))
3669 {
3670 *arg += 4;
3671 rettv->v_type = VAR_BOOL;
3672 rettv->vval.v_number = VVAL_TRUE;
3673 }
3674 else
3675 ret = NOTDONE;
3676 break;
3677
3678 /*
3679 * "false" constant
3680 */
3681 case 'f': if (STRNCMP(*arg, "false", 5) == 0
3682 && !eval_isnamec((*arg)[5]))
3683 {
3684 *arg += 5;
3685 rettv->v_type = VAR_BOOL;
3686 rettv->vval.v_number = VVAL_FALSE;
3687 }
3688 else
3689 ret = NOTDONE;
3690 break;
3691
3692 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003693 * List: [expr, expr]
3694 */
3695 case '[': ret = compile_list(arg, cctx);
3696 break;
3697
3698 /*
3699 * Dictionary: #{key: val, key: val}
3700 */
3701 case '#': if ((*arg)[1] == '{')
3702 {
3703 ++*arg;
3704 ret = compile_dict(arg, cctx, TRUE);
3705 }
3706 else
3707 ret = NOTDONE;
3708 break;
3709
3710 /*
3711 * Lambda: {arg, arg -> expr}
3712 * Dictionary: {'key': val, 'key': val}
3713 */
3714 case '{': {
3715 char_u *start = skipwhite(*arg + 1);
3716
3717 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003718 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003719 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003720 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003721 if (ret != FAIL && *start == '>')
3722 ret = compile_lambda(arg, cctx);
3723 else
3724 ret = compile_dict(arg, cctx, FALSE);
3725 }
3726 break;
3727
3728 /*
3729 * Option value: &name
3730 */
3731 case '&': ret = compile_get_option(arg, cctx);
3732 break;
3733
3734 /*
3735 * Environment variable: $VAR.
3736 */
3737 case '$': ret = compile_get_env(arg, cctx);
3738 break;
3739
3740 /*
3741 * Register contents: @r.
3742 */
3743 case '@': ret = compile_get_register(arg, cctx);
3744 break;
3745 /*
3746 * nested expression: (expression).
3747 */
3748 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaar1c747212020-05-09 18:28:34 +02003749
3750 // recursive!
3751 if (ppconst->pp_used <= PPSIZE - 10)
3752 {
3753 ret = compile_expr1(arg, cctx, ppconst);
3754 }
3755 else
3756 {
3757 // Not enough space in ppconst, flush constants.
3758 if (generate_ppconst(cctx, ppconst) == FAIL)
3759 return FAIL;
3760 ret = compile_expr0(arg, cctx);
3761 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003762 *arg = skipwhite(*arg);
3763 if (**arg == ')')
3764 ++*arg;
3765 else if (ret == OK)
3766 {
3767 emsg(_(e_missing_close));
3768 ret = FAIL;
3769 }
3770 break;
3771
3772 default: ret = NOTDONE;
3773 break;
3774 }
3775 if (ret == FAIL)
3776 return FAIL;
3777
Bram Moolenaar1c747212020-05-09 18:28:34 +02003778 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003779 {
3780 // apply the '!', '-' and '+' before the constant
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003781 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003782 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003783 clear_tv(rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003784 return FAIL;
3785 }
3786 start_leader = end_leader; // don't apply again below
3787
Bram Moolenaara5565e42020-05-09 15:44:01 +02003788 if (cctx->ctx_skip == TRUE)
3789 clear_tv(rettv);
3790 else
3791 // A constant expression can possibly be handled compile time,
3792 // return the value instead of generating code.
3793 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003794 }
3795 else if (ret == NOTDONE)
3796 {
3797 char_u *p;
3798 int r;
3799
3800 if (!eval_isnamec1(**arg))
3801 {
3802 semsg(_("E1015: Name expected: %s"), *arg);
3803 return FAIL;
3804 }
3805
3806 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003807 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003808 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02003809 {
3810 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
3811 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003812 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02003813 {
3814 if (generate_ppconst(cctx, ppconst) == FAIL)
3815 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003816 r = compile_load(arg, p, cctx, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003817 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003818 if (r == FAIL)
3819 return FAIL;
3820 }
3821
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003822 // Handle following "[]", ".member", etc.
3823 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003824 if (compile_subscript(arg, cctx, &start_leader, end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02003825 ppconst) == FAIL)
3826 return FAIL;
3827 if (ppconst->pp_used > 0)
3828 {
3829 // apply the '!', '-' and '+' before the constant
3830 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
3831 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
3832 return FAIL;
3833 return OK;
3834 }
3835 if (compile_leader(cctx, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003836 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003837 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003838}
3839
3840/*
3841 * * number multiplication
3842 * / number division
3843 * % number modulo
3844 */
3845 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003846compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003847{
3848 char_u *op;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003849 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003850
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003851 // get the first expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003852 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003853 return FAIL;
3854
3855 /*
3856 * Repeat computing, until no "*", "/" or "%" is following.
3857 */
3858 for (;;)
3859 {
3860 op = skipwhite(*arg);
3861 if (*op != '*' && *op != '/' && *op != '%')
3862 break;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003863
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003864 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003865 {
3866 char_u buf[3];
3867
3868 vim_strncpy(buf, op, 1);
3869 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003870 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003871 }
3872 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003873 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003874 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003875
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003876 // get the second expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003877 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003878 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003879
3880 if (ppconst->pp_used == ppconst_used + 2
3881 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3882 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003883 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003884 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3885 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003886 varnumber_T res = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003887
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003888 // both are numbers: compute the result
3889 switch (*op)
3890 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003891 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003892 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003893 case '/': res = tv1->vval.v_number / tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003894 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003895 case '%': res = tv1->vval.v_number % tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003896 break;
3897 }
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003898 tv1->vval.v_number = res;
3899 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003900 }
3901 else
3902 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003903 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003904 generate_two_op(cctx, op);
3905 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003906 }
3907
3908 return OK;
3909}
3910
3911/*
3912 * + number addition
3913 * - number subtraction
3914 * .. string concatenation
3915 */
3916 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003917compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003918{
3919 char_u *op;
3920 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003921 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003922
3923 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02003924 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003925 return FAIL;
3926
3927 /*
3928 * Repeat computing, until no "+", "-" or ".." is following.
3929 */
3930 for (;;)
3931 {
3932 op = skipwhite(*arg);
3933 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3934 break;
3935 oplen = (*op == '.' ? 2 : 1);
3936
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003937 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003938 {
3939 char_u buf[3];
3940
3941 vim_strncpy(buf, op, oplen);
3942 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003943 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003944 }
3945
3946 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003947 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003948 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003949
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003950 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02003951 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003952 return FAIL;
3953
Bram Moolenaara5565e42020-05-09 15:44:01 +02003954 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003955 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02003956 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
3957 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
3958 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3959 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003960 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003961 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3962 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003963
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003964 // concat/subtract/add constant numbers
3965 if (*op == '+')
3966 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
3967 else if (*op == '-')
3968 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
3969 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003970 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003971 // concatenate constant strings
3972 char_u *s1 = tv1->vval.v_string;
3973 char_u *s2 = tv2->vval.v_string;
3974 size_t len1 = STRLEN(s1);
3975
3976 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
3977 if (tv1->vval.v_string == NULL)
3978 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003979 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003980 return FAIL;
3981 }
3982 mch_memmove(tv1->vval.v_string, s1, len1);
3983 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003984 vim_free(s1);
3985 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003986 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003987 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003988 }
3989 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003990 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003991 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003992 if (*op == '.')
3993 {
3994 if (may_generate_2STRING(-2, cctx) == FAIL
3995 || may_generate_2STRING(-1, cctx) == FAIL)
3996 return FAIL;
3997 generate_instr_drop(cctx, ISN_CONCAT, 1);
3998 }
3999 else
4000 generate_two_op(cctx, op);
4001 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004002 }
4003
4004 return OK;
4005}
4006
4007/*
4008 * expr5a == expr5b
4009 * expr5a =~ expr5b
4010 * expr5a != expr5b
4011 * expr5a !~ expr5b
4012 * expr5a > expr5b
4013 * expr5a >= expr5b
4014 * expr5a < expr5b
4015 * expr5a <= expr5b
4016 * expr5a is expr5b
4017 * expr5a isnot expr5b
4018 *
4019 * Produces instructions:
4020 * EVAL expr5a Push result of "expr5a"
4021 * EVAL expr5b Push result of "expr5b"
4022 * COMPARE one of the compare instructions
4023 */
4024 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004025compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004026{
4027 exptype_T type = EXPR_UNKNOWN;
4028 char_u *p;
4029 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004030 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004031 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004032
4033 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004034 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004035 return FAIL;
4036
4037 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004038 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004039
4040 /*
4041 * If there is a comparative operator, use it.
4042 */
4043 if (type != EXPR_UNKNOWN)
4044 {
4045 int ic = FALSE; // Default: do not ignore case
4046
4047 if (type_is && (p[len] == '?' || p[len] == '#'))
4048 {
4049 semsg(_(e_invexpr2), *arg);
4050 return FAIL;
4051 }
4052 // extra question mark appended: ignore case
4053 if (p[len] == '?')
4054 {
4055 ic = TRUE;
4056 ++len;
4057 }
4058 // extra '#' appended: match case (ignored)
4059 else if (p[len] == '#')
4060 ++len;
4061 // nothing appended: match case
4062
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004063 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004064 {
4065 char_u buf[7];
4066
4067 vim_strncpy(buf, p, len);
4068 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004069 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004070 }
4071
4072 // get the second variable
4073 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004074 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004075 return FAIL;
4076
Bram Moolenaara5565e42020-05-09 15:44:01 +02004077 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004078 return FAIL;
4079
Bram Moolenaara5565e42020-05-09 15:44:01 +02004080 if (ppconst->pp_used == ppconst_used + 2)
4081 {
4082 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4083 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4084 int ret;
4085
4086 // Both sides are a constant, compute the result now.
4087 // First check for a valid combination of types, this is more
4088 // strict than typval_compare().
4089 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
4090 ret = FAIL;
4091 else
4092 {
4093 ret = typval_compare(tv1, tv2, type, ic);
4094 tv1->v_type = VAR_BOOL;
4095 tv1->vval.v_number = tv1->vval.v_number
4096 ? VVAL_TRUE : VVAL_FALSE;
4097 clear_tv(tv2);
4098 --ppconst->pp_used;
4099 }
4100 return ret;
4101 }
4102
4103 generate_ppconst(cctx, ppconst);
4104 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004105 }
4106
4107 return OK;
4108}
4109
Bram Moolenaar7f141552020-05-09 17:35:53 +02004110static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4111
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004112/*
4113 * Compile || or &&.
4114 */
4115 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004116compile_and_or(
4117 char_u **arg,
4118 cctx_T *cctx,
4119 char *op,
4120 ppconst_T *ppconst,
4121 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004122{
4123 char_u *p = skipwhite(*arg);
4124 int opchar = *op;
4125
4126 if (p[0] == opchar && p[1] == opchar)
4127 {
4128 garray_T *instr = &cctx->ctx_instr;
4129 garray_T end_ga;
4130
4131 /*
4132 * Repeat until there is no following "||" or "&&"
4133 */
4134 ga_init2(&end_ga, sizeof(int), 10);
4135 while (p[0] == opchar && p[1] == opchar)
4136 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004137 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4138 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004139 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004140 return FAIL;
4141 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004142
Bram Moolenaara5565e42020-05-09 15:44:01 +02004143 // TODO: use ppconst if the value is a constant
4144 generate_ppconst(cctx, ppconst);
4145
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004146 if (ga_grow(&end_ga, 1) == FAIL)
4147 {
4148 ga_clear(&end_ga);
4149 return FAIL;
4150 }
4151 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4152 ++end_ga.ga_len;
4153 generate_JUMP(cctx, opchar == '|'
4154 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
4155
4156 // eval the next expression
4157 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004158 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004159 return FAIL;
4160
Bram Moolenaara5565e42020-05-09 15:44:01 +02004161 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4162 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004163 {
4164 ga_clear(&end_ga);
4165 return FAIL;
4166 }
4167 p = skipwhite(*arg);
4168 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004169 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004170
4171 // Fill in the end label in all jumps.
4172 while (end_ga.ga_len > 0)
4173 {
4174 isn_T *isn;
4175
4176 --end_ga.ga_len;
4177 isn = ((isn_T *)instr->ga_data)
4178 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4179 isn->isn_arg.jump.jump_where = instr->ga_len;
4180 }
4181 ga_clear(&end_ga);
4182 }
4183
4184 return OK;
4185}
4186
4187/*
4188 * expr4a && expr4a && expr4a logical AND
4189 *
4190 * Produces instructions:
4191 * EVAL expr4a Push result of "expr4a"
4192 * JUMP_AND_KEEP_IF_FALSE end
4193 * EVAL expr4b Push result of "expr4b"
4194 * JUMP_AND_KEEP_IF_FALSE end
4195 * EVAL expr4c Push result of "expr4c"
4196 * end:
4197 */
4198 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004199compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004200{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004201 int ppconst_used = ppconst->pp_used;
4202
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004203 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004204 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004205 return FAIL;
4206
4207 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004208 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004209}
4210
4211/*
4212 * expr3a || expr3b || expr3c logical OR
4213 *
4214 * Produces instructions:
4215 * EVAL expr3a Push result of "expr3a"
4216 * JUMP_AND_KEEP_IF_TRUE end
4217 * EVAL expr3b Push result of "expr3b"
4218 * JUMP_AND_KEEP_IF_TRUE end
4219 * EVAL expr3c Push result of "expr3c"
4220 * end:
4221 */
4222 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004223compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004224{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004225 int ppconst_used = ppconst->pp_used;
4226
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004227 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004228 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004229 return FAIL;
4230
4231 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004232 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004233}
4234
4235/*
4236 * Toplevel expression: expr2 ? expr1a : expr1b
4237 *
4238 * Produces instructions:
4239 * EVAL expr2 Push result of "expr"
4240 * JUMP_IF_FALSE alt jump if false
4241 * EVAL expr1a
4242 * JUMP_ALWAYS end
4243 * alt: EVAL expr1b
4244 * end:
4245 */
4246 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004247compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004248{
4249 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004250 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004251
Bram Moolenaar61a89812020-05-07 16:58:17 +02004252 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004253 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004254 return FAIL;
4255
4256 p = skipwhite(*arg);
4257 if (*p == '?')
4258 {
4259 garray_T *instr = &cctx->ctx_instr;
4260 garray_T *stack = &cctx->ctx_type_stack;
4261 int alt_idx = instr->ga_len;
4262 int end_idx;
4263 isn_T *isn;
4264 type_T *type1;
4265 type_T *type2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004266 int has_const_expr = FALSE;
4267 int const_value = FALSE;
4268 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004269
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004270 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4271 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004272 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004273 return FAIL;
4274 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004275
Bram Moolenaara5565e42020-05-09 15:44:01 +02004276 if (ppconst->pp_used == ppconst_used + 1)
4277 {
4278 // the condition is a constant, we know whether the ? or the :
4279 // expression is to be evaluated.
4280 has_const_expr = TRUE;
4281 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4282 clear_tv(&ppconst->pp_tv[ppconst_used]);
4283 --ppconst->pp_used;
4284 cctx->ctx_skip = save_skip == TRUE || !const_value;
4285 }
4286 else
4287 {
4288 generate_ppconst(cctx, ppconst);
4289 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4290 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004291
4292 // evaluate the second expression; any type is accepted
4293 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004294 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004295 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004296 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004297 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298
Bram Moolenaara5565e42020-05-09 15:44:01 +02004299 if (!has_const_expr)
4300 {
4301 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004302
Bram Moolenaara5565e42020-05-09 15:44:01 +02004303 // remember the type and drop it
4304 --stack->ga_len;
4305 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004306
Bram Moolenaara5565e42020-05-09 15:44:01 +02004307 end_idx = instr->ga_len;
4308 generate_JUMP(cctx, JUMP_ALWAYS, 0);
4309
4310 // jump here from JUMP_IF_FALSE
4311 isn = ((isn_T *)instr->ga_data) + alt_idx;
4312 isn->isn_arg.jump.jump_where = instr->ga_len;
4313 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004314
4315 // Check for the ":".
4316 p = skipwhite(*arg);
4317 if (*p != ':')
4318 {
4319 emsg(_(e_missing_colon));
4320 return FAIL;
4321 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004322 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4323 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004324 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004325 return FAIL;
4326 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004327
4328 // evaluate the third expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004329 if (has_const_expr)
4330 cctx->ctx_skip = save_skip == TRUE || const_value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004331 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004332 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004333 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004334 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004335 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004336
Bram Moolenaara5565e42020-05-09 15:44:01 +02004337 if (!has_const_expr)
4338 {
4339 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004340
Bram Moolenaara5565e42020-05-09 15:44:01 +02004341 // If the types differ, the result has a more generic type.
4342 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4343 common_type(type1, type2, &type2, cctx->ctx_type_list);
4344
4345 // jump here from JUMP_ALWAYS
4346 isn = ((isn_T *)instr->ga_data) + end_idx;
4347 isn->isn_arg.jump.jump_where = instr->ga_len;
4348 }
4349
4350 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004351 }
4352 return OK;
4353}
4354
4355/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004356 * Toplevel expression.
4357 */
4358 static int
4359compile_expr0(char_u **arg, cctx_T *cctx)
4360{
4361 ppconst_T ppconst;
4362
4363 CLEAR_FIELD(ppconst);
4364 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4365 {
4366 clear_ppconst(&ppconst);
4367 return FAIL;
4368 }
4369 if (generate_ppconst(cctx, &ppconst) == FAIL)
4370 return FAIL;
4371 return OK;
4372}
4373
4374/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004375 * compile "return [expr]"
4376 */
4377 static char_u *
4378compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4379{
4380 char_u *p = arg;
4381 garray_T *stack = &cctx->ctx_type_stack;
4382 type_T *stack_type;
4383
4384 if (*p != NUL && *p != '|' && *p != '\n')
4385 {
4386 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02004387 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004388 return NULL;
4389
4390 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4391 if (set_return_type)
4392 cctx->ctx_ufunc->uf_ret_type = stack_type;
4393 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
4394 == FAIL)
4395 return NULL;
4396 }
4397 else
4398 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004399 // "set_return_type" cannot be TRUE, only used for a lambda which
4400 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004401 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4402 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004403 {
4404 emsg(_("E1003: Missing return value"));
4405 return NULL;
4406 }
4407
4408 // No argument, return zero.
4409 generate_PUSHNR(cctx, 0);
4410 }
4411
4412 if (generate_instr(cctx, ISN_RETURN) == NULL)
4413 return NULL;
4414
4415 // "return val | endif" is possible
4416 return skipwhite(p);
4417}
4418
4419/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004420 * Get a line from the compilation context, compatible with exarg_T getline().
4421 * Return a pointer to the line in allocated memory.
4422 * Return NULL for end-of-file or some error.
4423 */
4424 static char_u *
4425exarg_getline(
4426 int c UNUSED,
4427 void *cookie,
4428 int indent UNUSED,
4429 int do_concat UNUSED)
4430{
4431 cctx_T *cctx = (cctx_T *)cookie;
4432
4433 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4434 {
4435 iemsg("Heredoc got to end");
4436 return NULL;
4437 }
4438 ++cctx->ctx_lnum;
4439 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4440 [cctx->ctx_lnum]);
4441}
4442
4443/*
4444 * Compile a nested :def command.
4445 */
4446 static char_u *
4447compile_nested_function(exarg_T *eap, cctx_T *cctx)
4448{
4449 char_u *name_start = eap->arg;
4450 char_u *name_end = to_name_end(eap->arg, FALSE);
4451 char_u *name = get_lambda_name();
4452 lvar_T *lvar;
4453 ufunc_T *ufunc;
4454
4455 eap->arg = name_end;
4456 eap->getline = exarg_getline;
4457 eap->cookie = cctx;
4458 eap->skip = cctx->ctx_skip == TRUE;
4459 eap->forceit = FALSE;
Bram Moolenaar822ba242020-05-24 23:00:18 +02004460 ufunc = def_function(eap, name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02004461
Bram Moolenaar822ba242020-05-24 23:00:18 +02004462 if (ufunc == NULL)
4463 return NULL;
4464 if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED
4465 && compile_def_function(ufunc, TRUE, cctx) == FAIL)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004466 return NULL;
4467
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004468 // Define a local variable for the function reference.
Bram Moolenaar04b12692020-05-04 23:24:44 +02004469 lvar = reserve_local(cctx, name_start, name_end - name_start,
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004470 TRUE, ufunc->uf_func_type);
4471
4472 if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL
4473 || generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL)
4474 return NULL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004475
Bram Moolenaar61a89812020-05-07 16:58:17 +02004476 // TODO: warning for trailing text?
Bram Moolenaar04b12692020-05-04 23:24:44 +02004477 return (char_u *)"";
4478}
4479
4480/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004481 * Return the length of an assignment operator, or zero if there isn't one.
4482 */
4483 int
4484assignment_len(char_u *p, int *heredoc)
4485{
4486 if (*p == '=')
4487 {
4488 if (p[1] == '<' && p[2] == '<')
4489 {
4490 *heredoc = TRUE;
4491 return 3;
4492 }
4493 return 1;
4494 }
4495 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4496 return 2;
4497 if (STRNCMP(p, "..=", 3) == 0)
4498 return 3;
4499 return 0;
4500}
4501
4502// words that cannot be used as a variable
4503static char *reserved[] = {
4504 "true",
4505 "false",
4506 NULL
4507};
4508
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004509typedef enum {
4510 dest_local,
4511 dest_option,
4512 dest_env,
4513 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004514 dest_buffer,
4515 dest_window,
4516 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004517 dest_vimvar,
4518 dest_script,
4519 dest_reg,
4520} assign_dest_T;
4521
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004522/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004523 * Generate the load instruction for "name".
4524 */
4525 static void
4526generate_loadvar(
4527 cctx_T *cctx,
4528 assign_dest_T dest,
4529 char_u *name,
4530 lvar_T *lvar,
4531 type_T *type)
4532{
4533 switch (dest)
4534 {
4535 case dest_option:
4536 // TODO: check the option exists
4537 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
4538 break;
4539 case dest_global:
4540 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4541 break;
4542 case dest_buffer:
4543 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4544 break;
4545 case dest_window:
4546 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4547 break;
4548 case dest_tab:
4549 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4550 break;
4551 case dest_script:
4552 compile_load_scriptvar(cctx,
4553 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
4554 break;
4555 case dest_env:
4556 // Include $ in the name here
4557 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4558 break;
4559 case dest_reg:
4560 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
4561 break;
4562 case dest_vimvar:
4563 generate_LOADV(cctx, name + 2, TRUE);
4564 break;
4565 case dest_local:
4566 if (lvar->lv_from_outer)
4567 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx,
4568 NULL, type);
4569 else
4570 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
4571 break;
4572 }
4573}
4574
4575/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004576 * compile "let var [= expr]", "const var = expr" and "var = expr"
4577 * "arg" points to "var".
4578 */
4579 static char_u *
4580compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4581{
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004582 char_u *var_end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004583 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004584 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004585 char_u *ret = NULL;
4586 int var_count = 0;
4587 int semicolon = 0;
4588 size_t varlen;
4589 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004590 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004591 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004592 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004593 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004594 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004595 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004596 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004597 int oplen = 0;
4598 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004599 type_T *type = &t_any;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004600 type_T *member_type = &t_any;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004601 lvar_T *lvar = NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004602 lvar_T arg_lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004603 char_u *name;
4604 char_u *sp;
4605 int has_type = FALSE;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004606 int has_index = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004607 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4608 int instr_count = -1;
4609
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004610 var_end = skip_var_list(arg, FALSE, &var_count, &semicolon);
4611 if (var_end == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004612 return NULL;
4613 if (var_count > 0)
4614 {
4615 // TODO: let [var, var] = list
4616 emsg("Cannot handle a list yet");
4617 return NULL;
4618 }
4619
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004620 p = (*arg == '&' || *arg == '$' || *arg == '@') ? arg + 1 : arg;
4621 p = to_name_end(p, TRUE);
4622
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004623 // "a: type" is declaring variable "a" with a type, not "a:".
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004624 if (is_decl && var_end == arg + 2 && var_end[-1] == ':')
4625 --var_end;
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004626 if (is_decl && p == arg + 2 && p[-1] == ':')
4627 --p;
4628
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004629 varlen = p - arg;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02004630 name = vim_strnsave(arg, varlen);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004631 if (name == NULL)
4632 return NULL;
4633
Bram Moolenaar080457c2020-03-03 21:53:32 +01004634 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004635 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004636 if (*arg == '&')
4637 {
4638 int cc;
4639 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004640
Bram Moolenaar080457c2020-03-03 21:53:32 +01004641 dest = dest_option;
4642 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004643 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004644 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004645 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004646 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004647 if (is_decl)
4648 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004649 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004650 goto theend;
4651 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004652 p = arg;
4653 p = find_option_end(&p, &opt_flags);
4654 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004655 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004656 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004657 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004658 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004659 }
4660 cc = *p;
4661 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004662 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004663 *p = cc;
4664 if (opt_type == -3)
4665 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004666 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004667 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004668 }
4669 if (opt_type == -2 || opt_type == 0)
4670 type = &t_string;
4671 else
4672 type = &t_number; // both number and boolean option
4673 }
4674 else if (*arg == '$')
4675 {
4676 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004677 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004678 if (is_decl)
4679 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004680 semsg(_("E1065: Cannot declare an environment variable: %s"),
4681 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004682 goto theend;
4683 }
4684 }
4685 else if (*arg == '@')
4686 {
4687 if (!valid_yank_reg(arg[1], TRUE))
4688 {
4689 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004690 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004691 }
4692 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004693 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004694 if (is_decl)
4695 {
4696 semsg(_("E1066: Cannot declare a register: %s"), name);
4697 goto theend;
4698 }
4699 }
4700 else if (STRNCMP(arg, "g:", 2) == 0)
4701 {
4702 dest = dest_global;
4703 if (is_decl)
4704 {
4705 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4706 goto theend;
4707 }
4708 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004709 else if (STRNCMP(arg, "b:", 2) == 0)
4710 {
4711 dest = dest_buffer;
4712 if (is_decl)
4713 {
4714 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4715 goto theend;
4716 }
4717 }
4718 else if (STRNCMP(arg, "w:", 2) == 0)
4719 {
4720 dest = dest_window;
4721 if (is_decl)
4722 {
4723 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4724 goto theend;
4725 }
4726 }
4727 else if (STRNCMP(arg, "t:", 2) == 0)
4728 {
4729 dest = dest_tab;
4730 if (is_decl)
4731 {
4732 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4733 goto theend;
4734 }
4735 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004736 else if (STRNCMP(arg, "v:", 2) == 0)
4737 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004738 typval_T *vtv;
4739 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004740
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004741 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004742 if (vimvaridx < 0)
4743 {
4744 semsg(_(e_var_notfound), arg);
4745 goto theend;
4746 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004747 // We use the current value of "sandbox" here, is that OK?
4748 if (var_check_ro(di_flags, name, FALSE))
4749 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004750 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004751 vtv = get_vim_var_tv(vimvaridx);
4752 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004753 if (is_decl)
4754 {
4755 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4756 goto theend;
4757 }
4758 }
4759 else
4760 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004761 int idx;
4762
Bram Moolenaar080457c2020-03-03 21:53:32 +01004763 for (idx = 0; reserved[idx] != NULL; ++idx)
4764 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004765 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004766 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004767 goto theend;
4768 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004769
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004770 lvar = lookup_local(arg, varlen, cctx);
Bram Moolenaarbc38f252020-05-10 23:20:06 +02004771 if (lvar == NULL)
4772 {
4773 CLEAR_FIELD(arg_lvar);
4774 if (lookup_arg(arg, varlen,
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004775 &arg_lvar.lv_idx, &arg_lvar.lv_type,
4776 &arg_lvar.lv_from_outer, cctx) == OK)
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004777 {
Bram Moolenaarbc38f252020-05-10 23:20:06 +02004778 if (is_decl)
4779 {
4780 semsg(_(e_used_as_arg), name);
4781 goto theend;
4782 }
4783 lvar = &arg_lvar;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004784 }
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004785 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004786 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004787 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004788 if (is_decl)
4789 {
4790 semsg(_("E1017: Variable already declared: %s"), name);
4791 goto theend;
4792 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004793 else if (lvar->lv_const)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004794 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004795 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4796 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004797 }
4798 }
4799 else if (STRNCMP(arg, "s:", 2) == 0
4800 || lookup_script(arg, varlen) == OK
4801 || find_imported(arg, varlen, cctx) != NULL)
4802 {
4803 dest = dest_script;
4804 if (is_decl)
4805 {
4806 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004807 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004808 goto theend;
4809 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004810 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004811 else if (name[1] == ':' && name[2] != NUL)
4812 {
4813 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4814 goto theend;
4815 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004816 else if (!is_decl)
4817 {
4818 semsg(_("E1089: unknown variable: %s"), name);
4819 goto theend;
4820 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004821 }
4822 }
4823
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004824 // handle "a:name" as a name, not index "name" on "a"
4825 if (varlen > 1 || arg[varlen] != ':')
4826 p = var_end;
4827
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004828 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004829 {
4830 if (is_decl && *p == ':')
4831 {
4832 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004833 if (!VIM_ISWHITE(p[1]))
4834 {
4835 semsg(_(e_white_after), ":");
4836 goto theend;
4837 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004838 p = skipwhite(p + 1);
4839 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004840 has_type = TRUE;
4841 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004842 else if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004843 type = lvar->lv_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004844 }
4845
4846 sp = p;
4847 p = skipwhite(p);
4848 op = p;
4849 oplen = assignment_len(p, &heredoc);
4850 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4851 {
4852 char_u buf[4];
4853
4854 vim_strncpy(buf, op, oplen);
4855 semsg(_(e_white_both), buf);
4856 }
4857
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004858 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004859 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004860 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004861 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004862 goto theend;
4863 }
4864
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004865 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004866 {
4867 if (oplen > 1 && !heredoc)
4868 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004869 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004870 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4871 name);
4872 goto theend;
4873 }
4874
4875 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004876 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004877 goto theend;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004878 lvar = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4879 if (lvar == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004880 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004881 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004882 }
4883
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004884 member_type = type;
4885 if (var_end > arg + varlen)
4886 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004887 // Something follows after the variable: "var[idx]".
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004888 if (is_decl)
4889 {
4890 emsg(_("E1087: cannot use an index when declaring a variable"));
4891 goto theend;
4892 }
4893
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004894 if (arg[varlen] == '[')
4895 {
4896 has_index = TRUE;
4897 if (type->tt_member == NULL)
4898 {
4899 semsg(_("E1088: cannot use an index on %s"), name);
4900 goto theend;
4901 }
4902 member_type = type->tt_member;
4903 }
4904 else
4905 {
4906 semsg("Not supported yet: %s", arg);
4907 goto theend;
4908 }
4909 }
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004910 else if (lvar == &arg_lvar)
4911 {
4912 semsg(_("E1090: Cannot assign to argument %s"), name);
4913 goto theend;
4914 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004915
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004916 if (heredoc)
4917 {
4918 list_T *l;
4919 listitem_T *li;
4920
4921 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02004922 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004923 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004924 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004925
4926 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004927 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004928 {
4929 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4930 li->li_tv.vval.v_string = NULL;
4931 }
4932 generate_NEWLIST(cctx, l->lv_len);
4933 type = &t_list_string;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004934 member_type = &t_list_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004935 list_free(l);
4936 p += STRLEN(p);
4937 }
4938 else if (oplen > 0)
4939 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004940 int r;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004941
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004942 // for "+=", "*=", "..=" etc. first load the current value
4943 if (*op != '=')
4944 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004945 generate_loadvar(cctx, dest, name, lvar, type);
4946
4947 if (has_index)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004948 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004949 // TODO: get member from list or dict
4950 emsg("Index with operation not supported yet");
4951 goto theend;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004952 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004953 }
4954
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004955 // Compile the expression. Temporarily hide the new local variable
4956 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004957 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004958 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004959 instr_count = instr->ga_len;
4960 p = skipwhite(p + oplen);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004961 r = compile_expr0(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004962 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004963 ++cctx->ctx_locals.ga_len;
4964 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004965 goto theend;
4966
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004967 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004968 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004969 type_T *stacktype;
4970
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004971 stacktype = stack->ga_len == 0 ? &t_void
4972 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004973 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004974 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004975 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004976 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004977 if (stacktype->tt_type == VAR_VOID)
4978 {
4979 emsg(_("E1031: Cannot use void value"));
4980 goto theend;
4981 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004982 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004983 {
4984 // An empty list or dict has a &t_void member, for a
4985 // variable that implies &t_any.
4986 if (stacktype == &t_list_empty)
4987 lvar->lv_type = &t_list_any;
4988 else if (stacktype == &t_dict_empty)
4989 lvar->lv_type = &t_dict_any;
4990 else
4991 lvar->lv_type = stacktype;
4992 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004993 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004994 else
4995 {
4996 type_T *use_type = lvar->lv_type;
4997
4998 if (has_index)
4999 {
5000 use_type = use_type->tt_member;
5001 if (use_type == NULL)
5002 use_type = &t_void;
5003 }
5004 if (need_type(stacktype, use_type, -1, cctx) == FAIL)
5005 goto theend;
5006 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005007 }
Bram Moolenaara6e67e42020-05-15 23:36:40 +02005008 else if (*p != '=' && need_type(stacktype, member_type, -1,
5009 cctx) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005010 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005011 }
5012 }
5013 else if (cmdidx == CMD_const)
5014 {
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02005015 emsg(_(e_const_req_value));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005016 goto theend;
5017 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005018 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005019 {
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02005020 emsg(_(e_type_req));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005021 goto theend;
5022 }
5023 else
5024 {
5025 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005026 if (ga_grow(instr, 1) == FAIL)
5027 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005028 switch (member_type->tt_type)
Bram Moolenaar04d05222020-02-06 22:06:54 +01005029 {
5030 case VAR_BOOL:
5031 generate_PUSHBOOL(cctx, VVAL_FALSE);
5032 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01005033 case VAR_FLOAT:
5034#ifdef FEAT_FLOAT
5035 generate_PUSHF(cctx, 0.0);
5036#endif
5037 break;
5038 case VAR_STRING:
5039 generate_PUSHS(cctx, NULL);
5040 break;
5041 case VAR_BLOB:
5042 generate_PUSHBLOB(cctx, NULL);
5043 break;
5044 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005045 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01005046 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01005047 case VAR_LIST:
5048 generate_NEWLIST(cctx, 0);
5049 break;
5050 case VAR_DICT:
5051 generate_NEWDICT(cctx, 0);
5052 break;
5053 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005054 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01005055 break;
5056 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005057 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01005058 break;
5059 case VAR_NUMBER:
5060 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02005061 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02005062 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01005063 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02005064 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01005065 generate_PUSHNR(cctx, 0);
5066 break;
5067 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005068 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005069 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005070
5071 if (oplen > 0 && *op != '=')
5072 {
5073 type_T *expected = &t_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005074 type_T *stacktype;
5075
5076 // TODO: if type is known use float or any operation
5077
5078 if (*op == '.')
5079 expected = &t_string;
5080 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5081 if (need_type(stacktype, expected, -1, cctx) == FAIL)
5082 goto theend;
5083
5084 if (*op == '.')
5085 generate_instr_drop(cctx, ISN_CONCAT, 1);
5086 else
5087 {
5088 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
5089
5090 if (isn == NULL)
5091 goto theend;
5092 switch (*op)
5093 {
5094 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
5095 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
5096 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
5097 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
5098 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
5099 }
5100 }
5101 }
5102
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005103 if (has_index)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005104 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005105 int r;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005106
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005107 // Compile the "idx" in "var[idx]".
5108 if (new_local)
5109 --cctx->ctx_locals.ga_len;
5110 p = skipwhite(arg + varlen + 1);
5111 r = compile_expr0(&p, cctx);
5112 if (new_local)
5113 ++cctx->ctx_locals.ga_len;
5114 if (r == FAIL)
5115 goto theend;
5116 if (*skipwhite(p) != ']')
5117 {
5118 emsg(_(e_missbrac));
5119 goto theend;
5120 }
5121 if (type->tt_type == VAR_DICT
5122 && may_generate_2STRING(-1, cctx) == FAIL)
5123 goto theend;
5124 if (type->tt_type == VAR_LIST
5125 && ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type
5126 != VAR_NUMBER)
5127 {
5128 emsg(_(e_number_exp));
5129 goto theend;
5130 }
5131
5132 // Load the dict or list. On the stack we then have:
5133 // - value
5134 // - index
5135 // - variable
5136 generate_loadvar(cctx, dest, name, lvar, type);
5137
5138 if (type->tt_type == VAR_LIST)
5139 {
5140 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL)
5141 return FAIL;
5142 }
5143 else if (type->tt_type == VAR_DICT)
5144 {
5145 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL)
5146 return FAIL;
5147 }
5148 else
5149 {
5150 emsg(_(e_listreq));
5151 goto theend;
5152 }
5153 }
5154 else
5155 {
5156 switch (dest)
5157 {
5158 case dest_option:
5159 generate_STOREOPT(cctx, name + 1, opt_flags);
5160 break;
5161 case dest_global:
5162 // include g: with the name, easier to execute that way
5163 generate_STORE(cctx, ISN_STOREG, 0, name);
5164 break;
5165 case dest_buffer:
5166 // include b: with the name, easier to execute that way
5167 generate_STORE(cctx, ISN_STOREB, 0, name);
5168 break;
5169 case dest_window:
5170 // include w: with the name, easier to execute that way
5171 generate_STORE(cctx, ISN_STOREW, 0, name);
5172 break;
5173 case dest_tab:
5174 // include t: with the name, easier to execute that way
5175 generate_STORE(cctx, ISN_STORET, 0, name);
5176 break;
5177 case dest_env:
5178 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5179 break;
5180 case dest_reg:
5181 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5182 break;
5183 case dest_vimvar:
5184 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5185 break;
5186 case dest_script:
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005187 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005188 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5189 imported_T *import = NULL;
5190 int sid = current_sctx.sc_sid;
5191 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005192
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005193 if (name[1] != ':')
5194 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005195 import = find_imported(name, 0, cctx);
5196 if (import != NULL)
5197 sid = import->imp_sid;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005198 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005199
5200 idx = get_script_item_idx(sid, rawname, TRUE);
5201 // TODO: specific type
5202 if (idx < 0)
5203 {
5204 char_u *name_s = name;
5205
5206 // Include s: in the name for store_var()
5207 if (name[1] != ':')
5208 {
5209 int len = (int)STRLEN(name) + 3;
5210
5211 name_s = alloc(len);
5212 if (name_s == NULL)
5213 name_s = name;
5214 else
5215 vim_snprintf((char *)name_s, len, "s:%s", name);
5216 }
5217 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid,
5218 &t_any);
5219 if (name_s != name)
5220 vim_free(name_s);
5221 }
5222 else
5223 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005224 sid, idx, &t_any);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005225 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005226 break;
5227 case dest_local:
5228 if (lvar != NULL)
5229 {
5230 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
5231
5232 // optimization: turn "var = 123" from ISN_PUSHNR +
5233 // ISN_STORE into ISN_STORENR
5234 if (!lvar->lv_from_outer && instr->ga_len == instr_count + 1
5235 && isn->isn_type == ISN_PUSHNR)
5236 {
5237 varnumber_T val = isn->isn_arg.number;
5238
5239 isn->isn_type = ISN_STORENR;
5240 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
5241 isn->isn_arg.storenr.stnr_val = val;
5242 if (stack->ga_len > 0)
5243 --stack->ga_len;
5244 }
5245 else if (lvar->lv_from_outer)
5246 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx,
5247 NULL);
5248 else
5249 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5250 }
5251 break;
5252 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005253 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005254 ret = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005255
5256theend:
5257 vim_free(name);
5258 return ret;
5259}
5260
5261/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005262 * Check if "name" can be "unlet".
5263 */
5264 int
5265check_vim9_unlet(char_u *name)
5266{
5267 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
5268 {
5269 semsg(_("E1081: Cannot unlet %s"), name);
5270 return FAIL;
5271 }
5272 return OK;
5273}
5274
5275/*
5276 * Callback passed to ex_unletlock().
5277 */
5278 static int
5279compile_unlet(
5280 lval_T *lvp,
5281 char_u *name_end,
5282 exarg_T *eap,
5283 int deep UNUSED,
5284 void *coookie)
5285{
5286 cctx_T *cctx = coookie;
5287
5288 if (lvp->ll_tv == NULL)
5289 {
5290 char_u *p = lvp->ll_name;
5291 int cc = *name_end;
5292 int ret = OK;
5293
5294 // Normal name. Only supports g:, w:, t: and b: namespaces.
5295 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005296 if (*p == '$')
5297 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
5298 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005299 ret = FAIL;
5300 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005301 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005302
5303 *name_end = cc;
5304 return ret;
5305 }
5306
5307 // TODO: unlet {list}[idx]
5308 // TODO: unlet {dict}[key]
5309 emsg("Sorry, :unlet not fully implemented yet");
5310 return FAIL;
5311}
5312
5313/*
5314 * compile "unlet var", "lock var" and "unlock var"
5315 * "arg" points to "var".
5316 */
5317 static char_u *
5318compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
5319{
5320 char_u *p = arg;
5321
5322 if (eap->cmdidx != CMD_unlet)
5323 {
5324 emsg("Sorry, :lock and unlock not implemented yet");
5325 return NULL;
5326 }
5327
5328 if (*p == '!')
5329 {
5330 p = skipwhite(p + 1);
5331 eap->forceit = TRUE;
5332 }
5333
5334 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
5335 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5336}
5337
5338/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005339 * Compile an :import command.
5340 */
5341 static char_u *
5342compile_import(char_u *arg, cctx_T *cctx)
5343{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01005344 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005345}
5346
5347/*
5348 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
5349 */
5350 static int
5351compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
5352{
5353 garray_T *instr = &cctx->ctx_instr;
5354 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
5355
5356 if (endlabel == NULL)
5357 return FAIL;
5358 endlabel->el_next = *el;
5359 *el = endlabel;
5360 endlabel->el_end_label = instr->ga_len;
5361
5362 generate_JUMP(cctx, when, 0);
5363 return OK;
5364}
5365
5366 static void
5367compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
5368{
5369 garray_T *instr = &cctx->ctx_instr;
5370
5371 while (*el != NULL)
5372 {
5373 endlabel_T *cur = (*el);
5374 isn_T *isn;
5375
5376 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
5377 isn->isn_arg.jump.jump_where = instr->ga_len;
5378 *el = cur->el_next;
5379 vim_free(cur);
5380 }
5381}
5382
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005383 static void
5384compile_free_jump_to_end(endlabel_T **el)
5385{
5386 while (*el != NULL)
5387 {
5388 endlabel_T *cur = (*el);
5389
5390 *el = cur->el_next;
5391 vim_free(cur);
5392 }
5393}
5394
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005395/*
5396 * Create a new scope and set up the generic items.
5397 */
5398 static scope_T *
5399new_scope(cctx_T *cctx, scopetype_T type)
5400{
5401 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
5402
5403 if (scope == NULL)
5404 return NULL;
5405 scope->se_outer = cctx->ctx_scope;
5406 cctx->ctx_scope = scope;
5407 scope->se_type = type;
5408 scope->se_local_count = cctx->ctx_locals.ga_len;
5409 return scope;
5410}
5411
5412/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005413 * Free the current scope and go back to the outer scope.
5414 */
5415 static void
5416drop_scope(cctx_T *cctx)
5417{
5418 scope_T *scope = cctx->ctx_scope;
5419
5420 if (scope == NULL)
5421 {
5422 iemsg("calling drop_scope() without a scope");
5423 return;
5424 }
5425 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005426 switch (scope->se_type)
5427 {
5428 case IF_SCOPE:
5429 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
5430 case FOR_SCOPE:
5431 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
5432 case WHILE_SCOPE:
5433 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
5434 case TRY_SCOPE:
5435 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
5436 case NO_SCOPE:
5437 case BLOCK_SCOPE:
5438 break;
5439 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005440 vim_free(scope);
5441}
5442
5443/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005444 * compile "if expr"
5445 *
5446 * "if expr" Produces instructions:
5447 * EVAL expr Push result of "expr"
5448 * JUMP_IF_FALSE end
5449 * ... body ...
5450 * end:
5451 *
5452 * "if expr | else" Produces instructions:
5453 * EVAL expr Push result of "expr"
5454 * JUMP_IF_FALSE else
5455 * ... body ...
5456 * JUMP_ALWAYS end
5457 * else:
5458 * ... body ...
5459 * end:
5460 *
5461 * "if expr1 | elseif expr2 | else" Produces instructions:
5462 * EVAL expr Push result of "expr"
5463 * JUMP_IF_FALSE elseif
5464 * ... body ...
5465 * JUMP_ALWAYS end
5466 * elseif:
5467 * EVAL expr Push result of "expr"
5468 * JUMP_IF_FALSE else
5469 * ... body ...
5470 * JUMP_ALWAYS end
5471 * else:
5472 * ... body ...
5473 * end:
5474 */
5475 static char_u *
5476compile_if(char_u *arg, cctx_T *cctx)
5477{
5478 char_u *p = arg;
5479 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005480 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005481 scope_T *scope;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005482 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005483
Bram Moolenaara5565e42020-05-09 15:44:01 +02005484 CLEAR_FIELD(ppconst);
5485 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005486 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02005487 clear_ppconst(&ppconst);
5488 return NULL;
5489 }
5490 if (instr->ga_len == instr_count && ppconst.pp_used == 1)
5491 {
5492 // The expression results in a constant.
5493 // TODO: how about nesting?
5494 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? FALSE : TRUE;
5495 clear_ppconst(&ppconst);
5496 }
5497 else
5498 {
5499 // Not a constant, generate instructions for the expression.
5500 cctx->ctx_skip = MAYBE;
5501 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005502 return NULL;
5503 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005504
5505 scope = new_scope(cctx, IF_SCOPE);
5506 if (scope == NULL)
5507 return NULL;
5508
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005509 if (cctx->ctx_skip == MAYBE)
5510 {
5511 // "where" is set when ":elseif", "else" or ":endif" is found
5512 scope->se_u.se_if.is_if_label = instr->ga_len;
5513 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5514 }
5515 else
5516 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005517
5518 return p;
5519}
5520
5521 static char_u *
5522compile_elseif(char_u *arg, cctx_T *cctx)
5523{
5524 char_u *p = arg;
5525 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005526 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005527 isn_T *isn;
5528 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005529 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005530
5531 if (scope == NULL || scope->se_type != IF_SCOPE)
5532 {
5533 emsg(_(e_elseif_without_if));
5534 return NULL;
5535 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005536 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005537
Bram Moolenaar158906c2020-02-06 20:39:45 +01005538 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005539 {
5540 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005541 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005542 return NULL;
5543 // previous "if" or "elseif" jumps here
5544 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5545 isn->isn_arg.jump.jump_where = instr->ga_len;
5546 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005547
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005548 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02005549 CLEAR_FIELD(ppconst);
5550 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005551 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02005552 clear_ppconst(&ppconst);
5553 return NULL;
5554 }
5555 if (instr->ga_len == instr_count && ppconst.pp_used == 1)
5556 {
5557 // The expression results in a constant.
5558 // TODO: how about nesting?
5559 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? FALSE : TRUE;
5560 clear_ppconst(&ppconst);
5561 scope->se_u.se_if.is_if_label = -1;
5562 }
5563 else
5564 {
5565 // Not a constant, generate instructions for the expression.
5566 cctx->ctx_skip = MAYBE;
5567 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005568 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005569
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005570 // "where" is set when ":elseif", "else" or ":endif" is found
5571 scope->se_u.se_if.is_if_label = instr->ga_len;
5572 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5573 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005574
5575 return p;
5576}
5577
5578 static char_u *
5579compile_else(char_u *arg, cctx_T *cctx)
5580{
5581 char_u *p = arg;
5582 garray_T *instr = &cctx->ctx_instr;
5583 isn_T *isn;
5584 scope_T *scope = cctx->ctx_scope;
5585
5586 if (scope == NULL || scope->se_type != IF_SCOPE)
5587 {
5588 emsg(_(e_else_without_if));
5589 return NULL;
5590 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005591 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005592
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005593 // jump from previous block to the end, unless the else block is empty
5594 if (cctx->ctx_skip == MAYBE)
5595 {
5596 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005597 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005598 return NULL;
5599 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005600
Bram Moolenaar158906c2020-02-06 20:39:45 +01005601 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005602 {
5603 if (scope->se_u.se_if.is_if_label >= 0)
5604 {
5605 // previous "if" or "elseif" jumps here
5606 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5607 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005608 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005609 }
5610 }
5611
5612 if (cctx->ctx_skip != MAYBE)
5613 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005614
5615 return p;
5616}
5617
5618 static char_u *
5619compile_endif(char_u *arg, cctx_T *cctx)
5620{
5621 scope_T *scope = cctx->ctx_scope;
5622 ifscope_T *ifscope;
5623 garray_T *instr = &cctx->ctx_instr;
5624 isn_T *isn;
5625
5626 if (scope == NULL || scope->se_type != IF_SCOPE)
5627 {
5628 emsg(_(e_endif_without_if));
5629 return NULL;
5630 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005631 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005632 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005633
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005634 if (scope->se_u.se_if.is_if_label >= 0)
5635 {
5636 // previous "if" or "elseif" jumps here
5637 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5638 isn->isn_arg.jump.jump_where = instr->ga_len;
5639 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005640 // Fill in the "end" label in jumps at the end of the blocks.
5641 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005642 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005643
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005644 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005645 return arg;
5646}
5647
5648/*
5649 * compile "for var in expr"
5650 *
5651 * Produces instructions:
5652 * PUSHNR -1
5653 * STORE loop-idx Set index to -1
5654 * EVAL expr Push result of "expr"
5655 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5656 * - if beyond end, jump to "end"
5657 * - otherwise get item from list and push it
5658 * STORE var Store item in "var"
5659 * ... body ...
5660 * JUMP top Jump back to repeat
5661 * end: DROP Drop the result of "expr"
5662 *
5663 */
5664 static char_u *
5665compile_for(char_u *arg, cctx_T *cctx)
5666{
5667 char_u *p;
5668 size_t varlen;
5669 garray_T *instr = &cctx->ctx_instr;
5670 garray_T *stack = &cctx->ctx_type_stack;
5671 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005672 lvar_T *loop_lvar; // loop iteration variable
5673 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005674 type_T *vartype;
5675
5676 // TODO: list of variables: "for [key, value] in dict"
5677 // parse "var"
5678 for (p = arg; eval_isnamec1(*p); ++p)
5679 ;
5680 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005681 var_lvar = lookup_local(arg, varlen, cctx);
5682 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005683 {
5684 semsg(_("E1023: variable already defined: %s"), arg);
5685 return NULL;
5686 }
5687
5688 // consume "in"
5689 p = skipwhite(p);
5690 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5691 {
5692 emsg(_(e_missing_in));
5693 return NULL;
5694 }
5695 p = skipwhite(p + 2);
5696
5697
5698 scope = new_scope(cctx, FOR_SCOPE);
5699 if (scope == NULL)
5700 return NULL;
5701
5702 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005703 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5704 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005705 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005706 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005707 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005708 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005709 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005710
5711 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005712 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5713 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005714 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005715 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005716 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005717 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005718 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005719
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005720 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005721
5722 // compile "expr", it remains on the stack until "endfor"
5723 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005724 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005725 {
5726 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005727 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005728 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005729
5730 // now we know the type of "var"
5731 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5732 if (vartype->tt_type != VAR_LIST)
5733 {
5734 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005735 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005736 return NULL;
5737 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005738 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005739 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005740
5741 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005742 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005743
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005744 generate_FOR(cctx, loop_lvar->lv_idx);
5745 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005746
5747 return arg;
5748}
5749
5750/*
5751 * compile "endfor"
5752 */
5753 static char_u *
5754compile_endfor(char_u *arg, cctx_T *cctx)
5755{
5756 garray_T *instr = &cctx->ctx_instr;
5757 scope_T *scope = cctx->ctx_scope;
5758 forscope_T *forscope;
5759 isn_T *isn;
5760
5761 if (scope == NULL || scope->se_type != FOR_SCOPE)
5762 {
5763 emsg(_(e_for));
5764 return NULL;
5765 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005766 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005767 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005768 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005769
5770 // At end of ":for" scope jump back to the FOR instruction.
5771 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5772
5773 // Fill in the "end" label in the FOR statement so it can jump here
5774 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5775 isn->isn_arg.forloop.for_end = instr->ga_len;
5776
5777 // Fill in the "end" label any BREAK statements
5778 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5779
5780 // Below the ":for" scope drop the "expr" list from the stack.
5781 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5782 return NULL;
5783
5784 vim_free(scope);
5785
5786 return arg;
5787}
5788
5789/*
5790 * compile "while expr"
5791 *
5792 * Produces instructions:
5793 * top: EVAL expr Push result of "expr"
5794 * JUMP_IF_FALSE end jump if false
5795 * ... body ...
5796 * JUMP top Jump back to repeat
5797 * end:
5798 *
5799 */
5800 static char_u *
5801compile_while(char_u *arg, cctx_T *cctx)
5802{
5803 char_u *p = arg;
5804 garray_T *instr = &cctx->ctx_instr;
5805 scope_T *scope;
5806
5807 scope = new_scope(cctx, WHILE_SCOPE);
5808 if (scope == NULL)
5809 return NULL;
5810
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005811 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005812
5813 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02005814 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005815 return NULL;
5816
5817 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005818 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005819 JUMP_IF_FALSE, cctx) == FAIL)
5820 return FAIL;
5821
5822 return p;
5823}
5824
5825/*
5826 * compile "endwhile"
5827 */
5828 static char_u *
5829compile_endwhile(char_u *arg, cctx_T *cctx)
5830{
5831 scope_T *scope = cctx->ctx_scope;
5832
5833 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5834 {
5835 emsg(_(e_while));
5836 return NULL;
5837 }
5838 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005839 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005840
5841 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005842 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005843
5844 // Fill in the "end" label in the WHILE statement so it can jump here.
5845 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005846 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005847
5848 vim_free(scope);
5849
5850 return arg;
5851}
5852
5853/*
5854 * compile "continue"
5855 */
5856 static char_u *
5857compile_continue(char_u *arg, cctx_T *cctx)
5858{
5859 scope_T *scope = cctx->ctx_scope;
5860
5861 for (;;)
5862 {
5863 if (scope == NULL)
5864 {
5865 emsg(_(e_continue));
5866 return NULL;
5867 }
5868 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5869 break;
5870 scope = scope->se_outer;
5871 }
5872
5873 // Jump back to the FOR or WHILE instruction.
5874 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005875 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5876 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005877 return arg;
5878}
5879
5880/*
5881 * compile "break"
5882 */
5883 static char_u *
5884compile_break(char_u *arg, cctx_T *cctx)
5885{
5886 scope_T *scope = cctx->ctx_scope;
5887 endlabel_T **el;
5888
5889 for (;;)
5890 {
5891 if (scope == NULL)
5892 {
5893 emsg(_(e_break));
5894 return NULL;
5895 }
5896 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5897 break;
5898 scope = scope->se_outer;
5899 }
5900
5901 // Jump to the end of the FOR or WHILE loop.
5902 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005903 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005904 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005905 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005906 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5907 return FAIL;
5908
5909 return arg;
5910}
5911
5912/*
5913 * compile "{" start of block
5914 */
5915 static char_u *
5916compile_block(char_u *arg, cctx_T *cctx)
5917{
5918 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5919 return NULL;
5920 return skipwhite(arg + 1);
5921}
5922
5923/*
5924 * compile end of block: drop one scope
5925 */
5926 static void
5927compile_endblock(cctx_T *cctx)
5928{
5929 scope_T *scope = cctx->ctx_scope;
5930
5931 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005932 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005933 vim_free(scope);
5934}
5935
5936/*
5937 * compile "try"
5938 * Creates a new scope for the try-endtry, pointing to the first catch and
5939 * finally.
5940 * Creates another scope for the "try" block itself.
5941 * TRY instruction sets up exception handling at runtime.
5942 *
5943 * "try"
5944 * TRY -> catch1, -> finally push trystack entry
5945 * ... try block
5946 * "throw {exception}"
5947 * EVAL {exception}
5948 * THROW create exception
5949 * ... try block
5950 * " catch {expr}"
5951 * JUMP -> finally
5952 * catch1: PUSH exeception
5953 * EVAL {expr}
5954 * MATCH
5955 * JUMP nomatch -> catch2
5956 * CATCH remove exception
5957 * ... catch block
5958 * " catch"
5959 * JUMP -> finally
5960 * catch2: CATCH remove exception
5961 * ... catch block
5962 * " finally"
5963 * finally:
5964 * ... finally block
5965 * " endtry"
5966 * ENDTRY pop trystack entry, may rethrow
5967 */
5968 static char_u *
5969compile_try(char_u *arg, cctx_T *cctx)
5970{
5971 garray_T *instr = &cctx->ctx_instr;
5972 scope_T *try_scope;
5973 scope_T *scope;
5974
5975 // scope that holds the jumps that go to catch/finally/endtry
5976 try_scope = new_scope(cctx, TRY_SCOPE);
5977 if (try_scope == NULL)
5978 return NULL;
5979
5980 // "catch" is set when the first ":catch" is found.
5981 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005982 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005983 if (generate_instr(cctx, ISN_TRY) == NULL)
5984 return NULL;
5985
5986 // scope for the try block itself
5987 scope = new_scope(cctx, BLOCK_SCOPE);
5988 if (scope == NULL)
5989 return NULL;
5990
5991 return arg;
5992}
5993
5994/*
5995 * compile "catch {expr}"
5996 */
5997 static char_u *
5998compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5999{
6000 scope_T *scope = cctx->ctx_scope;
6001 garray_T *instr = &cctx->ctx_instr;
6002 char_u *p;
6003 isn_T *isn;
6004
6005 // end block scope from :try or :catch
6006 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6007 compile_endblock(cctx);
6008 scope = cctx->ctx_scope;
6009
6010 // Error if not in a :try scope
6011 if (scope == NULL || scope->se_type != TRY_SCOPE)
6012 {
6013 emsg(_(e_catch));
6014 return NULL;
6015 }
6016
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006017 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006018 {
6019 emsg(_("E1033: catch unreachable after catch-all"));
6020 return NULL;
6021 }
6022
6023 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006024 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006025 JUMP_ALWAYS, cctx) == FAIL)
6026 return NULL;
6027
6028 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006029 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006030 if (isn->isn_arg.try.try_catch == 0)
6031 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006032 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006033 {
6034 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006035 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006036 isn->isn_arg.jump.jump_where = instr->ga_len;
6037 }
6038
6039 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02006040 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006041 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006042 scope->se_u.se_try.ts_caught_all = TRUE;
6043 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006044 }
6045 else
6046 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006047 char_u *end;
6048 char_u *pat;
6049 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006050 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006051 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006052
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006053 // Push v:exception, push {expr} and MATCH
6054 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
6055
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006056 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006057 if (*end != *p)
6058 {
6059 semsg(_("E1067: Separator mismatch: %s"), p);
6060 vim_free(tofree);
6061 return FAIL;
6062 }
6063 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006064 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006065 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006066 len = (int)(end - tofree);
6067 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006068 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006069 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006070 if (pat == NULL)
6071 return FAIL;
6072 if (generate_PUSHS(cctx, pat) == FAIL)
6073 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006074
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006075 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
6076 return NULL;
6077
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006078 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006079 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
6080 return NULL;
6081 }
6082
6083 if (generate_instr(cctx, ISN_CATCH) == NULL)
6084 return NULL;
6085
6086 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6087 return NULL;
6088 return p;
6089}
6090
6091 static char_u *
6092compile_finally(char_u *arg, cctx_T *cctx)
6093{
6094 scope_T *scope = cctx->ctx_scope;
6095 garray_T *instr = &cctx->ctx_instr;
6096 isn_T *isn;
6097
6098 // end block scope from :try or :catch
6099 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6100 compile_endblock(cctx);
6101 scope = cctx->ctx_scope;
6102
6103 // Error if not in a :try scope
6104 if (scope == NULL || scope->se_type != TRY_SCOPE)
6105 {
6106 emsg(_(e_finally));
6107 return NULL;
6108 }
6109
6110 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006111 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006112 if (isn->isn_arg.try.try_finally != 0)
6113 {
6114 emsg(_(e_finally_dup));
6115 return NULL;
6116 }
6117
6118 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006119 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006120
Bram Moolenaar585fea72020-04-02 22:33:21 +02006121 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006122 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006123 {
6124 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006125 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006126 isn->isn_arg.jump.jump_where = instr->ga_len;
6127 }
6128
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006129 // TODO: set index in ts_finally_label jumps
6130
6131 return arg;
6132}
6133
6134 static char_u *
6135compile_endtry(char_u *arg, cctx_T *cctx)
6136{
6137 scope_T *scope = cctx->ctx_scope;
6138 garray_T *instr = &cctx->ctx_instr;
6139 isn_T *isn;
6140
6141 // end block scope from :catch or :finally
6142 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6143 compile_endblock(cctx);
6144 scope = cctx->ctx_scope;
6145
6146 // Error if not in a :try scope
6147 if (scope == NULL || scope->se_type != TRY_SCOPE)
6148 {
6149 if (scope == NULL)
6150 emsg(_(e_no_endtry));
6151 else if (scope->se_type == WHILE_SCOPE)
6152 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01006153 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006154 emsg(_(e_endfor));
6155 else
6156 emsg(_(e_endif));
6157 return NULL;
6158 }
6159
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006160 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006161 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
6162 {
6163 emsg(_("E1032: missing :catch or :finally"));
6164 return NULL;
6165 }
6166
6167 // Fill in the "end" label in jumps at the end of the blocks, if not done
6168 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006169 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006170
6171 // End :catch or :finally scope: set value in ISN_TRY instruction
6172 if (isn->isn_arg.try.try_finally == 0)
6173 isn->isn_arg.try.try_finally = instr->ga_len;
6174 compile_endblock(cctx);
6175
6176 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
6177 return NULL;
6178 return arg;
6179}
6180
6181/*
6182 * compile "throw {expr}"
6183 */
6184 static char_u *
6185compile_throw(char_u *arg, cctx_T *cctx UNUSED)
6186{
6187 char_u *p = skipwhite(arg);
6188
Bram Moolenaara5565e42020-05-09 15:44:01 +02006189 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006190 return NULL;
6191 if (may_generate_2STRING(-1, cctx) == FAIL)
6192 return NULL;
6193 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
6194 return NULL;
6195
6196 return p;
6197}
6198
6199/*
6200 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006201 * compile "echomsg expr"
6202 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01006203 * compile "execute expr"
6204 */
6205 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006206compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006207{
6208 char_u *p = arg;
6209 int count = 0;
6210
6211 for (;;)
6212 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006213 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006214 return NULL;
6215 ++count;
6216 p = skipwhite(p);
6217 if (ends_excmd(*p))
6218 break;
6219 }
6220
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006221 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
6222 generate_ECHO(cctx, cmdidx == CMD_echo, count);
6223 else if (cmdidx == CMD_execute)
6224 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
6225 else if (cmdidx == CMD_echomsg)
6226 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
6227 else
6228 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006229 return p;
6230}
6231
6232/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006233 * A command that is not compiled, execute with legacy code.
6234 */
6235 static char_u *
6236compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
6237{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006238 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006239 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006240
6241 if (cctx->ctx_skip == TRUE)
6242 goto theend;
6243
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006244 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
6245 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006246 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
6247 {
6248 // expand filename in "syntax include [@group] filename"
6249 has_expr = TRUE;
6250 eap->arg = skipwhite(eap->arg + 7);
6251 if (*eap->arg == '@')
6252 eap->arg = skiptowhite(eap->arg);
6253 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006254
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006255 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006256 {
6257 int count = 0;
6258 char_u *start = skipwhite(line);
6259
6260 // :cmd xxx`=expr1`yyy`=expr2`zzz
6261 // PUSHS ":cmd xxx"
6262 // eval expr1
6263 // PUSHS "yyy"
6264 // eval expr2
6265 // PUSHS "zzz"
6266 // EXECCONCAT 5
6267 for (;;)
6268 {
6269 if (p > start)
6270 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02006271 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006272 ++count;
6273 }
6274 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006275 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006276 return NULL;
6277 may_generate_2STRING(-1, cctx);
6278 ++count;
6279 p = skipwhite(p);
6280 if (*p != '`')
6281 {
6282 emsg(_("E1083: missing backtick"));
6283 return NULL;
6284 }
6285 start = p + 1;
6286
6287 p = (char_u *)strstr((char *)start, "`=");
6288 if (p == NULL)
6289 {
6290 if (*skipwhite(start) != NUL)
6291 {
6292 generate_PUSHS(cctx, vim_strsave(start));
6293 ++count;
6294 }
6295 break;
6296 }
6297 }
6298 generate_EXECCONCAT(cctx, count);
6299 }
6300 else
6301 generate_EXEC(cctx, line);
6302
6303theend:
6304 return (char_u *)"";
6305}
6306
6307/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02006308 * Add a function to the list of :def functions.
6309 * This "sets ufunc->uf_dfunc_idx" but the function isn't compiled yet.
6310 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02006311 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02006312add_def_function(ufunc_T *ufunc)
6313{
6314 dfunc_T *dfunc;
6315
6316 // Add the function to "def_functions".
6317 if (ga_grow(&def_functions, 1) == FAIL)
6318 return FAIL;
6319 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
6320 CLEAR_POINTER(dfunc);
6321 dfunc->df_idx = def_functions.ga_len;
6322 ufunc->uf_dfunc_idx = dfunc->df_idx;
6323 dfunc->df_ufunc = ufunc;
6324 ++def_functions.ga_len;
6325 return OK;
6326}
6327
6328/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006329 * After ex_function() has collected all the function lines: parse and compile
6330 * the lines into instructions.
6331 * Adds the function to "def_functions".
6332 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
6333 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006334 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006335 * This can be used recursively through compile_lambda(), which may reallocate
6336 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02006337 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006338 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02006339 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006340compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006341{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006342 char_u *line = NULL;
6343 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006344 char *errormsg = NULL; // error message
6345 int had_return = FALSE;
6346 cctx_T cctx;
6347 garray_T *instr;
6348 int called_emsg_before = called_emsg;
6349 int ret = FAIL;
6350 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006351 int do_estack_push;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006352 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006353
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006354 // When using a function that was compiled before: Free old instructions.
6355 // Otherwise add a new entry in "def_functions".
Bram Moolenaar09689a02020-05-09 22:50:08 +02006356 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006357 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02006358 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6359 + ufunc->uf_dfunc_idx;
Bram Moolenaar09689a02020-05-09 22:50:08 +02006360 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006361 }
Bram Moolenaar09689a02020-05-09 22:50:08 +02006362 else if (add_def_function(ufunc) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02006363 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006364
Bram Moolenaara80faa82020-04-12 19:37:17 +02006365 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006366 cctx.ctx_ufunc = ufunc;
6367 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006368 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006369 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
6370 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
6371 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
6372 cctx.ctx_type_list = &ufunc->uf_type_list;
6373 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
6374 instr = &cctx.ctx_instr;
6375
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006376 // Set the context to the function, it may be compiled when called from
6377 // another script. Set the script version to the most modern one.
6378 // The line number will be set in next_line_from_context().
6379 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006380 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
6381
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006382 // Make sure error messages are OK.
6383 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
6384 if (do_estack_push)
6385 estack_push_ufunc(ufunc, 1);
6386
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006387 if (ufunc->uf_def_args.ga_len > 0)
6388 {
6389 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006390 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006391 int i;
6392 char_u *arg;
6393 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
6394
6395 // Produce instructions for the default values of optional arguments.
6396 // Store the instruction index in uf_def_arg_idx[] so that we know
6397 // where to start when the function is called, depending on the number
6398 // of arguments.
6399 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
6400 if (ufunc->uf_def_arg_idx == NULL)
6401 goto erret;
6402 for (i = 0; i < count; ++i)
6403 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006404 garray_T *stack = &cctx.ctx_type_stack;
6405 type_T *val_type;
6406 int arg_idx = first_def_arg + i;
6407
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006408 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6409 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02006410 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006411 goto erret;
6412
6413 // If no type specified use the type of the default value.
6414 // Otherwise check that the default value type matches the
6415 // specified type.
6416 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6417 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6418 ufunc->uf_arg_types[arg_idx] = val_type;
6419 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6420 == FAIL)
6421 {
6422 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6423 arg_idx + 1);
6424 goto erret;
6425 }
6426
6427 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006428 goto erret;
6429 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006430 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6431 }
6432
6433 /*
6434 * Loop over all the lines of the function and generate instructions.
6435 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006436 for (;;)
6437 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006438 exarg_T ea;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006439 int starts_with_colon = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006440
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006441 // Bail out on the first error to avoid a flood of errors and report
6442 // the right line number when inside try/catch.
6443 if (emsg_before != called_emsg)
6444 goto erret;
6445
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006446 if (line != NULL && *line == '|')
6447 // the line continues after a '|'
6448 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006449 else if (line != NULL && *line != NUL
6450 && !(*line == '#' && (line == cctx.ctx_line_start
6451 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006452 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006453 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006454 goto erret;
6455 }
6456 else
6457 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006458 line = next_line_from_context(&cctx);
6459 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006460 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006461 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006462 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006463 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006464
6465 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006466 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006467 ea.cmdlinep = &line;
6468 ea.cmd = skipwhite(line);
6469
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006470 // Some things can be recognized by the first character.
6471 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006472 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006473 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006474 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006475 if (ea.cmd[1] != '{')
6476 {
6477 line = (char_u *)"";
6478 continue;
6479 }
6480 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006481
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006482 case '}':
6483 {
6484 // "}" ends a block scope
6485 scopetype_T stype = cctx.ctx_scope == NULL
6486 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006487
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006488 if (stype == BLOCK_SCOPE)
6489 {
6490 compile_endblock(&cctx);
6491 line = ea.cmd;
6492 }
6493 else
6494 {
6495 emsg(_("E1025: using } outside of a block scope"));
6496 goto erret;
6497 }
6498 if (line != NULL)
6499 line = skipwhite(ea.cmd + 1);
6500 continue;
6501 }
6502
6503 case '{':
6504 // "{" starts a block scope
6505 // "{'a': 1}->func() is something else
6506 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6507 {
6508 line = compile_block(ea.cmd, &cctx);
6509 continue;
6510 }
6511 break;
6512
6513 case ':':
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006514 starts_with_colon = TRUE;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006515 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006516 }
6517
6518 /*
6519 * COMMAND MODIFIERS
6520 */
6521 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6522 {
6523 if (errormsg != NULL)
6524 goto erret;
6525 // empty line or comment
6526 line = (char_u *)"";
6527 continue;
6528 }
6529
6530 // Skip ":call" to get to the function name.
6531 if (checkforcmd(&ea.cmd, "call", 3))
6532 ea.cmd = skipwhite(ea.cmd);
6533
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006534 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006535 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006536 char_u *pskip;
6537
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006538 // Assuming the command starts with a variable or function name,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006539 // find what follows.
6540 // Skip over "var.member", "var[idx]" and the like.
6541 // Also "&opt = val", "$ENV = val" and "@r = val".
6542 pskip = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006543 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006544 p = to_name_end(pskip, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006545 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006546 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006547 char_u *var_end;
6548 int oplen;
6549 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006550
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006551 var_end = find_name_end(pskip, NULL, NULL,
6552 FNE_CHECK_START | FNE_INCL_BR);
6553 oplen = assignment_len(skipwhite(var_end), &heredoc);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006554 if (oplen > 0)
6555 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006556 size_t len = p - ea.cmd;
6557
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006558 // Recognize an assignment if we recognize the variable
6559 // name:
6560 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006561 // "local = expr" where "local" is a local var.
6562 // "script = expr" where "script" is a script-local var.
6563 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006564 // "&opt = expr"
6565 // "$ENV = expr"
6566 // "@r = expr"
6567 if (*ea.cmd == '&'
6568 || *ea.cmd == '$'
6569 || *ea.cmd == '@'
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006570 || ((len) > 2 && ea.cmd[1] == ':')
6571 || lookup_local(ea.cmd, len, &cctx) != NULL
6572 || lookup_arg(ea.cmd, len, NULL, NULL,
6573 NULL, &cctx) == OK
6574 || lookup_script(ea.cmd, len) == OK
6575 || find_imported(ea.cmd, len, &cctx) != NULL)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006576 {
6577 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6578 if (line == NULL)
6579 goto erret;
6580 continue;
6581 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006582 }
6583 }
6584 }
6585
6586 /*
6587 * COMMAND after range
6588 */
6589 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006590 p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006591 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006592 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006593
6594 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6595 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006596 if (cctx.ctx_skip == TRUE)
6597 {
6598 line += STRLEN(line);
6599 continue;
6600 }
6601
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006602 // Expression or function call.
6603 if (ea.cmdidx == CMD_eval)
6604 {
6605 p = ea.cmd;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006606 if (compile_expr0(&p, &cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006607 goto erret;
6608
6609 // drop the return value
6610 generate_instr_drop(&cctx, ISN_DROP, 1);
6611 line = p;
6612 continue;
6613 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006614 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006615 iemsg("Command from find_ex_command() not handled");
6616 goto erret;
6617 }
6618
6619 p = skipwhite(p);
6620
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006621 if (cctx.ctx_skip == TRUE
6622 && ea.cmdidx != CMD_elseif
6623 && ea.cmdidx != CMD_else
6624 && ea.cmdidx != CMD_endif)
6625 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006626 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006627 continue;
6628 }
6629
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006630 switch (ea.cmdidx)
6631 {
6632 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006633 ea.arg = p;
6634 line = compile_nested_function(&ea, &cctx);
6635 break;
6636
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006637 case CMD_function:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006638 emsg(_("E1086: Cannot use :function inside :def"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006639 goto erret;
6640
6641 case CMD_return:
6642 line = compile_return(p, set_return_type, &cctx);
6643 had_return = TRUE;
6644 break;
6645
6646 case CMD_let:
6647 case CMD_const:
6648 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6649 break;
6650
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006651 case CMD_unlet:
6652 case CMD_unlockvar:
6653 case CMD_lockvar:
6654 line = compile_unletlock(p, &ea, &cctx);
6655 break;
6656
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006657 case CMD_import:
6658 line = compile_import(p, &cctx);
6659 break;
6660
6661 case CMD_if:
6662 line = compile_if(p, &cctx);
6663 break;
6664 case CMD_elseif:
6665 line = compile_elseif(p, &cctx);
6666 break;
6667 case CMD_else:
6668 line = compile_else(p, &cctx);
6669 break;
6670 case CMD_endif:
6671 line = compile_endif(p, &cctx);
6672 break;
6673
6674 case CMD_while:
6675 line = compile_while(p, &cctx);
6676 break;
6677 case CMD_endwhile:
6678 line = compile_endwhile(p, &cctx);
6679 break;
6680
6681 case CMD_for:
6682 line = compile_for(p, &cctx);
6683 break;
6684 case CMD_endfor:
6685 line = compile_endfor(p, &cctx);
6686 break;
6687 case CMD_continue:
6688 line = compile_continue(p, &cctx);
6689 break;
6690 case CMD_break:
6691 line = compile_break(p, &cctx);
6692 break;
6693
6694 case CMD_try:
6695 line = compile_try(p, &cctx);
6696 break;
6697 case CMD_catch:
6698 line = compile_catch(p, &cctx);
6699 break;
6700 case CMD_finally:
6701 line = compile_finally(p, &cctx);
6702 break;
6703 case CMD_endtry:
6704 line = compile_endtry(p, &cctx);
6705 break;
6706 case CMD_throw:
6707 line = compile_throw(p, &cctx);
6708 break;
6709
6710 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006711 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006712 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006713 case CMD_echomsg:
6714 case CMD_echoerr:
6715 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006716 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006717
6718 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006719 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006720 // Not recognized, execute with do_cmdline_cmd().
6721 ea.arg = p;
6722 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006723 break;
6724 }
6725 if (line == NULL)
6726 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006727 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006728
6729 if (cctx.ctx_type_stack.ga_len < 0)
6730 {
6731 iemsg("Type stack underflow");
6732 goto erret;
6733 }
6734 }
6735
6736 if (cctx.ctx_scope != NULL)
6737 {
6738 if (cctx.ctx_scope->se_type == IF_SCOPE)
6739 emsg(_(e_endif));
6740 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6741 emsg(_(e_endwhile));
6742 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6743 emsg(_(e_endfor));
6744 else
6745 emsg(_("E1026: Missing }"));
6746 goto erret;
6747 }
6748
6749 if (!had_return)
6750 {
6751 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6752 {
6753 emsg(_("E1027: Missing return statement"));
6754 goto erret;
6755 }
6756
6757 // Return zero if there is no return at the end.
6758 generate_PUSHNR(&cctx, 0);
6759 generate_instr(&cctx, ISN_RETURN);
6760 }
6761
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006762 {
6763 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6764 + ufunc->uf_dfunc_idx;
6765 dfunc->df_deleted = FALSE;
6766 dfunc->df_instr = instr->ga_data;
6767 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006768 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02006769 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006770 if (cctx.ctx_outer_used)
6771 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006772 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006773
6774 ret = OK;
6775
6776erret:
6777 if (ret == FAIL)
6778 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006779 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006780 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6781 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006782
6783 for (idx = 0; idx < instr->ga_len; ++idx)
6784 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006785 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006786
Bram Moolenaar45a15082020-05-25 00:28:33 +02006787 // if using the last entry in the table we might as well remove it
6788 if (!dfunc->df_deleted
6789 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006790 --def_functions.ga_len;
Bram Moolenaar45a15082020-05-25 00:28:33 +02006791 ufunc->uf_dfunc_idx = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006792
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006793 while (cctx.ctx_scope != NULL)
6794 drop_scope(&cctx);
6795
Bram Moolenaar20431c92020-03-20 18:39:46 +01006796 // Don't execute this function body.
6797 ga_clear_strings(&ufunc->uf_lines);
6798
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006799 if (errormsg != NULL)
6800 emsg(errormsg);
6801 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006802 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006803 }
6804
6805 current_sctx = save_current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006806 if (do_estack_push)
6807 estack_pop();
6808
Bram Moolenaar20431c92020-03-20 18:39:46 +01006809 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006810 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006811 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02006812 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006813}
6814
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02006815 void
6816set_function_type(ufunc_T *ufunc)
6817{
6818 int varargs = ufunc->uf_va_name != NULL;
6819 int argcount = ufunc->uf_args.ga_len;
6820
6821 // Create a type for the function, with the return type and any
6822 // argument types.
6823 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6824 // The type is included in "tt_args".
6825 if (argcount > 0 || varargs)
6826 {
6827 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6828 argcount, &ufunc->uf_type_list);
6829 // Add argument types to the function type.
6830 if (func_type_add_arg_types(ufunc->uf_func_type,
6831 argcount + varargs,
6832 &ufunc->uf_type_list) == FAIL)
6833 return;
6834 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6835 ufunc->uf_func_type->tt_min_argcount =
6836 argcount - ufunc->uf_def_args.ga_len;
6837 if (ufunc->uf_arg_types == NULL)
6838 {
6839 int i;
6840
6841 // lambda does not have argument types.
6842 for (i = 0; i < argcount; ++i)
6843 ufunc->uf_func_type->tt_args[i] = &t_any;
6844 }
6845 else
6846 mch_memmove(ufunc->uf_func_type->tt_args,
6847 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
6848 if (varargs)
6849 {
6850 ufunc->uf_func_type->tt_args[argcount] =
6851 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
6852 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6853 }
6854 }
6855 else
6856 // No arguments, can use a predefined type.
6857 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6858 argcount, &ufunc->uf_type_list);
6859}
6860
6861
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006862/*
6863 * Delete an instruction, free what it contains.
6864 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006865 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006866delete_instr(isn_T *isn)
6867{
6868 switch (isn->isn_type)
6869 {
6870 case ISN_EXEC:
6871 case ISN_LOADENV:
6872 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006873 case ISN_LOADB:
6874 case ISN_LOADW:
6875 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006876 case ISN_LOADOPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006877 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006878 case ISN_PUSHEXC:
6879 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006880 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006881 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006882 case ISN_STOREB:
6883 case ISN_STOREW:
6884 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006885 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006886 vim_free(isn->isn_arg.string);
6887 break;
6888
6889 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006890 case ISN_STORES:
6891 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006892 break;
6893
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006894 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006895 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006896 vim_free(isn->isn_arg.unlet.ul_name);
6897 break;
6898
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006899 case ISN_STOREOPT:
6900 vim_free(isn->isn_arg.storeopt.so_name);
6901 break;
6902
6903 case ISN_PUSHBLOB: // push blob isn_arg.blob
6904 blob_unref(isn->isn_arg.blob);
6905 break;
6906
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006907 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006908#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006909 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006910#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006911 break;
6912
6913 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006914#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006915 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006916#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006917 break;
6918
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006919 case ISN_UCALL:
6920 vim_free(isn->isn_arg.ufunc.cuf_name);
6921 break;
6922
Bram Moolenaar221fcc72020-05-05 19:46:20 +02006923 case ISN_FUNCREF:
6924 {
6925 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6926 + isn->isn_arg.funcref.fr_func;
6927 func_ptr_unref(dfunc->df_ufunc);
6928 }
6929 break;
6930
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006931 case ISN_2BOOL:
6932 case ISN_2STRING:
6933 case ISN_ADDBLOB:
6934 case ISN_ADDLIST:
6935 case ISN_BCALL:
6936 case ISN_CATCH:
6937 case ISN_CHECKNR:
6938 case ISN_CHECKTYPE:
6939 case ISN_COMPAREANY:
6940 case ISN_COMPAREBLOB:
6941 case ISN_COMPAREBOOL:
6942 case ISN_COMPAREDICT:
6943 case ISN_COMPAREFLOAT:
6944 case ISN_COMPAREFUNC:
6945 case ISN_COMPARELIST:
6946 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006947 case ISN_COMPARESPECIAL:
6948 case ISN_COMPARESTRING:
6949 case ISN_CONCAT:
6950 case ISN_DCALL:
6951 case ISN_DROP:
6952 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006953 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006954 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006955 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006956 case ISN_EXECCONCAT:
6957 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006958 case ISN_FOR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006959 case ISN_INDEX:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006960 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006961 case ISN_JUMP:
6962 case ISN_LOAD:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006963 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006964 case ISN_LOADSCRIPT:
6965 case ISN_LOADREG:
6966 case ISN_LOADV:
6967 case ISN_NEGATENR:
6968 case ISN_NEWDICT:
6969 case ISN_NEWLIST:
6970 case ISN_OPNR:
6971 case ISN_OPFLOAT:
6972 case ISN_OPANY:
6973 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006974 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006975 case ISN_PUSHF:
6976 case ISN_PUSHNR:
6977 case ISN_PUSHBOOL:
6978 case ISN_PUSHSPEC:
6979 case ISN_RETURN:
6980 case ISN_STORE:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02006981 case ISN_STOREOUTER:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006982 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006983 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006984 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006985 case ISN_STORESCRIPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006986 case ISN_STOREDICT:
6987 case ISN_STORELIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006988 case ISN_THROW:
6989 case ISN_TRY:
6990 // nothing allocated
6991 break;
6992 }
6993}
6994
6995/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006996 * Free all instructions for "dfunc".
6997 */
6998 static void
6999delete_def_function_contents(dfunc_T *dfunc)
7000{
7001 int idx;
7002
7003 ga_clear(&dfunc->df_def_args_isn);
7004
7005 if (dfunc->df_instr != NULL)
7006 {
7007 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
7008 delete_instr(dfunc->df_instr + idx);
7009 VIM_CLEAR(dfunc->df_instr);
7010 }
7011
7012 dfunc->df_deleted = TRUE;
7013}
7014
7015/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007016 * When a user function is deleted, delete any associated def function.
7017 */
7018 void
7019delete_def_function(ufunc_T *ufunc)
7020{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007021 if (ufunc->uf_dfunc_idx >= 0)
7022 {
7023 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7024 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007025
Bram Moolenaar20431c92020-03-20 18:39:46 +01007026 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007027 }
7028}
7029
7030#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01007031/*
7032 * Free all functions defined with ":def".
7033 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007034 void
7035free_def_functions(void)
7036{
Bram Moolenaar20431c92020-03-20 18:39:46 +01007037 int idx;
7038
7039 for (idx = 0; idx < def_functions.ga_len; ++idx)
7040 {
7041 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
7042
7043 delete_def_function_contents(dfunc);
7044 }
7045
7046 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007047}
7048#endif
7049
7050
7051#endif // FEAT_EVAL