blob: 7e700d5637a444eb239740d42d6ffb067d74338d [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 Moolenaar04b12692020-05-04 23:24:44 +0200104 int lv_func_idx; // for nested function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100105} lvar_T;
106
107/*
108 * Context for compiling lines of Vim script.
109 * Stores info about the local variables and condition stack.
110 */
111struct cctx_S {
112 ufunc_T *ctx_ufunc; // current function
113 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200114 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100115 garray_T ctx_instr; // generated instructions
116
117 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200118 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100119
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200120 int ctx_closure_count; // number of closures created in the
121 // function
122
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100123 garray_T ctx_imports; // imported items
124
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100125 int ctx_skip; // when TRUE skip commands, when FALSE skip
126 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100127 scope_T *ctx_scope; // current scope, NULL at toplevel
128
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200129 cctx_T *ctx_outer; // outer scope for lambda or nested
130 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200131 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200132
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100133 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200134 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135};
136
137static char e_var_notfound[] = N_("E1001: variable not found: %s");
138static char e_syntax_at[] = N_("E1002: Syntax error at %s");
139
140static int compile_expr1(char_u **arg, cctx_T *cctx);
141static int compile_expr2(char_u **arg, cctx_T *cctx);
142static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100143static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200144static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
145static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146
147/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200148 * Lookup variable "name" in the local scope and return it.
149 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100150 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200151 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152lookup_local(char_u *name, size_t len, cctx_T *cctx)
153{
154 int idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200155 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100156
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100157 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200158 return NULL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200159
160 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100161 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
162 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200163 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100164 if (STRNCMP(name, lvar->lv_name, len) == 0
165 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200166 {
167 lvar->lv_from_outer = FALSE;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200168 return lvar;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200169 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100170 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200171
172 // Find local in outer function scope.
173 if (cctx->ctx_outer != NULL)
174 {
175 lvar = lookup_local(name, len, cctx->ctx_outer);
176 if (lvar != NULL)
177 {
178 // TODO: are there situations we should not mark the outer scope as
179 // used?
180 cctx->ctx_outer_used = TRUE;
181 lvar->lv_from_outer = TRUE;
182 return lvar;
183 }
184 }
185
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200186 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100187}
188
189/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200190 * Lookup an argument in the current function and an enclosing function.
191 * Returns the argument index in "idxp"
192 * Returns the argument type in "type"
193 * Sets "gen_load_outer" to TRUE if found in outer scope.
194 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100195 */
196 static int
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200197lookup_arg(
198 char_u *name,
199 size_t len,
200 int *idxp,
201 type_T **type,
202 int *gen_load_outer,
203 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100204{
205 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200206 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100207
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100208 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200209 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100210 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
211 {
212 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
213
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200214 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
215 {
216 if (idxp != NULL)
217 {
218 // Arguments are located above the frame pointer. One further
219 // if there is a vararg argument
220 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
221 + STACK_FRAME_SIZE)
222 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
223
224 if (cctx->ctx_ufunc->uf_arg_types != NULL)
225 *type = cctx->ctx_ufunc->uf_arg_types[idx];
226 else
227 *type = &t_any;
228 }
229 return OK;
230 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100231 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100232
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200233 va_name = cctx->ctx_ufunc->uf_va_name;
234 if (va_name != NULL
235 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
236 {
237 if (idxp != NULL)
238 {
239 // varargs is always the last argument
240 *idxp = -STACK_FRAME_SIZE - 1;
241 *type = cctx->ctx_ufunc->uf_va_type;
242 }
243 return OK;
244 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100245
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200246 if (cctx->ctx_outer != NULL)
247 {
248 // Lookup the name for an argument of the outer function.
249 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
250 == OK)
251 {
252 *gen_load_outer = TRUE;
253 return OK;
254 }
255 }
256
257 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100258}
259
260/*
261 * Lookup a variable in the current script.
262 * Returns OK or FAIL.
263 */
264 static int
265lookup_script(char_u *name, size_t len)
266{
267 int cc;
268 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
269 dictitem_T *di;
270
271 cc = name[len];
272 name[len] = NUL;
273 di = find_var_in_ht(ht, 0, name, TRUE);
274 name[len] = cc;
275 return di == NULL ? FAIL: OK;
276}
277
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100278/*
279 * Check if "p[len]" is already defined, either in script "import_sid" or in
280 * compilation context "cctx".
281 * Return FAIL and give an error if it defined.
282 */
283 int
284check_defined(char_u *p, int len, cctx_T *cctx)
285{
286 if (lookup_script(p, len) == OK
287 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200288 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100289 || find_imported(p, len, cctx) != NULL)))
290 {
291 semsg("E1073: imported name already defined: %s", p);
292 return FAIL;
293 }
294 return OK;
295}
296
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200297/*
298 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
299 * be freed later.
300 */
301 static type_T *
302alloc_type(garray_T *type_gap)
303{
304 type_T *type;
305
306 if (ga_grow(type_gap, 1) == FAIL)
307 return NULL;
308 type = ALLOC_CLEAR_ONE(type_T);
309 if (type != NULL)
310 {
311 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
312 ++type_gap->ga_len;
313 }
314 return type;
315}
316
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100317 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200318get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100319{
320 type_T *type;
321
322 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200323 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100324 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200325 if (member_type->tt_type == VAR_VOID
326 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100327 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100328 if (member_type->tt_type == VAR_BOOL)
329 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100330 if (member_type->tt_type == VAR_NUMBER)
331 return &t_list_number;
332 if (member_type->tt_type == VAR_STRING)
333 return &t_list_string;
334
335 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200336 type = alloc_type(type_gap);
337 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100338 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100339 type->tt_type = VAR_LIST;
340 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200341 type->tt_argcount = 0;
342 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100343 return type;
344}
345
346 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200347get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100348{
349 type_T *type;
350
351 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200352 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100353 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200354 if (member_type->tt_type == VAR_VOID
355 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100356 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100357 if (member_type->tt_type == VAR_BOOL)
358 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100359 if (member_type->tt_type == VAR_NUMBER)
360 return &t_dict_number;
361 if (member_type->tt_type == VAR_STRING)
362 return &t_dict_string;
363
364 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200365 type = alloc_type(type_gap);
366 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100367 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100368 type->tt_type = VAR_DICT;
369 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200370 type->tt_argcount = 0;
371 type->tt_args = NULL;
372 return type;
373}
374
375/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200376 * Allocate a new type for a function.
377 */
378 static type_T *
379alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
380{
381 type_T *type = alloc_type(type_gap);
382
383 if (type == NULL)
384 return &t_any;
385 type->tt_type = VAR_FUNC;
386 type->tt_member = ret_type;
387 type->tt_argcount = argcount;
388 type->tt_args = NULL;
389 return type;
390}
391
392/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200393 * Get a function type, based on the return type "ret_type".
394 * If "argcount" is -1 or 0 a predefined type can be used.
395 * If "argcount" > 0 always create a new type, so that arguments can be added.
396 */
397 static type_T *
398get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
399{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200400 // recognize commonly used types
401 if (argcount <= 0)
402 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200403 if (ret_type == &t_unknown)
404 {
405 // (argcount == 0) is not possible
406 return &t_func_unknown;
407 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200408 if (ret_type == &t_void)
409 {
410 if (argcount == 0)
411 return &t_func_0_void;
412 else
413 return &t_func_void;
414 }
415 if (ret_type == &t_any)
416 {
417 if (argcount == 0)
418 return &t_func_0_any;
419 else
420 return &t_func_any;
421 }
422 if (ret_type == &t_number)
423 {
424 if (argcount == 0)
425 return &t_func_0_number;
426 else
427 return &t_func_number;
428 }
429 if (ret_type == &t_string)
430 {
431 if (argcount == 0)
432 return &t_func_0_string;
433 else
434 return &t_func_string;
435 }
436 }
437
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200438 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100439}
440
Bram Moolenaara8c17702020-04-01 21:17:24 +0200441/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200442 * For a function type, reserve space for "argcount" argument types (including
443 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200444 */
445 static int
446func_type_add_arg_types(
447 type_T *functype,
448 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200449 garray_T *type_gap)
450{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200451 // To make it easy to free the space needed for the argument types, add the
452 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200453 if (ga_grow(type_gap, 1) == FAIL)
454 return FAIL;
455 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
456 if (functype->tt_args == NULL)
457 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200458 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
459 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200460 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200461 return OK;
462}
463
464/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200465 * Return the type_T for a typval. Only for primitive types.
466 */
467 static type_T *
468typval2type(typval_T *tv)
469{
470 if (tv->v_type == VAR_NUMBER)
471 return &t_number;
472 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200473 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200474 if (tv->v_type == VAR_STRING)
475 return &t_string;
476 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
477 return &t_list_string;
478 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
479 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200480 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200481}
482
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200483 static void
484type_mismatch(type_T *expected, type_T *actual)
485{
486 char *tofree1, *tofree2;
487
488 semsg(_("E1013: type mismatch, expected %s but got %s"),
489 type_name(expected, &tofree1), type_name(actual, &tofree2));
490 vim_free(tofree1);
491 vim_free(tofree2);
492}
493
494 static void
495arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
496{
497 char *tofree1, *tofree2;
498
499 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
500 argidx,
501 type_name(expected, &tofree1), type_name(actual, &tofree2));
502 vim_free(tofree1);
503 vim_free(tofree2);
504}
505
506/*
507 * Check if the expected and actual types match.
508 * Does not allow for assigning "any" to a specific type.
509 */
510 static int
511check_type(type_T *expected, type_T *actual, int give_msg)
512{
513 int ret = OK;
514
515 // When expected is "unknown" we accept any actual type.
516 // When expected is "any" we accept any actual type except "void".
517 if (expected->tt_type != VAR_UNKNOWN
518 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
519
520 {
521 if (expected->tt_type != actual->tt_type)
522 {
523 if (give_msg)
524 type_mismatch(expected, actual);
525 return FAIL;
526 }
527 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
528 {
529 // "unknown" is used for an empty list or dict
530 if (actual->tt_member != &t_unknown)
531 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
532 }
533 else if (expected->tt_type == VAR_FUNC)
534 {
535 if (expected->tt_member != &t_unknown)
536 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
537 if (ret == OK && expected->tt_argcount != -1
538 && (actual->tt_argcount < expected->tt_min_argcount
539 || actual->tt_argcount > expected->tt_argcount))
540 ret = FAIL;
541 }
542 if (ret == FAIL && give_msg)
543 type_mismatch(expected, actual);
544 }
545 return ret;
546}
547
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100548/////////////////////////////////////////////////////////////////////
549// Following generate_ functions expect the caller to call ga_grow().
550
Bram Moolenaar080457c2020-03-03 21:53:32 +0100551#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
552#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
553
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100554/*
555 * Generate an instruction without arguments.
556 * Returns a pointer to the new instruction, NULL if failed.
557 */
558 static isn_T *
559generate_instr(cctx_T *cctx, isntype_T isn_type)
560{
561 garray_T *instr = &cctx->ctx_instr;
562 isn_T *isn;
563
Bram Moolenaar080457c2020-03-03 21:53:32 +0100564 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100565 if (ga_grow(instr, 1) == FAIL)
566 return NULL;
567 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
568 isn->isn_type = isn_type;
569 isn->isn_lnum = cctx->ctx_lnum + 1;
570 ++instr->ga_len;
571
572 return isn;
573}
574
575/*
576 * Generate an instruction without arguments.
577 * "drop" will be removed from the stack.
578 * Returns a pointer to the new instruction, NULL if failed.
579 */
580 static isn_T *
581generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
582{
583 garray_T *stack = &cctx->ctx_type_stack;
584
Bram Moolenaar080457c2020-03-03 21:53:32 +0100585 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100586 stack->ga_len -= drop;
587 return generate_instr(cctx, isn_type);
588}
589
590/*
591 * Generate instruction "isn_type" and put "type" on the type stack.
592 */
593 static isn_T *
594generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
595{
596 isn_T *isn;
597 garray_T *stack = &cctx->ctx_type_stack;
598
599 if ((isn = generate_instr(cctx, isn_type)) == NULL)
600 return NULL;
601
602 if (ga_grow(stack, 1) == FAIL)
603 return NULL;
604 ((type_T **)stack->ga_data)[stack->ga_len] = type;
605 ++stack->ga_len;
606
607 return isn;
608}
609
610/*
611 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
612 */
613 static int
614may_generate_2STRING(int offset, cctx_T *cctx)
615{
616 isn_T *isn;
617 garray_T *stack = &cctx->ctx_type_stack;
618 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
619
620 if ((*type)->tt_type == VAR_STRING)
621 return OK;
622 *type = &t_string;
623
624 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
625 return FAIL;
626 isn->isn_arg.number = offset;
627
628 return OK;
629}
630
631 static int
632check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
633{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200634 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100635 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200636 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100637 {
638 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100639 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100640 else
641 semsg(_("E1036: %c requires number or float arguments"), *op);
642 return FAIL;
643 }
644 return OK;
645}
646
647/*
648 * Generate an instruction with two arguments. The instruction depends on the
649 * type of the arguments.
650 */
651 static int
652generate_two_op(cctx_T *cctx, char_u *op)
653{
654 garray_T *stack = &cctx->ctx_type_stack;
655 type_T *type1;
656 type_T *type2;
657 vartype_T vartype;
658 isn_T *isn;
659
Bram Moolenaar080457c2020-03-03 21:53:32 +0100660 RETURN_OK_IF_SKIP(cctx);
661
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100662 // Get the known type of the two items on the stack. If they are matching
663 // use a type-specific instruction. Otherwise fall back to runtime type
664 // checking.
665 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
666 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200667 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100668 if (type1->tt_type == type2->tt_type
669 && (type1->tt_type == VAR_NUMBER
670 || type1->tt_type == VAR_LIST
671#ifdef FEAT_FLOAT
672 || type1->tt_type == VAR_FLOAT
673#endif
674 || type1->tt_type == VAR_BLOB))
675 vartype = type1->tt_type;
676
677 switch (*op)
678 {
679 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200680 && type1->tt_type != VAR_ANY
681 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100682 && check_number_or_float(
683 type1->tt_type, type2->tt_type, op) == FAIL)
684 return FAIL;
685 isn = generate_instr_drop(cctx,
686 vartype == VAR_NUMBER ? ISN_OPNR
687 : vartype == VAR_LIST ? ISN_ADDLIST
688 : vartype == VAR_BLOB ? ISN_ADDBLOB
689#ifdef FEAT_FLOAT
690 : vartype == VAR_FLOAT ? ISN_OPFLOAT
691#endif
692 : ISN_OPANY, 1);
693 if (isn != NULL)
694 isn->isn_arg.op.op_type = EXPR_ADD;
695 break;
696
697 case '-':
698 case '*':
699 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
700 op) == FAIL)
701 return FAIL;
702 if (vartype == VAR_NUMBER)
703 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
704#ifdef FEAT_FLOAT
705 else if (vartype == VAR_FLOAT)
706 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
707#endif
708 else
709 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
710 if (isn != NULL)
711 isn->isn_arg.op.op_type = *op == '*'
712 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
713 break;
714
Bram Moolenaar4c683752020-04-05 21:38:23 +0200715 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100716 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200717 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100718 && type2->tt_type != VAR_NUMBER))
719 {
720 emsg(_("E1035: % requires number arguments"));
721 return FAIL;
722 }
723 isn = generate_instr_drop(cctx,
724 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
725 if (isn != NULL)
726 isn->isn_arg.op.op_type = EXPR_REM;
727 break;
728 }
729
730 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200731 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100732 {
733 type_T *type = &t_any;
734
735#ifdef FEAT_FLOAT
736 // float+number and number+float results in float
737 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
738 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
739 type = &t_float;
740#endif
741 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
742 }
743
744 return OK;
745}
746
747/*
748 * Generate an ISN_COMPARE* instruction with a boolean result.
749 */
750 static int
751generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
752{
753 isntype_T isntype = ISN_DROP;
754 isn_T *isn;
755 garray_T *stack = &cctx->ctx_type_stack;
756 vartype_T type1;
757 vartype_T type2;
758
Bram Moolenaar080457c2020-03-03 21:53:32 +0100759 RETURN_OK_IF_SKIP(cctx);
760
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100761 // Get the known type of the two items on the stack. If they are matching
762 // use a type-specific instruction. Otherwise fall back to runtime type
763 // checking.
764 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
765 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200766 if (type1 == VAR_UNKNOWN)
767 type1 = VAR_ANY;
768 if (type2 == VAR_UNKNOWN)
769 type2 = VAR_ANY;
770
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100771 if (type1 == type2)
772 {
773 switch (type1)
774 {
775 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
776 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
777 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
778 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
779 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
780 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
781 case VAR_LIST: isntype = ISN_COMPARELIST; break;
782 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
783 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100784 default: isntype = ISN_COMPAREANY; break;
785 }
786 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200787 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100788 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
789 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
790 isntype = ISN_COMPAREANY;
791
792 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
793 && (isntype == ISN_COMPAREBOOL
794 || isntype == ISN_COMPARESPECIAL
795 || isntype == ISN_COMPARENR
796 || isntype == ISN_COMPAREFLOAT))
797 {
798 semsg(_("E1037: Cannot use \"%s\" with %s"),
799 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
800 return FAIL;
801 }
802 if (isntype == ISN_DROP
803 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
804 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
805 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
806 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
807 && exptype != EXPR_IS && exptype != EXPR_ISNOT
808 && (type1 == VAR_BLOB || type2 == VAR_BLOB
809 || type1 == VAR_LIST || type2 == VAR_LIST))))
810 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100811 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 vartype_name(type1), vartype_name(type2));
813 return FAIL;
814 }
815
816 if ((isn = generate_instr(cctx, isntype)) == NULL)
817 return FAIL;
818 isn->isn_arg.op.op_type = exptype;
819 isn->isn_arg.op.op_ic = ic;
820
821 // takes two arguments, puts one bool back
822 if (stack->ga_len >= 2)
823 {
824 --stack->ga_len;
825 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
826 }
827
828 return OK;
829}
830
831/*
832 * Generate an ISN_2BOOL instruction.
833 */
834 static int
835generate_2BOOL(cctx_T *cctx, int invert)
836{
837 isn_T *isn;
838 garray_T *stack = &cctx->ctx_type_stack;
839
Bram Moolenaar080457c2020-03-03 21:53:32 +0100840 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100841 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
842 return FAIL;
843 isn->isn_arg.number = invert;
844
845 // type becomes bool
846 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
847
848 return OK;
849}
850
851 static int
852generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
853{
854 isn_T *isn;
855 garray_T *stack = &cctx->ctx_type_stack;
856
Bram Moolenaar080457c2020-03-03 21:53:32 +0100857 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100858 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
859 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +0200860 // TODO: whole type, e.g. for a function also arg and return types
861 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100862 isn->isn_arg.type.ct_off = offset;
863
864 // type becomes vartype
Bram Moolenaar5adc55c2020-05-02 23:12:58 +0200865 ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100866
867 return OK;
868}
869
870/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200871 * Check that
872 * - "actual" is "expected" type or
873 * - "actual" is a type that can be "expected" type: add a runtime check; or
874 * - return FAIL.
875 */
876 static int
877need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
878{
879 if (check_type(expected, actual, FALSE) == OK)
880 return OK;
881 if (actual->tt_type != VAR_ANY
882 && actual->tt_type != VAR_UNKNOWN
883 && !(actual->tt_type == VAR_FUNC
884 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
885 {
886 type_mismatch(expected, actual);
887 return FAIL;
888 }
889 generate_TYPECHECK(cctx, expected, offset);
890 return OK;
891}
892
893/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100894 * Generate an ISN_PUSHNR instruction.
895 */
896 static int
897generate_PUSHNR(cctx_T *cctx, varnumber_T number)
898{
899 isn_T *isn;
900
Bram Moolenaar080457c2020-03-03 21:53:32 +0100901 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100902 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
903 return FAIL;
904 isn->isn_arg.number = number;
905
906 return OK;
907}
908
909/*
910 * Generate an ISN_PUSHBOOL instruction.
911 */
912 static int
913generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
914{
915 isn_T *isn;
916
Bram Moolenaar080457c2020-03-03 21:53:32 +0100917 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100918 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
919 return FAIL;
920 isn->isn_arg.number = number;
921
922 return OK;
923}
924
925/*
926 * Generate an ISN_PUSHSPEC instruction.
927 */
928 static int
929generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
930{
931 isn_T *isn;
932
Bram Moolenaar080457c2020-03-03 21:53:32 +0100933 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100934 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
935 return FAIL;
936 isn->isn_arg.number = number;
937
938 return OK;
939}
940
941#ifdef FEAT_FLOAT
942/*
943 * Generate an ISN_PUSHF instruction.
944 */
945 static int
946generate_PUSHF(cctx_T *cctx, float_T fnumber)
947{
948 isn_T *isn;
949
Bram Moolenaar080457c2020-03-03 21:53:32 +0100950 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100951 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
952 return FAIL;
953 isn->isn_arg.fnumber = fnumber;
954
955 return OK;
956}
957#endif
958
959/*
960 * Generate an ISN_PUSHS instruction.
961 * Consumes "str".
962 */
963 static int
964generate_PUSHS(cctx_T *cctx, char_u *str)
965{
966 isn_T *isn;
967
Bram Moolenaar080457c2020-03-03 21:53:32 +0100968 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100969 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
970 return FAIL;
971 isn->isn_arg.string = str;
972
973 return OK;
974}
975
976/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100977 * Generate an ISN_PUSHCHANNEL instruction.
978 * Consumes "channel".
979 */
980 static int
981generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
982{
983 isn_T *isn;
984
Bram Moolenaar080457c2020-03-03 21:53:32 +0100985 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100986 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
987 return FAIL;
988 isn->isn_arg.channel = channel;
989
990 return OK;
991}
992
993/*
994 * Generate an ISN_PUSHJOB instruction.
995 * Consumes "job".
996 */
997 static int
998generate_PUSHJOB(cctx_T *cctx, job_T *job)
999{
1000 isn_T *isn;
1001
Bram Moolenaar080457c2020-03-03 21:53:32 +01001002 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001003 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001004 return FAIL;
1005 isn->isn_arg.job = job;
1006
1007 return OK;
1008}
1009
1010/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011 * Generate an ISN_PUSHBLOB instruction.
1012 * Consumes "blob".
1013 */
1014 static int
1015generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1016{
1017 isn_T *isn;
1018
Bram Moolenaar080457c2020-03-03 21:53:32 +01001019 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001020 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1021 return FAIL;
1022 isn->isn_arg.blob = blob;
1023
1024 return OK;
1025}
1026
1027/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001028 * Generate an ISN_PUSHFUNC instruction with name "name".
1029 * Consumes "name".
1030 */
1031 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001032generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001033{
1034 isn_T *isn;
1035
Bram Moolenaar080457c2020-03-03 21:53:32 +01001036 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001037 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001038 return FAIL;
1039 isn->isn_arg.string = name;
1040
1041 return OK;
1042}
1043
1044/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001045 * Generate an ISN_STORE instruction.
1046 */
1047 static int
1048generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1049{
1050 isn_T *isn;
1051
Bram Moolenaar080457c2020-03-03 21:53:32 +01001052 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001053 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1054 return FAIL;
1055 if (name != NULL)
1056 isn->isn_arg.string = vim_strsave(name);
1057 else
1058 isn->isn_arg.number = idx;
1059
1060 return OK;
1061}
1062
1063/*
1064 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1065 */
1066 static int
1067generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1068{
1069 isn_T *isn;
1070
Bram Moolenaar080457c2020-03-03 21:53:32 +01001071 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001072 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1073 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001074 isn->isn_arg.storenr.stnr_idx = idx;
1075 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001076
1077 return OK;
1078}
1079
1080/*
1081 * Generate an ISN_STOREOPT instruction
1082 */
1083 static int
1084generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1085{
1086 isn_T *isn;
1087
Bram Moolenaar080457c2020-03-03 21:53:32 +01001088 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001089 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
1090 return FAIL;
1091 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1092 isn->isn_arg.storeopt.so_flags = opt_flags;
1093
1094 return OK;
1095}
1096
1097/*
1098 * Generate an ISN_LOAD or similar instruction.
1099 */
1100 static int
1101generate_LOAD(
1102 cctx_T *cctx,
1103 isntype_T isn_type,
1104 int idx,
1105 char_u *name,
1106 type_T *type)
1107{
1108 isn_T *isn;
1109
Bram Moolenaar080457c2020-03-03 21:53:32 +01001110 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001111 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1112 return FAIL;
1113 if (name != NULL)
1114 isn->isn_arg.string = vim_strsave(name);
1115 else
1116 isn->isn_arg.number = idx;
1117
1118 return OK;
1119}
1120
1121/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001122 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001123 */
1124 static int
1125generate_LOADV(
1126 cctx_T *cctx,
1127 char_u *name,
1128 int error)
1129{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001130 int di_flags;
1131 int vidx = find_vim_var(name, &di_flags);
1132 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001133
Bram Moolenaar080457c2020-03-03 21:53:32 +01001134 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001135 if (vidx < 0)
1136 {
1137 if (error)
1138 semsg(_(e_var_notfound), name);
1139 return FAIL;
1140 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001141 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001142
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001143 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001144}
1145
1146/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001147 * Generate an ISN_UNLET instruction.
1148 */
1149 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001150generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001151{
1152 isn_T *isn;
1153
1154 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001155 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001156 return FAIL;
1157 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1158 isn->isn_arg.unlet.ul_forceit = forceit;
1159
1160 return OK;
1161}
1162
1163/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001164 * Generate an ISN_LOADS instruction.
1165 */
1166 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001167generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001168 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001169 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001170 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001171 int sid,
1172 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001173{
1174 isn_T *isn;
1175
Bram Moolenaar080457c2020-03-03 21:53:32 +01001176 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001177 if (isn_type == ISN_LOADS)
1178 isn = generate_instr_type(cctx, isn_type, type);
1179 else
1180 isn = generate_instr_drop(cctx, isn_type, 1);
1181 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001182 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001183 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1184 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001185
1186 return OK;
1187}
1188
1189/*
1190 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1191 */
1192 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001193generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001194 cctx_T *cctx,
1195 isntype_T isn_type,
1196 int sid,
1197 int idx,
1198 type_T *type)
1199{
1200 isn_T *isn;
1201
Bram Moolenaar080457c2020-03-03 21:53:32 +01001202 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001203 if (isn_type == ISN_LOADSCRIPT)
1204 isn = generate_instr_type(cctx, isn_type, type);
1205 else
1206 isn = generate_instr_drop(cctx, isn_type, 1);
1207 if (isn == NULL)
1208 return FAIL;
1209 isn->isn_arg.script.script_sid = sid;
1210 isn->isn_arg.script.script_idx = idx;
1211 return OK;
1212}
1213
1214/*
1215 * Generate an ISN_NEWLIST instruction.
1216 */
1217 static int
1218generate_NEWLIST(cctx_T *cctx, int count)
1219{
1220 isn_T *isn;
1221 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 type_T *type;
1223 type_T *member;
1224
Bram Moolenaar080457c2020-03-03 21:53:32 +01001225 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001226 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1227 return FAIL;
1228 isn->isn_arg.number = count;
1229
1230 // drop the value types
1231 stack->ga_len -= count;
1232
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001233 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001234 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001235 if (count > 0)
1236 member = ((type_T **)stack->ga_data)[stack->ga_len];
1237 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001238 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001239 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240
1241 // add the list type to the type stack
1242 if (ga_grow(stack, 1) == FAIL)
1243 return FAIL;
1244 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1245 ++stack->ga_len;
1246
1247 return OK;
1248}
1249
1250/*
1251 * Generate an ISN_NEWDICT instruction.
1252 */
1253 static int
1254generate_NEWDICT(cctx_T *cctx, int count)
1255{
1256 isn_T *isn;
1257 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001258 type_T *type;
1259 type_T *member;
1260
Bram Moolenaar080457c2020-03-03 21:53:32 +01001261 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001262 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1263 return FAIL;
1264 isn->isn_arg.number = count;
1265
1266 // drop the key and value types
1267 stack->ga_len -= 2 * count;
1268
Bram Moolenaar436472f2020-02-20 22:54:43 +01001269 // Use the first value type for the list member type. Use "void" for an
1270 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001271 if (count > 0)
1272 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1273 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001274 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001275 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001276
1277 // add the dict type to the type stack
1278 if (ga_grow(stack, 1) == FAIL)
1279 return FAIL;
1280 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1281 ++stack->ga_len;
1282
1283 return OK;
1284}
1285
1286/*
1287 * Generate an ISN_FUNCREF instruction.
1288 */
1289 static int
1290generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1291{
1292 isn_T *isn;
1293 garray_T *stack = &cctx->ctx_type_stack;
1294
Bram Moolenaar080457c2020-03-03 21:53:32 +01001295 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001296 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1297 return FAIL;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001298 isn->isn_arg.funcref.fr_func = dfunc_idx;
1299 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001300
1301 if (ga_grow(stack, 1) == FAIL)
1302 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001303 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001304 // TODO: argument and return types
1305 ++stack->ga_len;
1306
1307 return OK;
1308}
1309
1310/*
1311 * Generate an ISN_JUMP instruction.
1312 */
1313 static int
1314generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1315{
1316 isn_T *isn;
1317 garray_T *stack = &cctx->ctx_type_stack;
1318
Bram Moolenaar080457c2020-03-03 21:53:32 +01001319 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001320 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1321 return FAIL;
1322 isn->isn_arg.jump.jump_when = when;
1323 isn->isn_arg.jump.jump_where = where;
1324
1325 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1326 --stack->ga_len;
1327
1328 return OK;
1329}
1330
1331 static int
1332generate_FOR(cctx_T *cctx, int loop_idx)
1333{
1334 isn_T *isn;
1335 garray_T *stack = &cctx->ctx_type_stack;
1336
Bram Moolenaar080457c2020-03-03 21:53:32 +01001337 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001338 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1339 return FAIL;
1340 isn->isn_arg.forloop.for_idx = loop_idx;
1341
1342 if (ga_grow(stack, 1) == FAIL)
1343 return FAIL;
1344 // type doesn't matter, will be stored next
1345 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1346 ++stack->ga_len;
1347
1348 return OK;
1349}
1350
1351/*
1352 * Generate an ISN_BCALL instruction.
1353 * Return FAIL if the number of arguments is wrong.
1354 */
1355 static int
1356generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1357{
1358 isn_T *isn;
1359 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001360 type_T *argtypes[MAX_FUNC_ARGS];
1361 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001362
Bram Moolenaar080457c2020-03-03 21:53:32 +01001363 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001364 if (check_internal_func(func_idx, argcount) == FAIL)
1365 return FAIL;
1366
1367 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1368 return FAIL;
1369 isn->isn_arg.bfunc.cbf_idx = func_idx;
1370 isn->isn_arg.bfunc.cbf_argcount = argcount;
1371
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001372 for (i = 0; i < argcount; ++i)
1373 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1374
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001375 stack->ga_len -= argcount; // drop the arguments
1376 if (ga_grow(stack, 1) == FAIL)
1377 return FAIL;
1378 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001379 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001380 ++stack->ga_len; // add return value
1381
1382 return OK;
1383}
1384
1385/*
1386 * Generate an ISN_DCALL or ISN_UCALL instruction.
1387 * Return FAIL if the number of arguments is wrong.
1388 */
1389 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001390generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391{
1392 isn_T *isn;
1393 garray_T *stack = &cctx->ctx_type_stack;
1394 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001395 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001396
Bram Moolenaar080457c2020-03-03 21:53:32 +01001397 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001398 if (argcount > regular_args && !has_varargs(ufunc))
1399 {
1400 semsg(_(e_toomanyarg), ufunc->uf_name);
1401 return FAIL;
1402 }
1403 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1404 {
1405 semsg(_(e_toofewarg), ufunc->uf_name);
1406 return FAIL;
1407 }
1408
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001409 if (ufunc->uf_dfunc_idx >= 0)
1410 {
1411 int i;
1412
1413 for (i = 0; i < argcount; ++i)
1414 {
1415 type_T *expected;
1416 type_T *actual;
1417
1418 if (i < regular_args)
1419 {
1420 if (ufunc->uf_arg_types == NULL)
1421 continue;
1422 expected = ufunc->uf_arg_types[i];
1423 }
1424 else
1425 expected = ufunc->uf_va_type->tt_member;
1426 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001427 if (need_type(actual, expected, -argcount + i, cctx) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001428 {
1429 arg_type_mismatch(expected, actual, i + 1);
1430 return FAIL;
1431 }
1432 }
1433 }
1434
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001435 if ((isn = generate_instr(cctx,
1436 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1437 return FAIL;
1438 if (ufunc->uf_dfunc_idx >= 0)
1439 {
1440 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1441 isn->isn_arg.dfunc.cdf_argcount = argcount;
1442 }
1443 else
1444 {
1445 // A user function may be deleted and redefined later, can't use the
1446 // ufunc pointer, need to look it up again at runtime.
1447 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1448 isn->isn_arg.ufunc.cuf_argcount = argcount;
1449 }
1450
1451 stack->ga_len -= argcount; // drop the arguments
1452 if (ga_grow(stack, 1) == FAIL)
1453 return FAIL;
1454 // add return value
1455 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1456 ++stack->ga_len;
1457
1458 return OK;
1459}
1460
1461/*
1462 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1463 */
1464 static int
1465generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1466{
1467 isn_T *isn;
1468 garray_T *stack = &cctx->ctx_type_stack;
1469
Bram Moolenaar080457c2020-03-03 21:53:32 +01001470 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001471 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1472 return FAIL;
1473 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1474 isn->isn_arg.ufunc.cuf_argcount = argcount;
1475
1476 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001477 if (ga_grow(stack, 1) == FAIL)
1478 return FAIL;
1479 // add return value
1480 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1481 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001482
1483 return OK;
1484}
1485
1486/*
1487 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001488 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001489 */
1490 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001491generate_PCALL(
1492 cctx_T *cctx,
1493 int argcount,
1494 char_u *name,
1495 type_T *type,
1496 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001497{
1498 isn_T *isn;
1499 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001500 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001501
Bram Moolenaar080457c2020-03-03 21:53:32 +01001502 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001503
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001504 if (type->tt_type == VAR_ANY)
1505 ret_type = &t_any;
1506 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1507 ret_type = type->tt_member;
1508 else
1509 {
1510 semsg(_("E1085: Not a callable type: %s"), name);
1511 return FAIL;
1512 }
1513
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001514 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1515 return FAIL;
1516 isn->isn_arg.pfunc.cpf_top = at_top;
1517 isn->isn_arg.pfunc.cpf_argcount = argcount;
1518
1519 stack->ga_len -= argcount; // drop the arguments
1520
1521 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001522 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001523
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001524 // If partial is above the arguments it must be cleared and replaced with
1525 // the return value.
1526 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1527 return FAIL;
1528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001529 return OK;
1530}
1531
1532/*
1533 * Generate an ISN_MEMBER instruction.
1534 */
1535 static int
1536generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1537{
1538 isn_T *isn;
1539 garray_T *stack = &cctx->ctx_type_stack;
1540 type_T *type;
1541
Bram Moolenaar080457c2020-03-03 21:53:32 +01001542 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001543 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1544 return FAIL;
1545 isn->isn_arg.string = vim_strnsave(name, (int)len);
1546
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001547 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001548 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001549 if (type->tt_type != VAR_DICT && type != &t_any)
1550 {
1551 emsg(_(e_dictreq));
1552 return FAIL;
1553 }
1554 // change dict type to dict member type
1555 if (type->tt_type == VAR_DICT)
1556 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001557
1558 return OK;
1559}
1560
1561/*
1562 * Generate an ISN_ECHO instruction.
1563 */
1564 static int
1565generate_ECHO(cctx_T *cctx, int with_white, int count)
1566{
1567 isn_T *isn;
1568
Bram Moolenaar080457c2020-03-03 21:53:32 +01001569 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001570 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1571 return FAIL;
1572 isn->isn_arg.echo.echo_with_white = with_white;
1573 isn->isn_arg.echo.echo_count = count;
1574
1575 return OK;
1576}
1577
Bram Moolenaarad39c092020-02-26 18:23:43 +01001578/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001579 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001580 */
1581 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001582generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001583{
1584 isn_T *isn;
1585
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001586 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001587 return FAIL;
1588 isn->isn_arg.number = count;
1589
1590 return OK;
1591}
1592
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001593 static int
1594generate_EXEC(cctx_T *cctx, char_u *line)
1595{
1596 isn_T *isn;
1597
Bram Moolenaar080457c2020-03-03 21:53:32 +01001598 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001599 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1600 return FAIL;
1601 isn->isn_arg.string = vim_strsave(line);
1602 return OK;
1603}
1604
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001605 static int
1606generate_EXECCONCAT(cctx_T *cctx, int count)
1607{
1608 isn_T *isn;
1609
1610 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1611 return FAIL;
1612 isn->isn_arg.number = count;
1613 return OK;
1614}
1615
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001616/*
1617 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001618 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001619 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001620 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001621reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1622{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001623 lvar_T *lvar;
1624
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001625 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001626 {
1627 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001628 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001629 }
1630
1631 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001632 return NULL;
1633 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001634
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001635 // Every local variable uses the next entry on the stack. We could re-use
1636 // the last ones when leaving a scope, but then variables used in a closure
1637 // might get overwritten. To keep things simple do not re-use stack
1638 // entries. This is less efficient, but memory is cheap these days.
1639 lvar->lv_idx = cctx->ctx_locals_count++;
1640
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001641 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1642 lvar->lv_const = isConst;
1643 lvar->lv_type = type;
1644
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001645 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001646}
1647
1648/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001649 * Remove local variables above "new_top".
1650 */
1651 static void
1652unwind_locals(cctx_T *cctx, int new_top)
1653{
1654 if (cctx->ctx_locals.ga_len > new_top)
1655 {
1656 int idx;
1657 lvar_T *lvar;
1658
1659 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1660 {
1661 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1662 vim_free(lvar->lv_name);
1663 }
1664 }
1665 cctx->ctx_locals.ga_len = new_top;
1666}
1667
1668/*
1669 * Free all local variables.
1670 */
1671 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001672free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001673{
1674 unwind_locals(cctx, 0);
1675 ga_clear(&cctx->ctx_locals);
1676}
1677
1678/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001679 * Skip over a type definition and return a pointer to just after it.
1680 */
1681 char_u *
1682skip_type(char_u *start)
1683{
1684 char_u *p = start;
1685
1686 while (ASCII_ISALNUM(*p) || *p == '_')
1687 ++p;
1688
1689 // Skip over "<type>"; this is permissive about white space.
1690 if (*skipwhite(p) == '<')
1691 {
1692 p = skipwhite(p);
1693 p = skip_type(skipwhite(p + 1));
1694 p = skipwhite(p);
1695 if (*p == '>')
1696 ++p;
1697 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001698 else if (*p == '(' && STRNCMP("func", start, 4) == 0)
1699 {
1700 // handle func(args): type
1701 ++p;
1702 while (*p != ')' && *p != NUL)
1703 {
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001704 char_u *sp = p;
1705
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001706 p = skip_type(p);
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001707 if (p == sp)
1708 return p; // syntax error
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001709 if (*p == ',')
1710 p = skipwhite(p + 1);
1711 }
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001712 if (*p == ')')
1713 {
1714 if (p[1] == ':')
1715 p = skip_type(skipwhite(p + 2));
1716 else
1717 p = skipwhite(p + 1);
1718 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001719 }
1720
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001721 return p;
1722}
1723
1724/*
1725 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001726 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001727 * Returns NULL in case of failure.
1728 */
1729 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001730parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001731{
1732 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001733 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001734
1735 if (**arg != '<')
1736 {
1737 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001738 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001739 else
1740 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001741 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001742 }
1743 *arg = skipwhite(*arg + 1);
1744
Bram Moolenaard77a8522020-04-03 21:59:57 +02001745 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001746
1747 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001748 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001749 {
1750 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001751 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001752 }
1753 ++*arg;
1754
1755 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001756 return get_list_type(member_type, type_gap);
1757 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001758}
1759
1760/*
1761 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001762 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001763 */
1764 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001765parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001766{
1767 char_u *p = *arg;
1768 size_t len;
1769
1770 // skip over the first word
1771 while (ASCII_ISALNUM(*p) || *p == '_')
1772 ++p;
1773 len = p - *arg;
1774
1775 switch (**arg)
1776 {
1777 case 'a':
1778 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1779 {
1780 *arg += len;
1781 return &t_any;
1782 }
1783 break;
1784 case 'b':
1785 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1786 {
1787 *arg += len;
1788 return &t_bool;
1789 }
1790 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1791 {
1792 *arg += len;
1793 return &t_blob;
1794 }
1795 break;
1796 case 'c':
1797 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1798 {
1799 *arg += len;
1800 return &t_channel;
1801 }
1802 break;
1803 case 'd':
1804 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1805 {
1806 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001807 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001808 }
1809 break;
1810 case 'f':
1811 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1812 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001813#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001814 *arg += len;
1815 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001816#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001817 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001818 return &t_any;
1819#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001820 }
1821 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1822 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001823 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001824 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001825 int argcount = -1;
1826 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001827 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001828 type_T *arg_type[MAX_FUNC_ARGS + 1];
1829
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001830 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001831 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001832 if (**arg == '(')
1833 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001834 // "func" may or may not return a value, "func()" does
1835 // not return a value.
1836 ret_type = &t_void;
1837
Bram Moolenaard77a8522020-04-03 21:59:57 +02001838 p = ++*arg;
1839 argcount = 0;
1840 while (*p != NUL && *p != ')')
1841 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001842 if (*p == '?')
1843 {
1844 if (first_optional == -1)
1845 first_optional = argcount;
1846 ++p;
1847 }
1848 else if (first_optional != -1)
1849 {
1850 emsg(_("E1007: mandatory argument after optional argument"));
1851 return &t_any;
1852 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001853 else if (STRNCMP(p, "...", 3) == 0)
1854 {
1855 flags |= TTFLAG_VARARGS;
1856 p += 3;
1857 }
1858
1859 arg_type[argcount++] = parse_type(&p, type_gap);
1860
1861 // Nothing comes after "...{type}".
1862 if (flags & TTFLAG_VARARGS)
1863 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001864
Bram Moolenaard77a8522020-04-03 21:59:57 +02001865 if (*p != ',' && *skipwhite(p) == ',')
1866 {
1867 semsg(_(e_no_white_before), ",");
1868 return &t_any;
1869 }
1870 if (*p == ',')
1871 {
1872 ++p;
1873 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001874 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001875 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001876 return &t_any;
1877 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001878 }
1879 p = skipwhite(p);
1880 if (argcount == MAX_FUNC_ARGS)
1881 {
1882 emsg(_("E740: Too many argument types"));
1883 return &t_any;
1884 }
1885 }
1886
1887 p = skipwhite(p);
1888 if (*p != ')')
1889 {
1890 emsg(_(e_missing_close));
1891 return &t_any;
1892 }
1893 *arg = p + 1;
1894 }
1895 if (**arg == ':')
1896 {
1897 // parse return type
1898 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001899 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001900 semsg(_(e_white_after), ":");
1901 *arg = skipwhite(*arg);
1902 ret_type = parse_type(arg, type_gap);
1903 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001904 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001905 type = get_func_type(ret_type, argcount, type_gap);
1906 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001907 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001908 type = alloc_func_type(ret_type, argcount, type_gap);
1909 type->tt_flags = flags;
1910 if (argcount > 0)
1911 {
1912 type->tt_argcount = argcount;
1913 type->tt_min_argcount = first_optional == -1
1914 ? argcount : first_optional;
1915 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001916 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001917 return &t_any;
1918 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001919 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001920 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001921 }
1922 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001923 }
1924 break;
1925 case 'j':
1926 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1927 {
1928 *arg += len;
1929 return &t_job;
1930 }
1931 break;
1932 case 'l':
1933 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1934 {
1935 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001936 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001937 }
1938 break;
1939 case 'n':
1940 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1941 {
1942 *arg += len;
1943 return &t_number;
1944 }
1945 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001946 case 's':
1947 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1948 {
1949 *arg += len;
1950 return &t_string;
1951 }
1952 break;
1953 case 'v':
1954 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1955 {
1956 *arg += len;
1957 return &t_void;
1958 }
1959 break;
1960 }
1961
1962 semsg(_("E1010: Type not recognized: %s"), *arg);
1963 return &t_any;
1964}
1965
1966/*
1967 * Check if "type1" and "type2" are exactly the same.
1968 */
1969 static int
1970equal_type(type_T *type1, type_T *type2)
1971{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001972 int i;
1973
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001974 if (type1->tt_type != type2->tt_type)
1975 return FALSE;
1976 switch (type1->tt_type)
1977 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001978 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001979 case VAR_ANY:
1980 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001981 case VAR_SPECIAL:
1982 case VAR_BOOL:
1983 case VAR_NUMBER:
1984 case VAR_FLOAT:
1985 case VAR_STRING:
1986 case VAR_BLOB:
1987 case VAR_JOB:
1988 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001989 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001990 case VAR_LIST:
1991 case VAR_DICT:
1992 return equal_type(type1->tt_member, type2->tt_member);
1993 case VAR_FUNC:
1994 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001995 if (!equal_type(type1->tt_member, type2->tt_member)
1996 || type1->tt_argcount != type2->tt_argcount)
1997 return FALSE;
1998 if (type1->tt_argcount < 0
1999 || type1->tt_args == NULL || type2->tt_args == NULL)
2000 return TRUE;
2001 for (i = 0; i < type1->tt_argcount; ++i)
2002 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
2003 return FALSE;
2004 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002005 }
2006 return TRUE;
2007}
2008
2009/*
2010 * Find the common type of "type1" and "type2" and put it in "dest".
2011 * "type2" and "dest" may be the same.
2012 */
2013 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02002014common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002015{
2016 if (equal_type(type1, type2))
2017 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002018 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002019 return;
2020 }
2021
2022 if (type1->tt_type == type2->tt_type)
2023 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002024 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
2025 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002026 type_T *common;
2027
Bram Moolenaard77a8522020-04-03 21:59:57 +02002028 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002029 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002030 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002031 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002032 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002033 return;
2034 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002035 if (type1->tt_type == VAR_FUNC)
2036 {
2037 type_T *common;
2038
2039 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
2040 if (type1->tt_argcount == type2->tt_argcount
2041 && type1->tt_argcount >= 0)
2042 {
2043 int argcount = type1->tt_argcount;
2044 int i;
2045
2046 *dest = alloc_func_type(common, argcount, type_gap);
2047 if (type1->tt_args != NULL && type2->tt_args != NULL)
2048 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02002049 if (func_type_add_arg_types(*dest, argcount,
2050 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002051 for (i = 0; i < argcount; ++i)
2052 common_type(type1->tt_args[i], type2->tt_args[i],
2053 &(*dest)->tt_args[i], type_gap);
2054 }
2055 }
2056 else
2057 *dest = alloc_func_type(common, -1, type_gap);
2058 return;
2059 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002060 }
2061
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002062 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002063}
2064
2065 char *
2066vartype_name(vartype_T type)
2067{
2068 switch (type)
2069 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002070 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002071 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002072 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002073 case VAR_SPECIAL: return "special";
2074 case VAR_BOOL: return "bool";
2075 case VAR_NUMBER: return "number";
2076 case VAR_FLOAT: return "float";
2077 case VAR_STRING: return "string";
2078 case VAR_BLOB: return "blob";
2079 case VAR_JOB: return "job";
2080 case VAR_CHANNEL: return "channel";
2081 case VAR_LIST: return "list";
2082 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002083
2084 case VAR_FUNC:
2085 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002086 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02002087 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002088}
2089
2090/*
2091 * Return the name of a type.
2092 * The result may be in allocated memory, in which case "tofree" is set.
2093 */
2094 char *
2095type_name(type_T *type, char **tofree)
2096{
2097 char *name = vartype_name(type->tt_type);
2098
2099 *tofree = NULL;
2100 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
2101 {
2102 char *member_free;
2103 char *member_name = type_name(type->tt_member, &member_free);
2104 size_t len;
2105
2106 len = STRLEN(name) + STRLEN(member_name) + 3;
2107 *tofree = alloc(len);
2108 if (*tofree != NULL)
2109 {
2110 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
2111 vim_free(member_free);
2112 return *tofree;
2113 }
2114 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002115 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002116 {
2117 garray_T ga;
2118 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002119 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002120
2121 ga_init2(&ga, 1, 100);
2122 if (ga_grow(&ga, 20) == FAIL)
2123 return "[unknown]";
2124 *tofree = ga.ga_data;
2125 STRCPY(ga.ga_data, "func(");
2126 ga.ga_len += 5;
2127
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002128 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002129 {
2130 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002131 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002132 int len;
2133
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002134 if (type->tt_args == NULL)
2135 arg_type = "[unknown]";
2136 else
2137 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002138 if (i > 0)
2139 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002140 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002141 ga.ga_len += 2;
2142 }
2143 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002144 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002145 {
2146 vim_free(arg_free);
2147 return "[unknown]";
2148 }
2149 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002150 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002151 {
2152 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
2153 ga.ga_len += 3;
2154 }
2155 else if (i >= type->tt_min_argcount)
2156 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002157 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002158 ga.ga_len += len;
2159 vim_free(arg_free);
2160 }
2161
2162 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002163 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002164 else
2165 {
2166 char *ret_free;
2167 char *ret_name = type_name(type->tt_member, &ret_free);
2168 int len;
2169
2170 len = (int)STRLEN(ret_name) + 4;
2171 if (ga_grow(&ga, len) == FAIL)
2172 {
2173 vim_free(ret_free);
2174 return "[unknown]";
2175 }
2176 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002177 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
2178 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002179 vim_free(ret_free);
2180 }
2181 return ga.ga_data;
2182 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002183
2184 return name;
2185}
2186
2187/*
2188 * Find "name" in script-local items of script "sid".
2189 * Returns the index in "sn_var_vals" if found.
2190 * If found but not in "sn_var_vals" returns -1.
2191 * If not found returns -2.
2192 */
2193 int
2194get_script_item_idx(int sid, char_u *name, int check_writable)
2195{
2196 hashtab_T *ht;
2197 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002198 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002199 int idx;
2200
2201 // First look the name up in the hashtable.
2202 if (sid <= 0 || sid > script_items.ga_len)
2203 return -1;
2204 ht = &SCRIPT_VARS(sid);
2205 di = find_var_in_ht(ht, 0, name, TRUE);
2206 if (di == NULL)
2207 return -2;
2208
2209 // Now find the svar_T index in sn_var_vals.
2210 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2211 {
2212 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2213
2214 if (sv->sv_tv == &di->di_tv)
2215 {
2216 if (check_writable && sv->sv_const)
2217 semsg(_(e_readonlyvar), name);
2218 return idx;
2219 }
2220 }
2221 return -1;
2222}
2223
2224/*
2225 * Find "name" in imported items of the current script/
2226 */
2227 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002228find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002229{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002230 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 int idx;
2232
2233 if (cctx != NULL)
2234 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2235 {
2236 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2237 + idx;
2238
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002239 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2240 : STRLEN(import->imp_name) == len
2241 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002242 return import;
2243 }
2244
2245 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2246 {
2247 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2248
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002249 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2250 : STRLEN(import->imp_name) == len
2251 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002252 return import;
2253 }
2254 return NULL;
2255}
2256
2257/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002258 * Free all imported variables.
2259 */
2260 static void
2261free_imported(cctx_T *cctx)
2262{
2263 int idx;
2264
2265 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2266 {
2267 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2268
2269 vim_free(import->imp_name);
2270 }
2271 ga_clear(&cctx->ctx_imports);
2272}
2273
2274/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002275 * Get the next line of the function from "cctx".
2276 * Returns NULL when at the end.
2277 */
2278 static char_u *
2279next_line_from_context(cctx_T *cctx)
2280{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002281 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002282
2283 do
2284 {
2285 ++cctx->ctx_lnum;
2286 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002287 {
2288 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002289 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002290 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002291 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002292 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002293 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2294 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002295 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002296 return line;
2297}
2298
2299/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002300 * Return TRUE if "p" points at a "#" but not at "#{".
2301 */
2302 static int
2303comment_start(char_u *p)
2304{
2305 return p[0] == '#' && p[1] != '{';
2306}
2307
2308/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002309 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002310 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002311 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2312 */
2313 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002314may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002315{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002316 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002317 {
2318 char_u *next = next_line_from_context(cctx);
2319
2320 if (next == NULL)
2321 return FAIL;
2322 *arg = skipwhite(next);
2323 }
2324 return OK;
2325}
2326
2327/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002328 * Generate an instruction to load script-local variable "name", without the
2329 * leading "s:".
2330 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002331 */
2332 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002333compile_load_scriptvar(
2334 cctx_T *cctx,
2335 char_u *name, // variable NUL terminated
2336 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002337 char_u **end, // end of variable
2338 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002339{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002340 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002341 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2342 imported_T *import;
2343
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002344 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002345 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002346 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002347 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2348 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002349 }
2350 if (idx >= 0)
2351 {
2352 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2353
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002354 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002355 current_sctx.sc_sid, idx, sv->sv_type);
2356 return OK;
2357 }
2358
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002359 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002360 if (import != NULL)
2361 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002362 if (import->imp_all)
2363 {
2364 char_u *p = skipwhite(*end);
2365 int name_len;
2366 ufunc_T *ufunc;
2367 type_T *type;
2368
2369 // Used "import * as Name", need to lookup the member.
2370 if (*p != '.')
2371 {
2372 semsg(_("E1060: expected dot after name: %s"), start);
2373 return FAIL;
2374 }
2375 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002376 if (VIM_ISWHITE(*p))
2377 {
2378 emsg(_("E1074: no white space allowed after dot"));
2379 return FAIL;
2380 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002381
2382 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2383 // TODO: what if it is a function?
2384 if (idx < 0)
2385 return FAIL;
2386 *end = p;
2387
2388 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2389 import->imp_sid,
2390 idx,
2391 type);
2392 }
2393 else
2394 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002395 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002396 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2397 import->imp_sid,
2398 import->imp_var_vals_idx,
2399 import->imp_type);
2400 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002401 return OK;
2402 }
2403
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002404 if (error)
2405 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002406 return FAIL;
2407}
2408
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002409 static int
2410generate_funcref(cctx_T *cctx, char_u *name)
2411{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002412 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002413
2414 if (ufunc == NULL)
2415 return FAIL;
2416
2417 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2418}
2419
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002420/*
2421 * Compile a variable name into a load instruction.
2422 * "end" points to just after the name.
2423 * When "error" is FALSE do not give an error when not found.
2424 */
2425 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002426compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002427{
2428 type_T *type;
2429 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002430 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002431 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002432 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002433
2434 if (*(*arg + 1) == ':')
2435 {
2436 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002437 if (end <= *arg + 2)
2438 name = vim_strsave((char_u *)"[empty]");
2439 else
2440 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002441 if (name == NULL)
2442 return FAIL;
2443
2444 if (**arg == 'v')
2445 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002446 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002447 }
2448 else if (**arg == 'g')
2449 {
2450 // Global variables can be defined later, thus we don't check if it
2451 // exists, give error at runtime.
2452 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2453 }
2454 else if (**arg == 's')
2455 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002456 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002457 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002458 else if (**arg == 'b')
2459 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002460 // Buffer-local variables can be defined later, thus we don't check
2461 // if it exists, give error at runtime.
2462 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002463 }
2464 else if (**arg == 'w')
2465 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002466 // Window-local variables can be defined later, thus we don't check
2467 // if it exists, give error at runtime.
2468 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002469 }
2470 else if (**arg == 't')
2471 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002472 // Tabpage-local variables can be defined later, thus we don't
2473 // check if it exists, give error at runtime.
2474 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002475 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002476 else
2477 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002478 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002479 goto theend;
2480 }
2481 }
2482 else
2483 {
2484 size_t len = end - *arg;
2485 int idx;
2486 int gen_load = FALSE;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002487 int gen_load_outer = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002488
2489 name = vim_strnsave(*arg, end - *arg);
2490 if (name == NULL)
2491 return FAIL;
2492
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002493 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002494 {
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002495 if (!gen_load_outer)
2496 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002497 }
2498 else
2499 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002500 lvar_T *lvar = lookup_local(*arg, len, cctx);
2501
2502 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002503 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002504 type = lvar->lv_type;
2505 idx = lvar->lv_idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002506 if (lvar->lv_from_outer)
2507 gen_load_outer = TRUE;
2508 else
2509 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002510 }
2511 else
2512 {
2513 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2514 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2515 res = generate_PUSHBOOL(cctx, **arg == 't'
2516 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002517 else
2518 {
2519 // "var" can be script-local even without using "s:" if it
2520 // already exists.
2521 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2522 == SCRIPT_VERSION_VIM9
2523 || lookup_script(*arg, len) == OK)
2524 res = compile_load_scriptvar(cctx, name, *arg, &end,
2525 FALSE);
2526
2527 // When the name starts with an uppercase letter or "x:" it
2528 // can be a user defined function.
2529 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2530 res = generate_funcref(cctx, name);
2531 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002532 }
2533 }
2534 if (gen_load)
2535 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002536 if (gen_load_outer)
2537 res = generate_LOAD(cctx, ISN_LOADOUTER, idx, NULL, type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002538 }
2539
2540 *arg = end;
2541
2542theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002543 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002544 semsg(_(e_var_notfound), name);
2545 vim_free(name);
2546 return res;
2547}
2548
2549/*
2550 * Compile the argument expressions.
2551 * "arg" points to just after the "(" and is advanced to after the ")"
2552 */
2553 static int
2554compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2555{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002556 char_u *p = *arg;
2557 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002558
Bram Moolenaare6085c52020-04-12 20:19:16 +02002559 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002560 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002561 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002562 {
2563 p = next_line_from_context(cctx);
2564 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002565 goto failret;
2566 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002567 p = skipwhite(p);
2568 }
2569 if (*p == ')')
2570 {
2571 *arg = p + 1;
2572 return OK;
2573 }
2574
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002575 if (compile_expr1(&p, cctx) == FAIL)
2576 return FAIL;
2577 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002578
2579 if (*p != ',' && *skipwhite(p) == ',')
2580 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002581 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002582 p = skipwhite(p);
2583 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002584 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002585 {
2586 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002587 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002588 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002589 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002590 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002591 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002592 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002593failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002594 emsg(_(e_missing_close));
2595 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002596}
2597
2598/*
2599 * Compile a function call: name(arg1, arg2)
2600 * "arg" points to "name", "arg + varlen" to the "(".
2601 * "argcount_init" is 1 for "value->method()"
2602 * Instructions:
2603 * EVAL arg1
2604 * EVAL arg2
2605 * BCALL / DCALL / UCALL
2606 */
2607 static int
2608compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2609{
2610 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002611 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002612 int argcount = argcount_init;
2613 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002614 char_u fname_buf[FLEN_FIXED + 1];
2615 char_u *tofree = NULL;
2616 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002617 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002618 int res = FAIL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02002619 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002620
2621 if (varlen >= sizeof(namebuf))
2622 {
2623 semsg(_("E1011: name too long: %s"), name);
2624 return FAIL;
2625 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002626 vim_strncpy(namebuf, *arg, varlen);
2627 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002628
2629 *arg = skipwhite(*arg + varlen + 1);
2630 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002631 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002632
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002633 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002634 {
2635 int idx;
2636
2637 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002638 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002639 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002640 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002641 else
2642 semsg(_(e_unknownfunc), namebuf);
2643 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002644 }
2645
Bram Moolenaar04b12692020-05-04 23:24:44 +02002646 // Check if the name is a nested function.
2647 lvar = lookup_local(namebuf, varlen, cctx);
2648 if (lvar != NULL && lvar->lv_func_idx > 0)
2649 {
2650 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
2651 + lvar->lv_func_idx;
2652 res = generate_CALL(cctx, dfunc->df_ufunc, argcount);
2653 goto theend;
2654 }
2655
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002656 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002657 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002658 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002659 {
2660 res = generate_CALL(cctx, ufunc, argcount);
2661 goto theend;
2662 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002663
2664 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002665 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002666 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002667 if (STRNCMP(namebuf, "g:", 2) != 0
2668 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002669 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002670 garray_T *stack = &cctx->ctx_type_stack;
2671 type_T *type;
2672
2673 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2674 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002675 goto theend;
2676 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002677
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002678 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002679 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002680 if (STRNCMP(namebuf, "g:", 2) == 0)
2681 res = generate_UCALL(cctx, name, argcount);
2682 else
2683 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002684
2685theend:
2686 vim_free(tofree);
2687 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002688}
2689
2690// like NAMESPACE_CHAR but with 'a' and 'l'.
2691#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2692
2693/*
2694 * Find the end of a variable or function name. Unlike find_name_end() this
2695 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002696 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002697 * Return a pointer to just after the name. Equal to "arg" if there is no
2698 * valid name.
2699 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002700 static char_u *
2701to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002702{
2703 char_u *p;
2704
2705 // Quick check for valid starting character.
2706 if (!eval_isnamec1(*arg))
2707 return arg;
2708
2709 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2710 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2711 // and can be used in slice "[n:]".
2712 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002713 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002714 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2715 break;
2716 return p;
2717}
2718
2719/*
2720 * Like to_name_end() but also skip over a list or dict constant.
2721 */
2722 char_u *
2723to_name_const_end(char_u *arg)
2724{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002725 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002726 typval_T rettv;
2727
2728 if (p == arg && *arg == '[')
2729 {
2730
2731 // Can be "[1, 2, 3]->Func()".
2732 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2733 p = arg;
2734 }
2735 else if (p == arg && *arg == '#' && arg[1] == '{')
2736 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002737 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002738 ++p;
2739 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2740 p = arg;
2741 }
2742 else if (p == arg && *arg == '{')
2743 {
2744 int ret = get_lambda_tv(&p, &rettv, FALSE);
2745
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002746 // Can be "{x -> ret}()".
2747 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002748 if (ret == NOTDONE)
2749 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2750 if (ret != OK)
2751 p = arg;
2752 }
2753
2754 return p;
2755}
2756
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002757/*
2758 * parse a list: [expr, expr]
2759 * "*arg" points to the '['.
2760 */
2761 static int
2762compile_list(char_u **arg, cctx_T *cctx)
2763{
2764 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002765 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002766 int count = 0;
2767
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002768 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002769 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002770 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002771 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002772 p = next_line_from_context(cctx);
2773 if (p == NULL)
2774 {
2775 semsg(_(e_list_end), *arg);
2776 return FAIL;
2777 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002778 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002779 p = skipwhite(p);
2780 }
2781 if (*p == ']')
2782 {
2783 ++p;
2784 // Allow for following comment, after at least one space.
2785 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2786 p += STRLEN(p);
2787 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002788 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002789 if (compile_expr1(&p, cctx) == FAIL)
2790 break;
2791 ++count;
2792 if (*p == ',')
2793 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002794 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002795 p = skipwhite(p);
2796 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002797 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002798
2799 generate_NEWLIST(cctx, count);
2800 return OK;
2801}
2802
2803/*
2804 * parse a lambda: {arg, arg -> expr}
2805 * "*arg" points to the '{'.
2806 */
2807 static int
2808compile_lambda(char_u **arg, cctx_T *cctx)
2809{
2810 garray_T *instr = &cctx->ctx_instr;
2811 typval_T rettv;
2812 ufunc_T *ufunc;
2813
2814 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002815 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002816 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002817
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002818 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002819 ++ufunc->uf_refcount;
2820 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002821 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002822
2823 // The function will have one line: "return {expr}".
2824 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002825 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002826
2827 if (ufunc->uf_dfunc_idx >= 0)
2828 {
2829 if (ga_grow(instr, 1) == FAIL)
2830 return FAIL;
2831 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2832 return OK;
2833 }
2834 return FAIL;
2835}
2836
2837/*
2838 * Compile a lamda call: expr->{lambda}(args)
2839 * "arg" points to the "{".
2840 */
2841 static int
2842compile_lambda_call(char_u **arg, cctx_T *cctx)
2843{
2844 ufunc_T *ufunc;
2845 typval_T rettv;
2846 int argcount = 1;
2847 int ret = FAIL;
2848
2849 // Get the funcref in "rettv".
2850 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2851 return FAIL;
2852
2853 if (**arg != '(')
2854 {
2855 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002856 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002857 else
2858 semsg(_(e_missing_paren), "lambda");
2859 clear_tv(&rettv);
2860 return FAIL;
2861 }
2862
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002863 ufunc = rettv.vval.v_partial->pt_func;
2864 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002865 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002866 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002867
2868 // The function will have one line: "return {expr}".
2869 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002870 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002871
2872 // compile the arguments
2873 *arg = skipwhite(*arg + 1);
2874 if (compile_arguments(arg, cctx, &argcount) == OK)
2875 // call the compiled function
2876 ret = generate_CALL(cctx, ufunc, argcount);
2877
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002878 return ret;
2879}
2880
2881/*
2882 * parse a dict: {'key': val} or #{key: val}
2883 * "*arg" points to the '{'.
2884 */
2885 static int
2886compile_dict(char_u **arg, cctx_T *cctx, int literal)
2887{
2888 garray_T *instr = &cctx->ctx_instr;
2889 int count = 0;
2890 dict_T *d = dict_alloc();
2891 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002892 char_u *whitep = *arg;
2893 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002894
2895 if (d == NULL)
2896 return FAIL;
2897 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002898 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002899 {
2900 char_u *key = NULL;
2901
Bram Moolenaar2c330432020-04-13 14:41:35 +02002902 while (**arg == NUL || (literal && **arg == '"')
2903 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002904 {
2905 *arg = next_line_from_context(cctx);
2906 if (*arg == NULL)
2907 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002908 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002909 *arg = skipwhite(*arg);
2910 }
2911
2912 if (**arg == '}')
2913 break;
2914
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002915 if (literal)
2916 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002917 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002918
Bram Moolenaar2c330432020-04-13 14:41:35 +02002919 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002920 {
2921 semsg(_("E1014: Invalid key: %s"), *arg);
2922 return FAIL;
2923 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002924 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002925 if (generate_PUSHS(cctx, key) == FAIL)
2926 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002927 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002928 }
2929 else
2930 {
2931 isn_T *isn;
2932
2933 if (compile_expr1(arg, cctx) == FAIL)
2934 return FAIL;
2935 // TODO: check type is string
2936 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2937 if (isn->isn_type == ISN_PUSHS)
2938 key = isn->isn_arg.string;
2939 }
2940
2941 // Check for duplicate keys, if using string keys.
2942 if (key != NULL)
2943 {
2944 item = dict_find(d, key, -1);
2945 if (item != NULL)
2946 {
2947 semsg(_(e_duplicate_key), key);
2948 goto failret;
2949 }
2950 item = dictitem_alloc(key);
2951 if (item != NULL)
2952 {
2953 item->di_tv.v_type = VAR_UNKNOWN;
2954 item->di_tv.v_lock = 0;
2955 if (dict_add(d, item) == FAIL)
2956 dictitem_free(item);
2957 }
2958 }
2959
2960 *arg = skipwhite(*arg);
2961 if (**arg != ':')
2962 {
2963 semsg(_(e_missing_dict_colon), *arg);
2964 return FAIL;
2965 }
2966
Bram Moolenaar2c330432020-04-13 14:41:35 +02002967 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002968 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002969 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002970 {
2971 *arg = next_line_from_context(cctx);
2972 if (*arg == NULL)
2973 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002974 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002975 *arg = skipwhite(*arg);
2976 }
2977
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002978 if (compile_expr1(arg, cctx) == FAIL)
2979 return FAIL;
2980 ++count;
2981
Bram Moolenaar2c330432020-04-13 14:41:35 +02002982 whitep = *arg;
2983 p = skipwhite(*arg);
2984 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002985 {
2986 *arg = next_line_from_context(cctx);
2987 if (*arg == NULL)
2988 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002989 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002990 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002991 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002992 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002993 if (**arg == '}')
2994 break;
2995 if (**arg != ',')
2996 {
2997 semsg(_(e_missing_dict_comma), *arg);
2998 goto failret;
2999 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003000 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003001 *arg = skipwhite(*arg + 1);
3002 }
3003
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003004 *arg = *arg + 1;
3005
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003006 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003007 p = skipwhite(*arg);
3008 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003009 *arg += STRLEN(*arg);
3010
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003011 dict_unref(d);
3012 return generate_NEWDICT(cctx, count);
3013
3014failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003015 if (*arg == NULL)
3016 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003017 dict_unref(d);
3018 return FAIL;
3019}
3020
3021/*
3022 * Compile "&option".
3023 */
3024 static int
3025compile_get_option(char_u **arg, cctx_T *cctx)
3026{
3027 typval_T rettv;
3028 char_u *start = *arg;
3029 int ret;
3030
3031 // parse the option and get the current value to get the type.
3032 rettv.v_type = VAR_UNKNOWN;
3033 ret = get_option_tv(arg, &rettv, TRUE);
3034 if (ret == OK)
3035 {
3036 // include the '&' in the name, get_option_tv() expects it.
3037 char_u *name = vim_strnsave(start, *arg - start);
3038 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
3039
3040 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3041 vim_free(name);
3042 }
3043 clear_tv(&rettv);
3044
3045 return ret;
3046}
3047
3048/*
3049 * Compile "$VAR".
3050 */
3051 static int
3052compile_get_env(char_u **arg, cctx_T *cctx)
3053{
3054 char_u *start = *arg;
3055 int len;
3056 int ret;
3057 char_u *name;
3058
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003059 ++*arg;
3060 len = get_env_len(arg);
3061 if (len == 0)
3062 {
3063 semsg(_(e_syntax_at), start - 1);
3064 return FAIL;
3065 }
3066
3067 // include the '$' in the name, get_env_tv() expects it.
3068 name = vim_strnsave(start, len + 1);
3069 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3070 vim_free(name);
3071 return ret;
3072}
3073
3074/*
3075 * Compile "@r".
3076 */
3077 static int
3078compile_get_register(char_u **arg, cctx_T *cctx)
3079{
3080 int ret;
3081
3082 ++*arg;
3083 if (**arg == NUL)
3084 {
3085 semsg(_(e_syntax_at), *arg - 1);
3086 return FAIL;
3087 }
3088 if (!valid_yank_reg(**arg, TRUE))
3089 {
3090 emsg_invreg(**arg);
3091 return FAIL;
3092 }
3093 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3094 ++*arg;
3095 return ret;
3096}
3097
3098/*
3099 * Apply leading '!', '-' and '+' to constant "rettv".
3100 */
3101 static int
3102apply_leader(typval_T *rettv, char_u *start, char_u *end)
3103{
3104 char_u *p = end;
3105
3106 // this works from end to start
3107 while (p > start)
3108 {
3109 --p;
3110 if (*p == '-' || *p == '+')
3111 {
3112 // only '-' has an effect, for '+' we only check the type
3113#ifdef FEAT_FLOAT
3114 if (rettv->v_type == VAR_FLOAT)
3115 {
3116 if (*p == '-')
3117 rettv->vval.v_float = -rettv->vval.v_float;
3118 }
3119 else
3120#endif
3121 {
3122 varnumber_T val;
3123 int error = FALSE;
3124
3125 // tv_get_number_chk() accepts a string, but we don't want that
3126 // here
3127 if (check_not_string(rettv) == FAIL)
3128 return FAIL;
3129 val = tv_get_number_chk(rettv, &error);
3130 clear_tv(rettv);
3131 if (error)
3132 return FAIL;
3133 if (*p == '-')
3134 val = -val;
3135 rettv->v_type = VAR_NUMBER;
3136 rettv->vval.v_number = val;
3137 }
3138 }
3139 else
3140 {
3141 int v = tv2bool(rettv);
3142
3143 // '!' is permissive in the type.
3144 clear_tv(rettv);
3145 rettv->v_type = VAR_BOOL;
3146 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3147 }
3148 }
3149 return OK;
3150}
3151
3152/*
3153 * Recognize v: variables that are constants and set "rettv".
3154 */
3155 static void
3156get_vim_constant(char_u **arg, typval_T *rettv)
3157{
3158 if (STRNCMP(*arg, "v:true", 6) == 0)
3159 {
3160 rettv->v_type = VAR_BOOL;
3161 rettv->vval.v_number = VVAL_TRUE;
3162 *arg += 6;
3163 }
3164 else if (STRNCMP(*arg, "v:false", 7) == 0)
3165 {
3166 rettv->v_type = VAR_BOOL;
3167 rettv->vval.v_number = VVAL_FALSE;
3168 *arg += 7;
3169 }
3170 else if (STRNCMP(*arg, "v:null", 6) == 0)
3171 {
3172 rettv->v_type = VAR_SPECIAL;
3173 rettv->vval.v_number = VVAL_NULL;
3174 *arg += 6;
3175 }
3176 else if (STRNCMP(*arg, "v:none", 6) == 0)
3177 {
3178 rettv->v_type = VAR_SPECIAL;
3179 rettv->vval.v_number = VVAL_NONE;
3180 *arg += 6;
3181 }
3182}
3183
3184/*
3185 * Compile code to apply '-', '+' and '!'.
3186 */
3187 static int
3188compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3189{
3190 char_u *p = end;
3191
3192 // this works from end to start
3193 while (p > start)
3194 {
3195 --p;
3196 if (*p == '-' || *p == '+')
3197 {
3198 int negate = *p == '-';
3199 isn_T *isn;
3200
3201 // TODO: check type
3202 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3203 {
3204 --p;
3205 if (*p == '-')
3206 negate = !negate;
3207 }
3208 // only '-' has an effect, for '+' we only check the type
3209 if (negate)
3210 isn = generate_instr(cctx, ISN_NEGATENR);
3211 else
3212 isn = generate_instr(cctx, ISN_CHECKNR);
3213 if (isn == NULL)
3214 return FAIL;
3215 }
3216 else
3217 {
3218 int invert = TRUE;
3219
3220 while (p > start && p[-1] == '!')
3221 {
3222 --p;
3223 invert = !invert;
3224 }
3225 if (generate_2BOOL(cctx, invert) == FAIL)
3226 return FAIL;
3227 }
3228 }
3229 return OK;
3230}
3231
3232/*
3233 * Compile whatever comes after "name" or "name()".
3234 */
3235 static int
3236compile_subscript(
3237 char_u **arg,
3238 cctx_T *cctx,
3239 char_u **start_leader,
3240 char_u *end_leader)
3241{
3242 for (;;)
3243 {
3244 if (**arg == '(')
3245 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003246 garray_T *stack = &cctx->ctx_type_stack;
3247 type_T *type;
3248 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003249
3250 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003251 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3252
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003253 *arg = skipwhite(*arg + 1);
3254 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3255 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003256 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003257 return FAIL;
3258 }
3259 else if (**arg == '-' && (*arg)[1] == '>')
3260 {
3261 char_u *p;
3262
3263 // something->method()
3264 // Apply the '!', '-' and '+' first:
3265 // -1.0->func() works like (-1.0)->func()
3266 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3267 return FAIL;
3268 *start_leader = end_leader; // don't apply again later
3269
3270 *arg = skipwhite(*arg + 2);
3271 if (**arg == '{')
3272 {
3273 // lambda call: list->{lambda}
3274 if (compile_lambda_call(arg, cctx) == FAIL)
3275 return FAIL;
3276 }
3277 else
3278 {
3279 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003280 p = *arg;
3281 if (ASCII_ISALPHA(*p) && p[1] == ':')
3282 p += 2;
3283 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003284 ;
3285 if (*p != '(')
3286 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003287 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003288 return FAIL;
3289 }
3290 // TODO: base value may not be the first argument
3291 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3292 return FAIL;
3293 }
3294 }
3295 else if (**arg == '[')
3296 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003297 garray_T *stack;
3298 type_T **typep;
3299
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003300 // list index: list[123]
3301 // TODO: more arguments
3302 // TODO: dict member dict['name']
3303 *arg = skipwhite(*arg + 1);
3304 if (compile_expr1(arg, cctx) == FAIL)
3305 return FAIL;
3306
3307 if (**arg != ']')
3308 {
3309 emsg(_(e_missbrac));
3310 return FAIL;
3311 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003312 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003313
3314 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3315 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003316 stack = &cctx->ctx_type_stack;
3317 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3318 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3319 {
3320 emsg(_(e_listreq));
3321 return FAIL;
3322 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003323 if ((*typep)->tt_type == VAR_LIST)
3324 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003325 }
3326 else if (**arg == '.' && (*arg)[1] != '.')
3327 {
3328 char_u *p;
3329
3330 ++*arg;
3331 p = *arg;
3332 // dictionary member: dict.name
3333 if (eval_isnamec1(*p))
3334 while (eval_isnamec(*p))
3335 MB_PTR_ADV(p);
3336 if (p == *arg)
3337 {
3338 semsg(_(e_syntax_at), *arg);
3339 return FAIL;
3340 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003341 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3342 return FAIL;
3343 *arg = p;
3344 }
3345 else
3346 break;
3347 }
3348
3349 // TODO - see handle_subscript():
3350 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3351 // Don't do this when "Func" is already a partial that was bound
3352 // explicitly (pt_auto is FALSE).
3353
3354 return OK;
3355}
3356
3357/*
3358 * Compile an expression at "*p" and add instructions to "instr".
3359 * "p" is advanced until after the expression, skipping white space.
3360 *
3361 * This is the equivalent of eval1(), eval2(), etc.
3362 */
3363
3364/*
3365 * number number constant
3366 * 0zFFFFFFFF Blob constant
3367 * "string" string constant
3368 * 'string' literal string constant
3369 * &option-name option value
3370 * @r register contents
3371 * identifier variable value
3372 * function() function call
3373 * $VAR environment variable
3374 * (expression) nested expression
3375 * [expr, expr] List
3376 * {key: val, key: val} Dictionary
3377 * #{key: val, key: val} Dictionary with literal keys
3378 *
3379 * Also handle:
3380 * ! in front logical NOT
3381 * - in front unary minus
3382 * + in front unary plus (ignored)
3383 * trailing (arg) funcref/partial call
3384 * trailing [] subscript in String or List
3385 * trailing .name entry in Dictionary
3386 * trailing ->name() method call
3387 */
3388 static int
3389compile_expr7(char_u **arg, cctx_T *cctx)
3390{
3391 typval_T rettv;
3392 char_u *start_leader, *end_leader;
3393 int ret = OK;
3394
3395 /*
3396 * Skip '!', '-' and '+' characters. They are handled later.
3397 */
3398 start_leader = *arg;
3399 while (**arg == '!' || **arg == '-' || **arg == '+')
3400 *arg = skipwhite(*arg + 1);
3401 end_leader = *arg;
3402
3403 rettv.v_type = VAR_UNKNOWN;
3404 switch (**arg)
3405 {
3406 /*
3407 * Number constant.
3408 */
3409 case '0': // also for blob starting with 0z
3410 case '1':
3411 case '2':
3412 case '3':
3413 case '4':
3414 case '5':
3415 case '6':
3416 case '7':
3417 case '8':
3418 case '9':
3419 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3420 return FAIL;
3421 break;
3422
3423 /*
3424 * String constant: "string".
3425 */
3426 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3427 return FAIL;
3428 break;
3429
3430 /*
3431 * Literal string constant: 'str''ing'.
3432 */
3433 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3434 return FAIL;
3435 break;
3436
3437 /*
3438 * Constant Vim variable.
3439 */
3440 case 'v': get_vim_constant(arg, &rettv);
3441 ret = NOTDONE;
3442 break;
3443
3444 /*
3445 * List: [expr, expr]
3446 */
3447 case '[': ret = compile_list(arg, cctx);
3448 break;
3449
3450 /*
3451 * Dictionary: #{key: val, key: val}
3452 */
3453 case '#': if ((*arg)[1] == '{')
3454 {
3455 ++*arg;
3456 ret = compile_dict(arg, cctx, TRUE);
3457 }
3458 else
3459 ret = NOTDONE;
3460 break;
3461
3462 /*
3463 * Lambda: {arg, arg -> expr}
3464 * Dictionary: {'key': val, 'key': val}
3465 */
3466 case '{': {
3467 char_u *start = skipwhite(*arg + 1);
3468
3469 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003470 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003471 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003472 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003473 if (ret != FAIL && *start == '>')
3474 ret = compile_lambda(arg, cctx);
3475 else
3476 ret = compile_dict(arg, cctx, FALSE);
3477 }
3478 break;
3479
3480 /*
3481 * Option value: &name
3482 */
3483 case '&': ret = compile_get_option(arg, cctx);
3484 break;
3485
3486 /*
3487 * Environment variable: $VAR.
3488 */
3489 case '$': ret = compile_get_env(arg, cctx);
3490 break;
3491
3492 /*
3493 * Register contents: @r.
3494 */
3495 case '@': ret = compile_get_register(arg, cctx);
3496 break;
3497 /*
3498 * nested expression: (expression).
3499 */
3500 case '(': *arg = skipwhite(*arg + 1);
3501 ret = compile_expr1(arg, cctx); // recursive!
3502 *arg = skipwhite(*arg);
3503 if (**arg == ')')
3504 ++*arg;
3505 else if (ret == OK)
3506 {
3507 emsg(_(e_missing_close));
3508 ret = FAIL;
3509 }
3510 break;
3511
3512 default: ret = NOTDONE;
3513 break;
3514 }
3515 if (ret == FAIL)
3516 return FAIL;
3517
3518 if (rettv.v_type != VAR_UNKNOWN)
3519 {
3520 // apply the '!', '-' and '+' before the constant
3521 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3522 {
3523 clear_tv(&rettv);
3524 return FAIL;
3525 }
3526 start_leader = end_leader; // don't apply again below
3527
3528 // push constant
3529 switch (rettv.v_type)
3530 {
3531 case VAR_BOOL:
3532 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3533 break;
3534 case VAR_SPECIAL:
3535 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3536 break;
3537 case VAR_NUMBER:
3538 generate_PUSHNR(cctx, rettv.vval.v_number);
3539 break;
3540#ifdef FEAT_FLOAT
3541 case VAR_FLOAT:
3542 generate_PUSHF(cctx, rettv.vval.v_float);
3543 break;
3544#endif
3545 case VAR_BLOB:
3546 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3547 rettv.vval.v_blob = NULL;
3548 break;
3549 case VAR_STRING:
3550 generate_PUSHS(cctx, rettv.vval.v_string);
3551 rettv.vval.v_string = NULL;
3552 break;
3553 default:
3554 iemsg("constant type missing");
3555 return FAIL;
3556 }
3557 }
3558 else if (ret == NOTDONE)
3559 {
3560 char_u *p;
3561 int r;
3562
3563 if (!eval_isnamec1(**arg))
3564 {
3565 semsg(_("E1015: Name expected: %s"), *arg);
3566 return FAIL;
3567 }
3568
3569 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003570 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003571 if (*p == '(')
3572 r = compile_call(arg, p - *arg, cctx, 0);
3573 else
3574 r = compile_load(arg, p, cctx, TRUE);
3575 if (r == FAIL)
3576 return FAIL;
3577 }
3578
3579 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3580 return FAIL;
3581
3582 // Now deal with prefixed '-', '+' and '!', if not done already.
3583 return compile_leader(cctx, start_leader, end_leader);
3584}
3585
3586/*
3587 * * number multiplication
3588 * / number division
3589 * % number modulo
3590 */
3591 static int
3592compile_expr6(char_u **arg, cctx_T *cctx)
3593{
3594 char_u *op;
3595
3596 // get the first variable
3597 if (compile_expr7(arg, cctx) == FAIL)
3598 return FAIL;
3599
3600 /*
3601 * Repeat computing, until no "*", "/" or "%" is following.
3602 */
3603 for (;;)
3604 {
3605 op = skipwhite(*arg);
3606 if (*op != '*' && *op != '/' && *op != '%')
3607 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003608 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003609 {
3610 char_u buf[3];
3611
3612 vim_strncpy(buf, op, 1);
3613 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003614 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003615 }
3616 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003617 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003618 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003619
3620 // get the second variable
3621 if (compile_expr7(arg, cctx) == FAIL)
3622 return FAIL;
3623
3624 generate_two_op(cctx, op);
3625 }
3626
3627 return OK;
3628}
3629
3630/*
3631 * + number addition
3632 * - number subtraction
3633 * .. string concatenation
3634 */
3635 static int
3636compile_expr5(char_u **arg, cctx_T *cctx)
3637{
3638 char_u *op;
3639 int oplen;
3640
3641 // get the first variable
3642 if (compile_expr6(arg, cctx) == FAIL)
3643 return FAIL;
3644
3645 /*
3646 * Repeat computing, until no "+", "-" or ".." is following.
3647 */
3648 for (;;)
3649 {
3650 op = skipwhite(*arg);
3651 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3652 break;
3653 oplen = (*op == '.' ? 2 : 1);
3654
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003655 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003656 {
3657 char_u buf[3];
3658
3659 vim_strncpy(buf, op, oplen);
3660 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003661 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003662 }
3663
3664 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003665 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003666 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003667
3668 // get the second variable
3669 if (compile_expr6(arg, cctx) == FAIL)
3670 return FAIL;
3671
3672 if (*op == '.')
3673 {
3674 if (may_generate_2STRING(-2, cctx) == FAIL
3675 || may_generate_2STRING(-1, cctx) == FAIL)
3676 return FAIL;
3677 generate_instr_drop(cctx, ISN_CONCAT, 1);
3678 }
3679 else
3680 generate_two_op(cctx, op);
3681 }
3682
3683 return OK;
3684}
3685
Bram Moolenaar080457c2020-03-03 21:53:32 +01003686 static exptype_T
3687get_compare_type(char_u *p, int *len, int *type_is)
3688{
3689 exptype_T type = EXPR_UNKNOWN;
3690 int i;
3691
3692 switch (p[0])
3693 {
3694 case '=': if (p[1] == '=')
3695 type = EXPR_EQUAL;
3696 else if (p[1] == '~')
3697 type = EXPR_MATCH;
3698 break;
3699 case '!': if (p[1] == '=')
3700 type = EXPR_NEQUAL;
3701 else if (p[1] == '~')
3702 type = EXPR_NOMATCH;
3703 break;
3704 case '>': if (p[1] != '=')
3705 {
3706 type = EXPR_GREATER;
3707 *len = 1;
3708 }
3709 else
3710 type = EXPR_GEQUAL;
3711 break;
3712 case '<': if (p[1] != '=')
3713 {
3714 type = EXPR_SMALLER;
3715 *len = 1;
3716 }
3717 else
3718 type = EXPR_SEQUAL;
3719 break;
3720 case 'i': if (p[1] == 's')
3721 {
3722 // "is" and "isnot"; but not a prefix of a name
3723 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3724 *len = 5;
3725 i = p[*len];
3726 if (!isalnum(i) && i != '_')
3727 {
3728 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3729 *type_is = TRUE;
3730 }
3731 }
3732 break;
3733 }
3734 return type;
3735}
3736
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003737/*
3738 * expr5a == expr5b
3739 * expr5a =~ expr5b
3740 * expr5a != expr5b
3741 * expr5a !~ expr5b
3742 * expr5a > expr5b
3743 * expr5a >= expr5b
3744 * expr5a < expr5b
3745 * expr5a <= expr5b
3746 * expr5a is expr5b
3747 * expr5a isnot expr5b
3748 *
3749 * Produces instructions:
3750 * EVAL expr5a Push result of "expr5a"
3751 * EVAL expr5b Push result of "expr5b"
3752 * COMPARE one of the compare instructions
3753 */
3754 static int
3755compile_expr4(char_u **arg, cctx_T *cctx)
3756{
3757 exptype_T type = EXPR_UNKNOWN;
3758 char_u *p;
3759 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003760 int type_is = FALSE;
3761
3762 // get the first variable
3763 if (compile_expr5(arg, cctx) == FAIL)
3764 return FAIL;
3765
3766 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003767 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003768
3769 /*
3770 * If there is a comparative operator, use it.
3771 */
3772 if (type != EXPR_UNKNOWN)
3773 {
3774 int ic = FALSE; // Default: do not ignore case
3775
3776 if (type_is && (p[len] == '?' || p[len] == '#'))
3777 {
3778 semsg(_(e_invexpr2), *arg);
3779 return FAIL;
3780 }
3781 // extra question mark appended: ignore case
3782 if (p[len] == '?')
3783 {
3784 ic = TRUE;
3785 ++len;
3786 }
3787 // extra '#' appended: match case (ignored)
3788 else if (p[len] == '#')
3789 ++len;
3790 // nothing appended: match case
3791
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003792 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003793 {
3794 char_u buf[7];
3795
3796 vim_strncpy(buf, p, len);
3797 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003798 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003799 }
3800
3801 // get the second variable
3802 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003803 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003804 return FAIL;
3805
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003806 if (compile_expr5(arg, cctx) == FAIL)
3807 return FAIL;
3808
3809 generate_COMPARE(cctx, type, ic);
3810 }
3811
3812 return OK;
3813}
3814
3815/*
3816 * Compile || or &&.
3817 */
3818 static int
3819compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3820{
3821 char_u *p = skipwhite(*arg);
3822 int opchar = *op;
3823
3824 if (p[0] == opchar && p[1] == opchar)
3825 {
3826 garray_T *instr = &cctx->ctx_instr;
3827 garray_T end_ga;
3828
3829 /*
3830 * Repeat until there is no following "||" or "&&"
3831 */
3832 ga_init2(&end_ga, sizeof(int), 10);
3833 while (p[0] == opchar && p[1] == opchar)
3834 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003835 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3836 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003837 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003838 return FAIL;
3839 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003840
3841 if (ga_grow(&end_ga, 1) == FAIL)
3842 {
3843 ga_clear(&end_ga);
3844 return FAIL;
3845 }
3846 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3847 ++end_ga.ga_len;
3848 generate_JUMP(cctx, opchar == '|'
3849 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3850
3851 // eval the next expression
3852 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003853 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003854 return FAIL;
3855
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003856 if ((opchar == '|' ? compile_expr3(arg, cctx)
3857 : compile_expr4(arg, cctx)) == FAIL)
3858 {
3859 ga_clear(&end_ga);
3860 return FAIL;
3861 }
3862 p = skipwhite(*arg);
3863 }
3864
3865 // Fill in the end label in all jumps.
3866 while (end_ga.ga_len > 0)
3867 {
3868 isn_T *isn;
3869
3870 --end_ga.ga_len;
3871 isn = ((isn_T *)instr->ga_data)
3872 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3873 isn->isn_arg.jump.jump_where = instr->ga_len;
3874 }
3875 ga_clear(&end_ga);
3876 }
3877
3878 return OK;
3879}
3880
3881/*
3882 * expr4a && expr4a && expr4a logical AND
3883 *
3884 * Produces instructions:
3885 * EVAL expr4a Push result of "expr4a"
3886 * JUMP_AND_KEEP_IF_FALSE end
3887 * EVAL expr4b Push result of "expr4b"
3888 * JUMP_AND_KEEP_IF_FALSE end
3889 * EVAL expr4c Push result of "expr4c"
3890 * end:
3891 */
3892 static int
3893compile_expr3(char_u **arg, cctx_T *cctx)
3894{
3895 // get the first variable
3896 if (compile_expr4(arg, cctx) == FAIL)
3897 return FAIL;
3898
3899 // || and && work almost the same
3900 return compile_and_or(arg, cctx, "&&");
3901}
3902
3903/*
3904 * expr3a || expr3b || expr3c logical OR
3905 *
3906 * Produces instructions:
3907 * EVAL expr3a Push result of "expr3a"
3908 * JUMP_AND_KEEP_IF_TRUE end
3909 * EVAL expr3b Push result of "expr3b"
3910 * JUMP_AND_KEEP_IF_TRUE end
3911 * EVAL expr3c Push result of "expr3c"
3912 * end:
3913 */
3914 static int
3915compile_expr2(char_u **arg, cctx_T *cctx)
3916{
3917 // eval the first expression
3918 if (compile_expr3(arg, cctx) == FAIL)
3919 return FAIL;
3920
3921 // || and && work almost the same
3922 return compile_and_or(arg, cctx, "||");
3923}
3924
3925/*
3926 * Toplevel expression: expr2 ? expr1a : expr1b
3927 *
3928 * Produces instructions:
3929 * EVAL expr2 Push result of "expr"
3930 * JUMP_IF_FALSE alt jump if false
3931 * EVAL expr1a
3932 * JUMP_ALWAYS end
3933 * alt: EVAL expr1b
3934 * end:
3935 */
3936 static int
3937compile_expr1(char_u **arg, cctx_T *cctx)
3938{
3939 char_u *p;
3940
Bram Moolenaar3df02f52020-05-03 15:47:33 +02003941 // TODO: Try parsing as a constant. If that works just one PUSH
3942 // instruction needs to be generated.
3943
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003944 // evaluate the first expression
3945 if (compile_expr2(arg, cctx) == FAIL)
3946 return FAIL;
3947
3948 p = skipwhite(*arg);
3949 if (*p == '?')
3950 {
3951 garray_T *instr = &cctx->ctx_instr;
3952 garray_T *stack = &cctx->ctx_type_stack;
3953 int alt_idx = instr->ga_len;
3954 int end_idx;
3955 isn_T *isn;
3956 type_T *type1;
3957 type_T *type2;
3958
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003959 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3960 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003961 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003962 return FAIL;
3963 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003964
3965 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3966
3967 // evaluate the second expression; any type is accepted
3968 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003969 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003970 return FAIL;
3971
Bram Moolenaara6d53682020-01-28 23:04:06 +01003972 if (compile_expr1(arg, cctx) == FAIL)
3973 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003974
3975 // remember the type and drop it
3976 --stack->ga_len;
3977 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3978
3979 end_idx = instr->ga_len;
3980 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3981
3982 // jump here from JUMP_IF_FALSE
3983 isn = ((isn_T *)instr->ga_data) + alt_idx;
3984 isn->isn_arg.jump.jump_where = instr->ga_len;
3985
3986 // Check for the ":".
3987 p = skipwhite(*arg);
3988 if (*p != ':')
3989 {
3990 emsg(_(e_missing_colon));
3991 return FAIL;
3992 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003993 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3994 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003995 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003996 return FAIL;
3997 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003998
3999 // evaluate the third expression
4000 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004001 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004002 return FAIL;
4003
Bram Moolenaara6d53682020-01-28 23:04:06 +01004004 if (compile_expr1(arg, cctx) == FAIL)
4005 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004006
4007 // If the types differ, the result has a more generic type.
4008 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01004009 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004010
4011 // jump here from JUMP_ALWAYS
4012 isn = ((isn_T *)instr->ga_data) + end_idx;
4013 isn->isn_arg.jump.jump_where = instr->ga_len;
4014 }
4015 return OK;
4016}
4017
4018/*
4019 * compile "return [expr]"
4020 */
4021 static char_u *
4022compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4023{
4024 char_u *p = arg;
4025 garray_T *stack = &cctx->ctx_type_stack;
4026 type_T *stack_type;
4027
4028 if (*p != NUL && *p != '|' && *p != '\n')
4029 {
4030 // compile return argument into instructions
4031 if (compile_expr1(&p, cctx) == FAIL)
4032 return NULL;
4033
4034 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4035 if (set_return_type)
4036 cctx->ctx_ufunc->uf_ret_type = stack_type;
4037 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
4038 == FAIL)
4039 return NULL;
4040 }
4041 else
4042 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004043 // "set_return_type" cannot be TRUE, only used for a lambda which
4044 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004045 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4046 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004047 {
4048 emsg(_("E1003: Missing return value"));
4049 return NULL;
4050 }
4051
4052 // No argument, return zero.
4053 generate_PUSHNR(cctx, 0);
4054 }
4055
4056 if (generate_instr(cctx, ISN_RETURN) == NULL)
4057 return NULL;
4058
4059 // "return val | endif" is possible
4060 return skipwhite(p);
4061}
4062
4063/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004064 * Get a line from the compilation context, compatible with exarg_T getline().
4065 * Return a pointer to the line in allocated memory.
4066 * Return NULL for end-of-file or some error.
4067 */
4068 static char_u *
4069exarg_getline(
4070 int c UNUSED,
4071 void *cookie,
4072 int indent UNUSED,
4073 int do_concat UNUSED)
4074{
4075 cctx_T *cctx = (cctx_T *)cookie;
4076
4077 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4078 {
4079 iemsg("Heredoc got to end");
4080 return NULL;
4081 }
4082 ++cctx->ctx_lnum;
4083 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4084 [cctx->ctx_lnum]);
4085}
4086
4087/*
4088 * Compile a nested :def command.
4089 */
4090 static char_u *
4091compile_nested_function(exarg_T *eap, cctx_T *cctx)
4092{
4093 char_u *name_start = eap->arg;
4094 char_u *name_end = to_name_end(eap->arg, FALSE);
4095 char_u *name = get_lambda_name();
4096 lvar_T *lvar;
4097 ufunc_T *ufunc;
4098
4099 eap->arg = name_end;
4100 eap->getline = exarg_getline;
4101 eap->cookie = cctx;
4102 eap->skip = cctx->ctx_skip == TRUE;
4103 eap->forceit = FALSE;
4104 ufunc = def_function(eap, name, cctx);
4105
4106 if (ufunc == NULL)
4107 return NULL;
4108
4109 // Define a local variable for the function, but change the index to -1 to
4110 // mark it as a function name.
4111 lvar = reserve_local(cctx, name_start, name_end - name_start,
4112 TRUE, &t_func_unknown);
4113 lvar->lv_idx = 0;
4114 ++cctx->ctx_locals_count; // doesn't count as a local variable
4115 lvar->lv_func_idx = ufunc->uf_dfunc_idx;
4116
4117 // TODO: warning for trailing?
4118 return (char_u *)"";
4119}
4120
4121/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004122 * Return the length of an assignment operator, or zero if there isn't one.
4123 */
4124 int
4125assignment_len(char_u *p, int *heredoc)
4126{
4127 if (*p == '=')
4128 {
4129 if (p[1] == '<' && p[2] == '<')
4130 {
4131 *heredoc = TRUE;
4132 return 3;
4133 }
4134 return 1;
4135 }
4136 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4137 return 2;
4138 if (STRNCMP(p, "..=", 3) == 0)
4139 return 3;
4140 return 0;
4141}
4142
4143// words that cannot be used as a variable
4144static char *reserved[] = {
4145 "true",
4146 "false",
4147 NULL
4148};
4149
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004150typedef enum {
4151 dest_local,
4152 dest_option,
4153 dest_env,
4154 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004155 dest_buffer,
4156 dest_window,
4157 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004158 dest_vimvar,
4159 dest_script,
4160 dest_reg,
4161} assign_dest_T;
4162
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004163/*
4164 * compile "let var [= expr]", "const var = expr" and "var = expr"
4165 * "arg" points to "var".
4166 */
4167 static char_u *
4168compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4169{
4170 char_u *p;
4171 char_u *ret = NULL;
4172 int var_count = 0;
4173 int semicolon = 0;
4174 size_t varlen;
4175 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004176 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004177 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004178 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004179 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004180 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004181 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004182 int oplen = 0;
4183 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004184 type_T *type = &t_any;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004185 lvar_T *lvar = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004186 char_u *name;
4187 char_u *sp;
4188 int has_type = FALSE;
4189 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4190 int instr_count = -1;
4191
4192 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4193 if (p == NULL)
4194 return NULL;
4195 if (var_count > 0)
4196 {
4197 // TODO: let [var, var] = list
4198 emsg("Cannot handle a list yet");
4199 return NULL;
4200 }
4201
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004202 // "a: type" is declaring variable "a" with a type, not "a:".
4203 if (is_decl && p == arg + 2 && p[-1] == ':')
4204 --p;
4205
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004206 varlen = p - arg;
4207 name = vim_strnsave(arg, (int)varlen);
4208 if (name == NULL)
4209 return NULL;
4210
Bram Moolenaar080457c2020-03-03 21:53:32 +01004211 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004212 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004213 if (*arg == '&')
4214 {
4215 int cc;
4216 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004217
Bram Moolenaar080457c2020-03-03 21:53:32 +01004218 dest = dest_option;
4219 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004220 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004221 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004222 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004223 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004224 if (is_decl)
4225 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004226 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004227 goto theend;
4228 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004229 p = arg;
4230 p = find_option_end(&p, &opt_flags);
4231 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004232 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004233 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004234 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004235 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004236 }
4237 cc = *p;
4238 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004239 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004240 *p = cc;
4241 if (opt_type == -3)
4242 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004243 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004244 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004245 }
4246 if (opt_type == -2 || opt_type == 0)
4247 type = &t_string;
4248 else
4249 type = &t_number; // both number and boolean option
4250 }
4251 else if (*arg == '$')
4252 {
4253 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004254 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004255 if (is_decl)
4256 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004257 semsg(_("E1065: Cannot declare an environment variable: %s"),
4258 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004259 goto theend;
4260 }
4261 }
4262 else if (*arg == '@')
4263 {
4264 if (!valid_yank_reg(arg[1], TRUE))
4265 {
4266 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004267 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004268 }
4269 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004270 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004271 if (is_decl)
4272 {
4273 semsg(_("E1066: Cannot declare a register: %s"), name);
4274 goto theend;
4275 }
4276 }
4277 else if (STRNCMP(arg, "g:", 2) == 0)
4278 {
4279 dest = dest_global;
4280 if (is_decl)
4281 {
4282 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4283 goto theend;
4284 }
4285 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004286 else if (STRNCMP(arg, "b:", 2) == 0)
4287 {
4288 dest = dest_buffer;
4289 if (is_decl)
4290 {
4291 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4292 goto theend;
4293 }
4294 }
4295 else if (STRNCMP(arg, "w:", 2) == 0)
4296 {
4297 dest = dest_window;
4298 if (is_decl)
4299 {
4300 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4301 goto theend;
4302 }
4303 }
4304 else if (STRNCMP(arg, "t:", 2) == 0)
4305 {
4306 dest = dest_tab;
4307 if (is_decl)
4308 {
4309 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4310 goto theend;
4311 }
4312 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004313 else if (STRNCMP(arg, "v:", 2) == 0)
4314 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004315 typval_T *vtv;
4316 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004317
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004318 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004319 if (vimvaridx < 0)
4320 {
4321 semsg(_(e_var_notfound), arg);
4322 goto theend;
4323 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004324 // We use the current value of "sandbox" here, is that OK?
4325 if (var_check_ro(di_flags, name, FALSE))
4326 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004327 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004328 vtv = get_vim_var_tv(vimvaridx);
4329 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004330 if (is_decl)
4331 {
4332 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4333 goto theend;
4334 }
4335 }
4336 else
4337 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004338 int idx;
4339
Bram Moolenaar080457c2020-03-03 21:53:32 +01004340 for (idx = 0; reserved[idx] != NULL; ++idx)
4341 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004342 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004343 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004344 goto theend;
4345 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004346
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004347 lvar = lookup_local(arg, varlen, cctx);
4348 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004349 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004350 if (is_decl)
4351 {
4352 semsg(_("E1017: Variable already declared: %s"), name);
4353 goto theend;
4354 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004355 else if (lvar->lv_const)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004356 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004357 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4358 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004359 }
4360 }
4361 else if (STRNCMP(arg, "s:", 2) == 0
4362 || lookup_script(arg, varlen) == OK
4363 || find_imported(arg, varlen, cctx) != NULL)
4364 {
4365 dest = dest_script;
4366 if (is_decl)
4367 {
4368 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004369 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004370 goto theend;
4371 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004372 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004373 else if (name[1] == ':' && name[2] != NUL)
4374 {
4375 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4376 goto theend;
4377 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004378 }
4379 }
4380
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004381 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004382 {
4383 if (is_decl && *p == ':')
4384 {
4385 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004386 if (!VIM_ISWHITE(p[1]))
4387 {
4388 semsg(_(e_white_after), ":");
4389 goto theend;
4390 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004391 p = skipwhite(p + 1);
4392 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004393 has_type = TRUE;
4394 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004395 else if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004396 type = lvar->lv_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004397 }
4398
4399 sp = p;
4400 p = skipwhite(p);
4401 op = p;
4402 oplen = assignment_len(p, &heredoc);
4403 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4404 {
4405 char_u buf[4];
4406
4407 vim_strncpy(buf, op, oplen);
4408 semsg(_(e_white_both), buf);
4409 }
4410
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004411 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004412 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004413 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004414 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004415 goto theend;
4416 }
4417
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004418 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004419 {
4420 if (oplen > 1 && !heredoc)
4421 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004422 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004423 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4424 name);
4425 goto theend;
4426 }
4427
4428 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004429 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004430 goto theend;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004431 lvar = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4432 if (lvar == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004433 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004434 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004435 }
4436
4437 if (heredoc)
4438 {
4439 list_T *l;
4440 listitem_T *li;
4441
4442 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02004443 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004444 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004445 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004446
4447 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004448 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004449 {
4450 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4451 li->li_tv.vval.v_string = NULL;
4452 }
4453 generate_NEWLIST(cctx, l->lv_len);
4454 type = &t_list_string;
4455 list_free(l);
4456 p += STRLEN(p);
4457 }
4458 else if (oplen > 0)
4459 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004460 int r;
4461 type_T *stacktype;
4462 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004463
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004464 // for "+=", "*=", "..=" etc. first load the current value
4465 if (*op != '=')
4466 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004467 switch (dest)
4468 {
4469 case dest_option:
4470 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004471 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004472 break;
4473 case dest_global:
4474 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4475 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004476 case dest_buffer:
4477 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4478 break;
4479 case dest_window:
4480 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4481 break;
4482 case dest_tab:
4483 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4484 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004485 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004486 compile_load_scriptvar(cctx,
4487 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004488 break;
4489 case dest_env:
4490 // Include $ in the name here
4491 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4492 break;
4493 case dest_reg:
4494 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4495 break;
4496 case dest_vimvar:
4497 generate_LOADV(cctx, name + 2, TRUE);
4498 break;
4499 case dest_local:
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004500 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004501 break;
4502 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004503 }
4504
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004505 // Compile the expression. Temporarily hide the new local variable
4506 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004507 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004508 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004509 instr_count = instr->ga_len;
4510 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004511 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004512 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004513 ++cctx->ctx_locals.ga_len;
4514 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004515 goto theend;
4516
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004517 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004518 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004519 stack = &cctx->ctx_type_stack;
4520 stacktype = stack->ga_len == 0 ? &t_void
4521 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004522 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004523 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004524 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004525 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004526 if (stacktype->tt_type == VAR_VOID)
4527 {
4528 emsg(_("E1031: Cannot use void value"));
4529 goto theend;
4530 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004531 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004532 {
4533 // An empty list or dict has a &t_void member, for a
4534 // variable that implies &t_any.
4535 if (stacktype == &t_list_empty)
4536 lvar->lv_type = &t_list_any;
4537 else if (stacktype == &t_dict_empty)
4538 lvar->lv_type = &t_dict_any;
4539 else
4540 lvar->lv_type = stacktype;
4541 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004542 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004543 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4544 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004545 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004546 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004547 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004548 }
4549 }
4550 else if (cmdidx == CMD_const)
4551 {
4552 emsg(_("E1021: const requires a value"));
4553 goto theend;
4554 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004555 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004556 {
4557 emsg(_("E1022: type or initialization required"));
4558 goto theend;
4559 }
4560 else
4561 {
4562 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004563 if (ga_grow(instr, 1) == FAIL)
4564 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004565 switch (type->tt_type)
4566 {
4567 case VAR_BOOL:
4568 generate_PUSHBOOL(cctx, VVAL_FALSE);
4569 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004570 case VAR_FLOAT:
4571#ifdef FEAT_FLOAT
4572 generate_PUSHF(cctx, 0.0);
4573#endif
4574 break;
4575 case VAR_STRING:
4576 generate_PUSHS(cctx, NULL);
4577 break;
4578 case VAR_BLOB:
4579 generate_PUSHBLOB(cctx, NULL);
4580 break;
4581 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004582 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004583 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004584 case VAR_LIST:
4585 generate_NEWLIST(cctx, 0);
4586 break;
4587 case VAR_DICT:
4588 generate_NEWDICT(cctx, 0);
4589 break;
4590 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004591 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004592 break;
4593 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004594 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004595 break;
4596 case VAR_NUMBER:
4597 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004598 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004599 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004600 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004601 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004602 generate_PUSHNR(cctx, 0);
4603 break;
4604 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004605 }
4606
4607 if (oplen > 0 && *op != '=')
4608 {
4609 type_T *expected = &t_number;
4610 garray_T *stack = &cctx->ctx_type_stack;
4611 type_T *stacktype;
4612
4613 // TODO: if type is known use float or any operation
4614
4615 if (*op == '.')
4616 expected = &t_string;
4617 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4618 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4619 goto theend;
4620
4621 if (*op == '.')
4622 generate_instr_drop(cctx, ISN_CONCAT, 1);
4623 else
4624 {
4625 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4626
4627 if (isn == NULL)
4628 goto theend;
4629 switch (*op)
4630 {
4631 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4632 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4633 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4634 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4635 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4636 }
4637 }
4638 }
4639
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004640 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004641 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004642 case dest_option:
4643 generate_STOREOPT(cctx, name + 1, opt_flags);
4644 break;
4645 case dest_global:
4646 // include g: with the name, easier to execute that way
4647 generate_STORE(cctx, ISN_STOREG, 0, name);
4648 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004649 case dest_buffer:
4650 // include b: with the name, easier to execute that way
4651 generate_STORE(cctx, ISN_STOREB, 0, name);
4652 break;
4653 case dest_window:
4654 // include w: with the name, easier to execute that way
4655 generate_STORE(cctx, ISN_STOREW, 0, name);
4656 break;
4657 case dest_tab:
4658 // include t: with the name, easier to execute that way
4659 generate_STORE(cctx, ISN_STORET, 0, name);
4660 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004661 case dest_env:
4662 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4663 break;
4664 case dest_reg:
4665 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4666 break;
4667 case dest_vimvar:
4668 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4669 break;
4670 case dest_script:
4671 {
4672 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4673 imported_T *import = NULL;
4674 int sid = current_sctx.sc_sid;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004675 int idx;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004676
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004677 if (name[1] != ':')
4678 {
4679 import = find_imported(name, 0, cctx);
4680 if (import != NULL)
4681 sid = import->imp_sid;
4682 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004683
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004684 idx = get_script_item_idx(sid, rawname, TRUE);
4685 // TODO: specific type
4686 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004687 {
4688 char_u *name_s = name;
4689
4690 // Include s: in the name for store_var()
4691 if (name[1] != ':')
4692 {
4693 int len = (int)STRLEN(name) + 3;
4694
4695 name_s = alloc(len);
4696 if (name_s == NULL)
4697 name_s = name;
4698 else
4699 vim_snprintf((char *)name_s, len, "s:%s", name);
4700 }
4701 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4702 if (name_s != name)
4703 vim_free(name_s);
4704 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004705 else
4706 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4707 sid, idx, &t_any);
4708 }
4709 break;
4710 case dest_local:
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004711 if (lvar != NULL)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004712 {
4713 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004714
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004715 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4716 // into ISN_STORENR
4717 if (instr->ga_len == instr_count + 1
4718 && isn->isn_type == ISN_PUSHNR)
4719 {
4720 varnumber_T val = isn->isn_arg.number;
4721 garray_T *stack = &cctx->ctx_type_stack;
4722
4723 isn->isn_type = ISN_STORENR;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004724 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004725 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004726 if (stack->ga_len > 0)
4727 --stack->ga_len;
4728 }
4729 else
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004730 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004731 }
4732 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004733 }
4734 ret = p;
4735
4736theend:
4737 vim_free(name);
4738 return ret;
4739}
4740
4741/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004742 * Check if "name" can be "unlet".
4743 */
4744 int
4745check_vim9_unlet(char_u *name)
4746{
4747 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4748 {
4749 semsg(_("E1081: Cannot unlet %s"), name);
4750 return FAIL;
4751 }
4752 return OK;
4753}
4754
4755/*
4756 * Callback passed to ex_unletlock().
4757 */
4758 static int
4759compile_unlet(
4760 lval_T *lvp,
4761 char_u *name_end,
4762 exarg_T *eap,
4763 int deep UNUSED,
4764 void *coookie)
4765{
4766 cctx_T *cctx = coookie;
4767
4768 if (lvp->ll_tv == NULL)
4769 {
4770 char_u *p = lvp->ll_name;
4771 int cc = *name_end;
4772 int ret = OK;
4773
4774 // Normal name. Only supports g:, w:, t: and b: namespaces.
4775 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004776 if (*p == '$')
4777 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4778 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004779 ret = FAIL;
4780 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004781 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004782
4783 *name_end = cc;
4784 return ret;
4785 }
4786
4787 // TODO: unlet {list}[idx]
4788 // TODO: unlet {dict}[key]
4789 emsg("Sorry, :unlet not fully implemented yet");
4790 return FAIL;
4791}
4792
4793/*
4794 * compile "unlet var", "lock var" and "unlock var"
4795 * "arg" points to "var".
4796 */
4797 static char_u *
4798compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4799{
4800 char_u *p = arg;
4801
4802 if (eap->cmdidx != CMD_unlet)
4803 {
4804 emsg("Sorry, :lock and unlock not implemented yet");
4805 return NULL;
4806 }
4807
4808 if (*p == '!')
4809 {
4810 p = skipwhite(p + 1);
4811 eap->forceit = TRUE;
4812 }
4813
4814 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4815 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4816}
4817
4818/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004819 * Compile an :import command.
4820 */
4821 static char_u *
4822compile_import(char_u *arg, cctx_T *cctx)
4823{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004824 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004825}
4826
4827/*
4828 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4829 */
4830 static int
4831compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4832{
4833 garray_T *instr = &cctx->ctx_instr;
4834 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4835
4836 if (endlabel == NULL)
4837 return FAIL;
4838 endlabel->el_next = *el;
4839 *el = endlabel;
4840 endlabel->el_end_label = instr->ga_len;
4841
4842 generate_JUMP(cctx, when, 0);
4843 return OK;
4844}
4845
4846 static void
4847compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4848{
4849 garray_T *instr = &cctx->ctx_instr;
4850
4851 while (*el != NULL)
4852 {
4853 endlabel_T *cur = (*el);
4854 isn_T *isn;
4855
4856 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4857 isn->isn_arg.jump.jump_where = instr->ga_len;
4858 *el = cur->el_next;
4859 vim_free(cur);
4860 }
4861}
4862
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004863 static void
4864compile_free_jump_to_end(endlabel_T **el)
4865{
4866 while (*el != NULL)
4867 {
4868 endlabel_T *cur = (*el);
4869
4870 *el = cur->el_next;
4871 vim_free(cur);
4872 }
4873}
4874
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004875/*
4876 * Create a new scope and set up the generic items.
4877 */
4878 static scope_T *
4879new_scope(cctx_T *cctx, scopetype_T type)
4880{
4881 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4882
4883 if (scope == NULL)
4884 return NULL;
4885 scope->se_outer = cctx->ctx_scope;
4886 cctx->ctx_scope = scope;
4887 scope->se_type = type;
4888 scope->se_local_count = cctx->ctx_locals.ga_len;
4889 return scope;
4890}
4891
4892/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004893 * Free the current scope and go back to the outer scope.
4894 */
4895 static void
4896drop_scope(cctx_T *cctx)
4897{
4898 scope_T *scope = cctx->ctx_scope;
4899
4900 if (scope == NULL)
4901 {
4902 iemsg("calling drop_scope() without a scope");
4903 return;
4904 }
4905 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004906 switch (scope->se_type)
4907 {
4908 case IF_SCOPE:
4909 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4910 case FOR_SCOPE:
4911 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4912 case WHILE_SCOPE:
4913 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4914 case TRY_SCOPE:
4915 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4916 case NO_SCOPE:
4917 case BLOCK_SCOPE:
4918 break;
4919 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004920 vim_free(scope);
4921}
4922
4923/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004924 * Evaluate an expression that is a constant:
4925 * has(arg)
4926 *
4927 * Also handle:
4928 * ! in front logical NOT
4929 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004930 * Return FAIL if the expression is not a constant.
4931 */
4932 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004933evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004934{
4935 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004936 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004937 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004938
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004939 /*
4940 * Skip '!' characters. They are handled later.
4941 */
4942 start_leader = *arg;
4943 while (**arg == '!')
4944 *arg = skipwhite(*arg + 1);
4945 end_leader = *arg;
4946
4947 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004948 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004949 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004950 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4951 {
4952 tv->v_type = VAR_SPECIAL;
4953 tv->vval.v_number = VVAL_TRUE;
4954 *arg += 4;
4955 return OK;
4956 }
4957 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4958 {
4959 tv->v_type = VAR_SPECIAL;
4960 tv->vval.v_number = VVAL_FALSE;
4961 *arg += 5;
4962 return OK;
4963 }
4964
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004965 if (STRNCMP("has(", *arg, 4) == 0)
4966 {
4967 has_call = TRUE;
4968 *arg = skipwhite(*arg + 4);
4969 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004970
4971 if (**arg == '"')
4972 {
4973 if (get_string_tv(arg, tv, TRUE) == FAIL)
4974 return FAIL;
4975 }
4976 else if (**arg == '\'')
4977 {
4978 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4979 return FAIL;
4980 }
4981 else
4982 return FAIL;
4983
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004984 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004985 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004986 *arg = skipwhite(*arg);
4987 if (**arg != ')')
4988 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004989 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004990
4991 argvars[0] = *tv;
4992 argvars[1].v_type = VAR_UNKNOWN;
4993 tv->v_type = VAR_NUMBER;
4994 tv->vval.v_number = 0;
4995 f_has(argvars, tv);
4996 clear_tv(&argvars[0]);
4997
4998 while (start_leader < end_leader)
4999 {
5000 if (*start_leader == '!')
5001 tv->vval.v_number = !tv->vval.v_number;
5002 ++start_leader;
5003 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01005004 }
5005
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005006 return OK;
5007}
5008
Bram Moolenaar080457c2020-03-03 21:53:32 +01005009 static int
5010evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
5011{
5012 exptype_T type = EXPR_UNKNOWN;
5013 char_u *p;
5014 int len = 2;
5015 int type_is = FALSE;
5016
5017 // get the first variable
5018 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
5019 return FAIL;
5020
5021 p = skipwhite(*arg);
5022 type = get_compare_type(p, &len, &type_is);
5023
5024 /*
5025 * If there is a comparative operator, use it.
5026 */
5027 if (type != EXPR_UNKNOWN)
5028 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02005029 typval_T tv2;
5030 char_u *s1, *s2;
5031 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
5032 int n;
5033
5034 // TODO: Only string == string is supported now
5035 if (tv->v_type != VAR_STRING)
5036 return FAIL;
5037 if (type != EXPR_EQUAL)
5038 return FAIL;
5039
5040 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02005041 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02005042 *arg = skipwhite(p + len);
5043 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
5044 || tv2.v_type != VAR_STRING)
5045 {
5046 clear_tv(&tv2);
5047 return FAIL;
5048 }
5049 s1 = tv_get_string_buf(tv, buf1);
5050 s2 = tv_get_string_buf(&tv2, buf2);
5051 n = STRCMP(s1, s2);
5052 clear_tv(tv);
5053 clear_tv(&tv2);
5054 tv->v_type = VAR_BOOL;
5055 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01005056 }
5057
5058 return OK;
5059}
5060
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005061static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
5062
5063/*
5064 * Compile constant || or &&.
5065 */
5066 static int
5067evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
5068{
5069 char_u *p = skipwhite(*arg);
5070 int opchar = *op;
5071
5072 if (p[0] == opchar && p[1] == opchar)
5073 {
5074 int val = tv2bool(tv);
5075
5076 /*
5077 * Repeat until there is no following "||" or "&&"
5078 */
5079 while (p[0] == opchar && p[1] == opchar)
5080 {
5081 typval_T tv2;
5082
5083 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
5084 return FAIL;
5085
5086 // eval the next expression
5087 *arg = skipwhite(p + 2);
5088 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01005089 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005090 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01005091 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005092 {
5093 clear_tv(&tv2);
5094 return FAIL;
5095 }
5096 if ((opchar == '&') == val)
5097 {
5098 // false || tv2 or true && tv2: use tv2
5099 clear_tv(tv);
5100 *tv = tv2;
5101 val = tv2bool(tv);
5102 }
5103 else
5104 clear_tv(&tv2);
5105 p = skipwhite(*arg);
5106 }
5107 }
5108
5109 return OK;
5110}
5111
5112/*
5113 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
5114 * Return FAIL if the expression is not a constant.
5115 */
5116 static int
5117evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
5118{
5119 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01005120 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005121 return FAIL;
5122
5123 // || and && work almost the same
5124 return evaluate_const_and_or(arg, cctx, "&&", tv);
5125}
5126
5127/*
5128 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
5129 * Return FAIL if the expression is not a constant.
5130 */
5131 static int
5132evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
5133{
5134 // evaluate the first expression
5135 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
5136 return FAIL;
5137
5138 // || and && work almost the same
5139 return evaluate_const_and_or(arg, cctx, "||", tv);
5140}
5141
5142/*
5143 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
5144 * E.g. for "has('feature')".
5145 * This does not produce error messages. "tv" should be cleared afterwards.
5146 * Return FAIL if the expression is not a constant.
5147 */
5148 static int
5149evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
5150{
5151 char_u *p;
5152
5153 // evaluate the first expression
5154 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
5155 return FAIL;
5156
5157 p = skipwhite(*arg);
5158 if (*p == '?')
5159 {
5160 int val = tv2bool(tv);
5161 typval_T tv2;
5162
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005163 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005164 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5165 return FAIL;
5166
5167 // evaluate the second expression; any type is accepted
5168 clear_tv(tv);
5169 *arg = skipwhite(p + 1);
5170 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
5171 return FAIL;
5172
5173 // Check for the ":".
5174 p = skipwhite(*arg);
5175 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5176 return FAIL;
5177
5178 // evaluate the third expression
5179 *arg = skipwhite(p + 1);
5180 tv2.v_type = VAR_UNKNOWN;
5181 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5182 {
5183 clear_tv(&tv2);
5184 return FAIL;
5185 }
5186 if (val)
5187 {
5188 // use the expr after "?"
5189 clear_tv(&tv2);
5190 }
5191 else
5192 {
5193 // use the expr after ":"
5194 clear_tv(tv);
5195 *tv = tv2;
5196 }
5197 }
5198 return OK;
5199}
5200
5201/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005202 * compile "if expr"
5203 *
5204 * "if expr" Produces instructions:
5205 * EVAL expr Push result of "expr"
5206 * JUMP_IF_FALSE end
5207 * ... body ...
5208 * end:
5209 *
5210 * "if expr | else" Produces instructions:
5211 * EVAL expr Push result of "expr"
5212 * JUMP_IF_FALSE else
5213 * ... body ...
5214 * JUMP_ALWAYS end
5215 * else:
5216 * ... body ...
5217 * end:
5218 *
5219 * "if expr1 | elseif expr2 | else" Produces instructions:
5220 * EVAL expr Push result of "expr"
5221 * JUMP_IF_FALSE elseif
5222 * ... body ...
5223 * JUMP_ALWAYS end
5224 * elseif:
5225 * EVAL expr Push result of "expr"
5226 * JUMP_IF_FALSE else
5227 * ... body ...
5228 * JUMP_ALWAYS end
5229 * else:
5230 * ... body ...
5231 * end:
5232 */
5233 static char_u *
5234compile_if(char_u *arg, cctx_T *cctx)
5235{
5236 char_u *p = arg;
5237 garray_T *instr = &cctx->ctx_instr;
5238 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005239 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005240
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005241 // compile "expr"; if we know it evaluates to FALSE skip the block
5242 tv.v_type = VAR_UNKNOWN;
5243 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5244 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5245 else
5246 cctx->ctx_skip = MAYBE;
5247 clear_tv(&tv);
5248 if (cctx->ctx_skip == MAYBE)
5249 {
5250 p = arg;
5251 if (compile_expr1(&p, cctx) == FAIL)
5252 return NULL;
5253 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005254
5255 scope = new_scope(cctx, IF_SCOPE);
5256 if (scope == NULL)
5257 return NULL;
5258
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005259 if (cctx->ctx_skip == MAYBE)
5260 {
5261 // "where" is set when ":elseif", "else" or ":endif" is found
5262 scope->se_u.se_if.is_if_label = instr->ga_len;
5263 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5264 }
5265 else
5266 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005267
5268 return p;
5269}
5270
5271 static char_u *
5272compile_elseif(char_u *arg, cctx_T *cctx)
5273{
5274 char_u *p = arg;
5275 garray_T *instr = &cctx->ctx_instr;
5276 isn_T *isn;
5277 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005278 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005279
5280 if (scope == NULL || scope->se_type != IF_SCOPE)
5281 {
5282 emsg(_(e_elseif_without_if));
5283 return NULL;
5284 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005285 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005286
Bram Moolenaar158906c2020-02-06 20:39:45 +01005287 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005288 {
5289 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005290 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005291 return NULL;
5292 // previous "if" or "elseif" jumps here
5293 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5294 isn->isn_arg.jump.jump_where = instr->ga_len;
5295 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005296
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005297 // compile "expr"; if we know it evaluates to FALSE skip the block
5298 tv.v_type = VAR_UNKNOWN;
5299 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5300 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5301 else
5302 cctx->ctx_skip = MAYBE;
5303 clear_tv(&tv);
5304 if (cctx->ctx_skip == MAYBE)
5305 {
5306 p = arg;
5307 if (compile_expr1(&p, cctx) == FAIL)
5308 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005309
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005310 // "where" is set when ":elseif", "else" or ":endif" is found
5311 scope->se_u.se_if.is_if_label = instr->ga_len;
5312 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5313 }
5314 else
5315 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005316
5317 return p;
5318}
5319
5320 static char_u *
5321compile_else(char_u *arg, cctx_T *cctx)
5322{
5323 char_u *p = arg;
5324 garray_T *instr = &cctx->ctx_instr;
5325 isn_T *isn;
5326 scope_T *scope = cctx->ctx_scope;
5327
5328 if (scope == NULL || scope->se_type != IF_SCOPE)
5329 {
5330 emsg(_(e_else_without_if));
5331 return NULL;
5332 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005333 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005334
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005335 // jump from previous block to the end, unless the else block is empty
5336 if (cctx->ctx_skip == MAYBE)
5337 {
5338 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005339 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005340 return NULL;
5341 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005342
Bram Moolenaar158906c2020-02-06 20:39:45 +01005343 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005344 {
5345 if (scope->se_u.se_if.is_if_label >= 0)
5346 {
5347 // previous "if" or "elseif" jumps here
5348 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5349 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005350 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005351 }
5352 }
5353
5354 if (cctx->ctx_skip != MAYBE)
5355 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005356
5357 return p;
5358}
5359
5360 static char_u *
5361compile_endif(char_u *arg, cctx_T *cctx)
5362{
5363 scope_T *scope = cctx->ctx_scope;
5364 ifscope_T *ifscope;
5365 garray_T *instr = &cctx->ctx_instr;
5366 isn_T *isn;
5367
5368 if (scope == NULL || scope->se_type != IF_SCOPE)
5369 {
5370 emsg(_(e_endif_without_if));
5371 return NULL;
5372 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005373 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005374 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005375
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005376 if (scope->se_u.se_if.is_if_label >= 0)
5377 {
5378 // previous "if" or "elseif" jumps here
5379 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5380 isn->isn_arg.jump.jump_where = instr->ga_len;
5381 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005382 // Fill in the "end" label in jumps at the end of the blocks.
5383 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005384 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005385
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005386 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005387 return arg;
5388}
5389
5390/*
5391 * compile "for var in expr"
5392 *
5393 * Produces instructions:
5394 * PUSHNR -1
5395 * STORE loop-idx Set index to -1
5396 * EVAL expr Push result of "expr"
5397 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5398 * - if beyond end, jump to "end"
5399 * - otherwise get item from list and push it
5400 * STORE var Store item in "var"
5401 * ... body ...
5402 * JUMP top Jump back to repeat
5403 * end: DROP Drop the result of "expr"
5404 *
5405 */
5406 static char_u *
5407compile_for(char_u *arg, cctx_T *cctx)
5408{
5409 char_u *p;
5410 size_t varlen;
5411 garray_T *instr = &cctx->ctx_instr;
5412 garray_T *stack = &cctx->ctx_type_stack;
5413 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005414 lvar_T *loop_lvar; // loop iteration variable
5415 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005416 type_T *vartype;
5417
5418 // TODO: list of variables: "for [key, value] in dict"
5419 // parse "var"
5420 for (p = arg; eval_isnamec1(*p); ++p)
5421 ;
5422 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005423 var_lvar = lookup_local(arg, varlen, cctx);
5424 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005425 {
5426 semsg(_("E1023: variable already defined: %s"), arg);
5427 return NULL;
5428 }
5429
5430 // consume "in"
5431 p = skipwhite(p);
5432 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5433 {
5434 emsg(_(e_missing_in));
5435 return NULL;
5436 }
5437 p = skipwhite(p + 2);
5438
5439
5440 scope = new_scope(cctx, FOR_SCOPE);
5441 if (scope == NULL)
5442 return NULL;
5443
5444 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005445 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5446 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005447 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005448 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005449 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005450 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005451 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005452
5453 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005454 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5455 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005456 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005457 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005458 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005459 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005460 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005461
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005462 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005463
5464 // compile "expr", it remains on the stack until "endfor"
5465 arg = p;
5466 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005467 {
5468 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005469 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005470 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005471
5472 // now we know the type of "var"
5473 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5474 if (vartype->tt_type != VAR_LIST)
5475 {
5476 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005477 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005478 return NULL;
5479 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005480 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005481 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005482
5483 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005484 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005485
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005486 generate_FOR(cctx, loop_lvar->lv_idx);
5487 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005488
5489 return arg;
5490}
5491
5492/*
5493 * compile "endfor"
5494 */
5495 static char_u *
5496compile_endfor(char_u *arg, cctx_T *cctx)
5497{
5498 garray_T *instr = &cctx->ctx_instr;
5499 scope_T *scope = cctx->ctx_scope;
5500 forscope_T *forscope;
5501 isn_T *isn;
5502
5503 if (scope == NULL || scope->se_type != FOR_SCOPE)
5504 {
5505 emsg(_(e_for));
5506 return NULL;
5507 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005508 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005509 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005510 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005511
5512 // At end of ":for" scope jump back to the FOR instruction.
5513 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5514
5515 // Fill in the "end" label in the FOR statement so it can jump here
5516 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5517 isn->isn_arg.forloop.for_end = instr->ga_len;
5518
5519 // Fill in the "end" label any BREAK statements
5520 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5521
5522 // Below the ":for" scope drop the "expr" list from the stack.
5523 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5524 return NULL;
5525
5526 vim_free(scope);
5527
5528 return arg;
5529}
5530
5531/*
5532 * compile "while expr"
5533 *
5534 * Produces instructions:
5535 * top: EVAL expr Push result of "expr"
5536 * JUMP_IF_FALSE end jump if false
5537 * ... body ...
5538 * JUMP top Jump back to repeat
5539 * end:
5540 *
5541 */
5542 static char_u *
5543compile_while(char_u *arg, cctx_T *cctx)
5544{
5545 char_u *p = arg;
5546 garray_T *instr = &cctx->ctx_instr;
5547 scope_T *scope;
5548
5549 scope = new_scope(cctx, WHILE_SCOPE);
5550 if (scope == NULL)
5551 return NULL;
5552
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005553 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005554
5555 // compile "expr"
5556 if (compile_expr1(&p, cctx) == FAIL)
5557 return NULL;
5558
5559 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005560 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005561 JUMP_IF_FALSE, cctx) == FAIL)
5562 return FAIL;
5563
5564 return p;
5565}
5566
5567/*
5568 * compile "endwhile"
5569 */
5570 static char_u *
5571compile_endwhile(char_u *arg, cctx_T *cctx)
5572{
5573 scope_T *scope = cctx->ctx_scope;
5574
5575 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5576 {
5577 emsg(_(e_while));
5578 return NULL;
5579 }
5580 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005581 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005582
5583 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005584 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005585
5586 // Fill in the "end" label in the WHILE statement so it can jump here.
5587 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005588 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005589
5590 vim_free(scope);
5591
5592 return arg;
5593}
5594
5595/*
5596 * compile "continue"
5597 */
5598 static char_u *
5599compile_continue(char_u *arg, cctx_T *cctx)
5600{
5601 scope_T *scope = cctx->ctx_scope;
5602
5603 for (;;)
5604 {
5605 if (scope == NULL)
5606 {
5607 emsg(_(e_continue));
5608 return NULL;
5609 }
5610 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5611 break;
5612 scope = scope->se_outer;
5613 }
5614
5615 // Jump back to the FOR or WHILE instruction.
5616 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005617 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5618 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005619 return arg;
5620}
5621
5622/*
5623 * compile "break"
5624 */
5625 static char_u *
5626compile_break(char_u *arg, cctx_T *cctx)
5627{
5628 scope_T *scope = cctx->ctx_scope;
5629 endlabel_T **el;
5630
5631 for (;;)
5632 {
5633 if (scope == NULL)
5634 {
5635 emsg(_(e_break));
5636 return NULL;
5637 }
5638 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5639 break;
5640 scope = scope->se_outer;
5641 }
5642
5643 // Jump to the end of the FOR or WHILE loop.
5644 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005645 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005646 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005647 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005648 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5649 return FAIL;
5650
5651 return arg;
5652}
5653
5654/*
5655 * compile "{" start of block
5656 */
5657 static char_u *
5658compile_block(char_u *arg, cctx_T *cctx)
5659{
5660 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5661 return NULL;
5662 return skipwhite(arg + 1);
5663}
5664
5665/*
5666 * compile end of block: drop one scope
5667 */
5668 static void
5669compile_endblock(cctx_T *cctx)
5670{
5671 scope_T *scope = cctx->ctx_scope;
5672
5673 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005674 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005675 vim_free(scope);
5676}
5677
5678/*
5679 * compile "try"
5680 * Creates a new scope for the try-endtry, pointing to the first catch and
5681 * finally.
5682 * Creates another scope for the "try" block itself.
5683 * TRY instruction sets up exception handling at runtime.
5684 *
5685 * "try"
5686 * TRY -> catch1, -> finally push trystack entry
5687 * ... try block
5688 * "throw {exception}"
5689 * EVAL {exception}
5690 * THROW create exception
5691 * ... try block
5692 * " catch {expr}"
5693 * JUMP -> finally
5694 * catch1: PUSH exeception
5695 * EVAL {expr}
5696 * MATCH
5697 * JUMP nomatch -> catch2
5698 * CATCH remove exception
5699 * ... catch block
5700 * " catch"
5701 * JUMP -> finally
5702 * catch2: CATCH remove exception
5703 * ... catch block
5704 * " finally"
5705 * finally:
5706 * ... finally block
5707 * " endtry"
5708 * ENDTRY pop trystack entry, may rethrow
5709 */
5710 static char_u *
5711compile_try(char_u *arg, cctx_T *cctx)
5712{
5713 garray_T *instr = &cctx->ctx_instr;
5714 scope_T *try_scope;
5715 scope_T *scope;
5716
5717 // scope that holds the jumps that go to catch/finally/endtry
5718 try_scope = new_scope(cctx, TRY_SCOPE);
5719 if (try_scope == NULL)
5720 return NULL;
5721
5722 // "catch" is set when the first ":catch" is found.
5723 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005724 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005725 if (generate_instr(cctx, ISN_TRY) == NULL)
5726 return NULL;
5727
5728 // scope for the try block itself
5729 scope = new_scope(cctx, BLOCK_SCOPE);
5730 if (scope == NULL)
5731 return NULL;
5732
5733 return arg;
5734}
5735
5736/*
5737 * compile "catch {expr}"
5738 */
5739 static char_u *
5740compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5741{
5742 scope_T *scope = cctx->ctx_scope;
5743 garray_T *instr = &cctx->ctx_instr;
5744 char_u *p;
5745 isn_T *isn;
5746
5747 // end block scope from :try or :catch
5748 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5749 compile_endblock(cctx);
5750 scope = cctx->ctx_scope;
5751
5752 // Error if not in a :try scope
5753 if (scope == NULL || scope->se_type != TRY_SCOPE)
5754 {
5755 emsg(_(e_catch));
5756 return NULL;
5757 }
5758
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005759 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005760 {
5761 emsg(_("E1033: catch unreachable after catch-all"));
5762 return NULL;
5763 }
5764
5765 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005766 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005767 JUMP_ALWAYS, cctx) == FAIL)
5768 return NULL;
5769
5770 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005771 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005772 if (isn->isn_arg.try.try_catch == 0)
5773 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005774 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005775 {
5776 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005777 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005778 isn->isn_arg.jump.jump_where = instr->ga_len;
5779 }
5780
5781 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005782 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005783 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005784 scope->se_u.se_try.ts_caught_all = TRUE;
5785 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005786 }
5787 else
5788 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005789 char_u *end;
5790 char_u *pat;
5791 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005792 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005793 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005794
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005795 // Push v:exception, push {expr} and MATCH
5796 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5797
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005798 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005799 if (*end != *p)
5800 {
5801 semsg(_("E1067: Separator mismatch: %s"), p);
5802 vim_free(tofree);
5803 return FAIL;
5804 }
5805 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005806 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005807 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005808 len = (int)(end - tofree);
5809 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005810 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005811 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005812 if (pat == NULL)
5813 return FAIL;
5814 if (generate_PUSHS(cctx, pat) == FAIL)
5815 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005816
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005817 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5818 return NULL;
5819
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005820 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005821 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5822 return NULL;
5823 }
5824
5825 if (generate_instr(cctx, ISN_CATCH) == NULL)
5826 return NULL;
5827
5828 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5829 return NULL;
5830 return p;
5831}
5832
5833 static char_u *
5834compile_finally(char_u *arg, cctx_T *cctx)
5835{
5836 scope_T *scope = cctx->ctx_scope;
5837 garray_T *instr = &cctx->ctx_instr;
5838 isn_T *isn;
5839
5840 // end block scope from :try or :catch
5841 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5842 compile_endblock(cctx);
5843 scope = cctx->ctx_scope;
5844
5845 // Error if not in a :try scope
5846 if (scope == NULL || scope->se_type != TRY_SCOPE)
5847 {
5848 emsg(_(e_finally));
5849 return NULL;
5850 }
5851
5852 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005853 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005854 if (isn->isn_arg.try.try_finally != 0)
5855 {
5856 emsg(_(e_finally_dup));
5857 return NULL;
5858 }
5859
5860 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005861 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005862
Bram Moolenaar585fea72020-04-02 22:33:21 +02005863 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005864 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005865 {
5866 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005867 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005868 isn->isn_arg.jump.jump_where = instr->ga_len;
5869 }
5870
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005871 // TODO: set index in ts_finally_label jumps
5872
5873 return arg;
5874}
5875
5876 static char_u *
5877compile_endtry(char_u *arg, cctx_T *cctx)
5878{
5879 scope_T *scope = cctx->ctx_scope;
5880 garray_T *instr = &cctx->ctx_instr;
5881 isn_T *isn;
5882
5883 // end block scope from :catch or :finally
5884 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5885 compile_endblock(cctx);
5886 scope = cctx->ctx_scope;
5887
5888 // Error if not in a :try scope
5889 if (scope == NULL || scope->se_type != TRY_SCOPE)
5890 {
5891 if (scope == NULL)
5892 emsg(_(e_no_endtry));
5893 else if (scope->se_type == WHILE_SCOPE)
5894 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005895 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005896 emsg(_(e_endfor));
5897 else
5898 emsg(_(e_endif));
5899 return NULL;
5900 }
5901
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005902 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005903 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5904 {
5905 emsg(_("E1032: missing :catch or :finally"));
5906 return NULL;
5907 }
5908
5909 // Fill in the "end" label in jumps at the end of the blocks, if not done
5910 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005911 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005912
5913 // End :catch or :finally scope: set value in ISN_TRY instruction
5914 if (isn->isn_arg.try.try_finally == 0)
5915 isn->isn_arg.try.try_finally = instr->ga_len;
5916 compile_endblock(cctx);
5917
5918 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5919 return NULL;
5920 return arg;
5921}
5922
5923/*
5924 * compile "throw {expr}"
5925 */
5926 static char_u *
5927compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5928{
5929 char_u *p = skipwhite(arg);
5930
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005931 if (compile_expr1(&p, cctx) == FAIL)
5932 return NULL;
5933 if (may_generate_2STRING(-1, cctx) == FAIL)
5934 return NULL;
5935 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5936 return NULL;
5937
5938 return p;
5939}
5940
5941/*
5942 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005943 * compile "echomsg expr"
5944 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01005945 * compile "execute expr"
5946 */
5947 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005948compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01005949{
5950 char_u *p = arg;
5951 int count = 0;
5952
5953 for (;;)
5954 {
5955 if (compile_expr1(&p, cctx) == FAIL)
5956 return NULL;
5957 ++count;
5958 p = skipwhite(p);
5959 if (ends_excmd(*p))
5960 break;
5961 }
5962
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005963 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
5964 generate_ECHO(cctx, cmdidx == CMD_echo, count);
5965 else if (cmdidx == CMD_execute)
5966 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
5967 else if (cmdidx == CMD_echomsg)
5968 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
5969 else
5970 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005971 return p;
5972}
5973
5974/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005975 * A command that is not compiled, execute with legacy code.
5976 */
5977 static char_u *
5978compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
5979{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005980 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005981 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005982
5983 if (cctx->ctx_skip == TRUE)
5984 goto theend;
5985
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005986 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
5987 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005988 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
5989 {
5990 // expand filename in "syntax include [@group] filename"
5991 has_expr = TRUE;
5992 eap->arg = skipwhite(eap->arg + 7);
5993 if (*eap->arg == '@')
5994 eap->arg = skiptowhite(eap->arg);
5995 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005996
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005997 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005998 {
5999 int count = 0;
6000 char_u *start = skipwhite(line);
6001
6002 // :cmd xxx`=expr1`yyy`=expr2`zzz
6003 // PUSHS ":cmd xxx"
6004 // eval expr1
6005 // PUSHS "yyy"
6006 // eval expr2
6007 // PUSHS "zzz"
6008 // EXECCONCAT 5
6009 for (;;)
6010 {
6011 if (p > start)
6012 {
6013 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
6014 ++count;
6015 }
6016 p += 2;
6017 if (compile_expr1(&p, cctx) == FAIL)
6018 return NULL;
6019 may_generate_2STRING(-1, cctx);
6020 ++count;
6021 p = skipwhite(p);
6022 if (*p != '`')
6023 {
6024 emsg(_("E1083: missing backtick"));
6025 return NULL;
6026 }
6027 start = p + 1;
6028
6029 p = (char_u *)strstr((char *)start, "`=");
6030 if (p == NULL)
6031 {
6032 if (*skipwhite(start) != NUL)
6033 {
6034 generate_PUSHS(cctx, vim_strsave(start));
6035 ++count;
6036 }
6037 break;
6038 }
6039 }
6040 generate_EXECCONCAT(cctx, count);
6041 }
6042 else
6043 generate_EXEC(cctx, line);
6044
6045theend:
6046 return (char_u *)"";
6047}
6048
6049/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006050 * After ex_function() has collected all the function lines: parse and compile
6051 * the lines into instructions.
6052 * Adds the function to "def_functions".
6053 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
6054 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006055 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006056 * This can be used recursively through compile_lambda(), which may reallocate
6057 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006058 */
6059 void
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006060compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006061{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006062 char_u *line = NULL;
6063 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006064 char *errormsg = NULL; // error message
6065 int had_return = FALSE;
6066 cctx_T cctx;
6067 garray_T *instr;
6068 int called_emsg_before = called_emsg;
6069 int ret = FAIL;
6070 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006071 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006072
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006073 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006074 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01006075
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006076 if (ufunc->uf_dfunc_idx >= 0)
6077 {
6078 // Redefining a function that was compiled before.
6079 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
6080
6081 // Free old instructions.
6082 delete_def_function_contents(dfunc);
6083 }
6084 else
6085 {
6086 // Add the function to "def_functions".
6087 if (ga_grow(&def_functions, 1) == FAIL)
6088 return;
6089 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006090 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006091 dfunc->df_idx = def_functions.ga_len;
6092 ufunc->uf_dfunc_idx = dfunc->df_idx;
6093 dfunc->df_ufunc = ufunc;
6094 ++def_functions.ga_len;
6095 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006096 }
6097
Bram Moolenaara80faa82020-04-12 19:37:17 +02006098 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006099 cctx.ctx_ufunc = ufunc;
6100 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006101 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006102 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
6103 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
6104 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
6105 cctx.ctx_type_list = &ufunc->uf_type_list;
6106 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
6107 instr = &cctx.ctx_instr;
6108
6109 // Most modern script version.
6110 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
6111
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006112 if (ufunc->uf_def_args.ga_len > 0)
6113 {
6114 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006115 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006116 int i;
6117 char_u *arg;
6118 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
6119
6120 // Produce instructions for the default values of optional arguments.
6121 // Store the instruction index in uf_def_arg_idx[] so that we know
6122 // where to start when the function is called, depending on the number
6123 // of arguments.
6124 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
6125 if (ufunc->uf_def_arg_idx == NULL)
6126 goto erret;
6127 for (i = 0; i < count; ++i)
6128 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006129 garray_T *stack = &cctx.ctx_type_stack;
6130 type_T *val_type;
6131 int arg_idx = first_def_arg + i;
6132
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006133 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6134 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006135 if (compile_expr1(&arg, &cctx) == FAIL)
6136 goto erret;
6137
6138 // If no type specified use the type of the default value.
6139 // Otherwise check that the default value type matches the
6140 // specified type.
6141 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6142 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6143 ufunc->uf_arg_types[arg_idx] = val_type;
6144 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6145 == FAIL)
6146 {
6147 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6148 arg_idx + 1);
6149 goto erret;
6150 }
6151
6152 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006153 goto erret;
6154 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006155 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6156 }
6157
6158 /*
6159 * Loop over all the lines of the function and generate instructions.
6160 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006161 for (;;)
6162 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006163 exarg_T ea;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006164 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006165
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006166 // Bail out on the first error to avoid a flood of errors and report
6167 // the right line number when inside try/catch.
6168 if (emsg_before != called_emsg)
6169 goto erret;
6170
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006171 if (line != NULL && *line == '|')
6172 // the line continues after a '|'
6173 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006174 else if (line != NULL && *line != NUL
6175 && !(*line == '#' && (line == cctx.ctx_line_start
6176 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006177 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006178 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006179 goto erret;
6180 }
6181 else
6182 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006183 line = next_line_from_context(&cctx);
6184 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006185 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006186 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006187 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006188 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006189
6190 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006191 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006192 ea.cmdlinep = &line;
6193 ea.cmd = skipwhite(line);
6194
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006195 // Some things can be recognized by the first character.
6196 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006197 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006198 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006199 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006200 if (ea.cmd[1] != '{')
6201 {
6202 line = (char_u *)"";
6203 continue;
6204 }
6205 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006206
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006207 case '}':
6208 {
6209 // "}" ends a block scope
6210 scopetype_T stype = cctx.ctx_scope == NULL
6211 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006212
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006213 if (stype == BLOCK_SCOPE)
6214 {
6215 compile_endblock(&cctx);
6216 line = ea.cmd;
6217 }
6218 else
6219 {
6220 emsg(_("E1025: using } outside of a block scope"));
6221 goto erret;
6222 }
6223 if (line != NULL)
6224 line = skipwhite(ea.cmd + 1);
6225 continue;
6226 }
6227
6228 case '{':
6229 // "{" starts a block scope
6230 // "{'a': 1}->func() is something else
6231 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6232 {
6233 line = compile_block(ea.cmd, &cctx);
6234 continue;
6235 }
6236 break;
6237
6238 case ':':
6239 is_ex_command = TRUE;
6240 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006241 }
6242
6243 /*
6244 * COMMAND MODIFIERS
6245 */
6246 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6247 {
6248 if (errormsg != NULL)
6249 goto erret;
6250 // empty line or comment
6251 line = (char_u *)"";
6252 continue;
6253 }
6254
6255 // Skip ":call" to get to the function name.
6256 if (checkforcmd(&ea.cmd, "call", 3))
6257 ea.cmd = skipwhite(ea.cmd);
6258
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006259 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006260 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006261 // Assuming the command starts with a variable or function name,
6262 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6263 // val".
6264 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6265 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006266 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006267 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006268 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006269 int oplen;
6270 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006271
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006272 oplen = assignment_len(skipwhite(p), &heredoc);
6273 if (oplen > 0)
6274 {
6275 // Recognize an assignment if we recognize the variable
6276 // name:
6277 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006278 // "local = expr" where "local" is a local var.
6279 // "script = expr" where "script" is a script-local var.
6280 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006281 // "&opt = expr"
6282 // "$ENV = expr"
6283 // "@r = expr"
6284 if (*ea.cmd == '&'
6285 || *ea.cmd == '$'
6286 || *ea.cmd == '@'
6287 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006288 || lookup_local(ea.cmd, p - ea.cmd, &cctx) != NULL
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006289 || lookup_script(ea.cmd, p - ea.cmd) == OK
6290 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6291 {
6292 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6293 if (line == NULL)
6294 goto erret;
6295 continue;
6296 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006297 }
6298 }
6299 }
6300
6301 /*
6302 * COMMAND after range
6303 */
6304 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006305 p = find_ex_command(&ea, NULL, is_ex_command ? NULL
6306 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006307 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006308
6309 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6310 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006311 if (cctx.ctx_skip == TRUE)
6312 {
6313 line += STRLEN(line);
6314 continue;
6315 }
6316
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006317 // Expression or function call.
6318 if (ea.cmdidx == CMD_eval)
6319 {
6320 p = ea.cmd;
6321 if (compile_expr1(&p, &cctx) == FAIL)
6322 goto erret;
6323
6324 // drop the return value
6325 generate_instr_drop(&cctx, ISN_DROP, 1);
6326 line = p;
6327 continue;
6328 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006329 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006330 iemsg("Command from find_ex_command() not handled");
6331 goto erret;
6332 }
6333
6334 p = skipwhite(p);
6335
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006336 if (cctx.ctx_skip == TRUE
6337 && ea.cmdidx != CMD_elseif
6338 && ea.cmdidx != CMD_else
6339 && ea.cmdidx != CMD_endif)
6340 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006341 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006342 continue;
6343 }
6344
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006345 switch (ea.cmdidx)
6346 {
6347 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006348 ea.arg = p;
6349 line = compile_nested_function(&ea, &cctx);
6350 break;
6351
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006352 case CMD_function:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006353 emsg(_("E1086: Cannot use :function inside :def"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006354 goto erret;
6355
6356 case CMD_return:
6357 line = compile_return(p, set_return_type, &cctx);
6358 had_return = TRUE;
6359 break;
6360
6361 case CMD_let:
6362 case CMD_const:
6363 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6364 break;
6365
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006366 case CMD_unlet:
6367 case CMD_unlockvar:
6368 case CMD_lockvar:
6369 line = compile_unletlock(p, &ea, &cctx);
6370 break;
6371
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006372 case CMD_import:
6373 line = compile_import(p, &cctx);
6374 break;
6375
6376 case CMD_if:
6377 line = compile_if(p, &cctx);
6378 break;
6379 case CMD_elseif:
6380 line = compile_elseif(p, &cctx);
6381 break;
6382 case CMD_else:
6383 line = compile_else(p, &cctx);
6384 break;
6385 case CMD_endif:
6386 line = compile_endif(p, &cctx);
6387 break;
6388
6389 case CMD_while:
6390 line = compile_while(p, &cctx);
6391 break;
6392 case CMD_endwhile:
6393 line = compile_endwhile(p, &cctx);
6394 break;
6395
6396 case CMD_for:
6397 line = compile_for(p, &cctx);
6398 break;
6399 case CMD_endfor:
6400 line = compile_endfor(p, &cctx);
6401 break;
6402 case CMD_continue:
6403 line = compile_continue(p, &cctx);
6404 break;
6405 case CMD_break:
6406 line = compile_break(p, &cctx);
6407 break;
6408
6409 case CMD_try:
6410 line = compile_try(p, &cctx);
6411 break;
6412 case CMD_catch:
6413 line = compile_catch(p, &cctx);
6414 break;
6415 case CMD_finally:
6416 line = compile_finally(p, &cctx);
6417 break;
6418 case CMD_endtry:
6419 line = compile_endtry(p, &cctx);
6420 break;
6421 case CMD_throw:
6422 line = compile_throw(p, &cctx);
6423 break;
6424
6425 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006426 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006427 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006428 case CMD_echomsg:
6429 case CMD_echoerr:
6430 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006431 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006432
6433 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006434 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006435 // Not recognized, execute with do_cmdline_cmd().
6436 ea.arg = p;
6437 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006438 break;
6439 }
6440 if (line == NULL)
6441 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006442 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006443
6444 if (cctx.ctx_type_stack.ga_len < 0)
6445 {
6446 iemsg("Type stack underflow");
6447 goto erret;
6448 }
6449 }
6450
6451 if (cctx.ctx_scope != NULL)
6452 {
6453 if (cctx.ctx_scope->se_type == IF_SCOPE)
6454 emsg(_(e_endif));
6455 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6456 emsg(_(e_endwhile));
6457 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6458 emsg(_(e_endfor));
6459 else
6460 emsg(_("E1026: Missing }"));
6461 goto erret;
6462 }
6463
6464 if (!had_return)
6465 {
6466 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6467 {
6468 emsg(_("E1027: Missing return statement"));
6469 goto erret;
6470 }
6471
6472 // Return zero if there is no return at the end.
6473 generate_PUSHNR(&cctx, 0);
6474 generate_instr(&cctx, ISN_RETURN);
6475 }
6476
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006477 {
6478 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6479 + ufunc->uf_dfunc_idx;
6480 dfunc->df_deleted = FALSE;
6481 dfunc->df_instr = instr->ga_data;
6482 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006483 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02006484 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006485 if (cctx.ctx_outer_used)
6486 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006487 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006488
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006489 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006490 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006491 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006492
6493 // Create a type for the function, with the return type and any
6494 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006495 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6496 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006497 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006498 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006499 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6500 argcount, &ufunc->uf_type_list);
6501 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006502 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006503 argcount + varargs,
6504 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006505 {
6506 ret = FAIL;
6507 goto erret;
6508 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006509 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6510 ufunc->uf_func_type->tt_min_argcount =
6511 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006512 if (ufunc->uf_arg_types == NULL)
6513 {
6514 int i;
6515
6516 // lambda does not have argument types.
6517 for (i = 0; i < argcount; ++i)
6518 ufunc->uf_func_type->tt_args[i] = &t_any;
6519 }
6520 else
6521 mch_memmove(ufunc->uf_func_type->tt_args,
6522 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006523 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006524 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006525 ufunc->uf_func_type->tt_args[argcount] =
6526 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006527 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6528 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006529 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006530 else
6531 // No arguments, can use a predefined type.
6532 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6533 argcount, &ufunc->uf_type_list);
6534
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006535 }
6536
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006537 ret = OK;
6538
6539erret:
6540 if (ret == FAIL)
6541 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006542 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006543 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6544 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006545
6546 for (idx = 0; idx < instr->ga_len; ++idx)
6547 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006548 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006549
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006550 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006551 if (!dfunc->df_deleted)
6552 --def_functions.ga_len;
6553
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006554 while (cctx.ctx_scope != NULL)
6555 drop_scope(&cctx);
6556
Bram Moolenaar20431c92020-03-20 18:39:46 +01006557 // Don't execute this function body.
6558 ga_clear_strings(&ufunc->uf_lines);
6559
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006560 if (errormsg != NULL)
6561 emsg(errormsg);
6562 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006563 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006564 }
6565
6566 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006567 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006568 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006569 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006570}
6571
6572/*
6573 * Delete an instruction, free what it contains.
6574 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006575 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006576delete_instr(isn_T *isn)
6577{
6578 switch (isn->isn_type)
6579 {
6580 case ISN_EXEC:
6581 case ISN_LOADENV:
6582 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006583 case ISN_LOADB:
6584 case ISN_LOADW:
6585 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006586 case ISN_LOADOPT:
6587 case ISN_MEMBER:
6588 case ISN_PUSHEXC:
6589 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006590 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006591 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006592 case ISN_STOREB:
6593 case ISN_STOREW:
6594 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006595 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006596 vim_free(isn->isn_arg.string);
6597 break;
6598
6599 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006600 case ISN_STORES:
6601 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006602 break;
6603
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006604 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006605 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006606 vim_free(isn->isn_arg.unlet.ul_name);
6607 break;
6608
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006609 case ISN_STOREOPT:
6610 vim_free(isn->isn_arg.storeopt.so_name);
6611 break;
6612
6613 case ISN_PUSHBLOB: // push blob isn_arg.blob
6614 blob_unref(isn->isn_arg.blob);
6615 break;
6616
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006617 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006618#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006619 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006620#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006621 break;
6622
6623 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006624#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006625 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006626#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006627 break;
6628
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006629 case ISN_UCALL:
6630 vim_free(isn->isn_arg.ufunc.cuf_name);
6631 break;
6632
6633 case ISN_2BOOL:
6634 case ISN_2STRING:
6635 case ISN_ADDBLOB:
6636 case ISN_ADDLIST:
6637 case ISN_BCALL:
6638 case ISN_CATCH:
6639 case ISN_CHECKNR:
6640 case ISN_CHECKTYPE:
6641 case ISN_COMPAREANY:
6642 case ISN_COMPAREBLOB:
6643 case ISN_COMPAREBOOL:
6644 case ISN_COMPAREDICT:
6645 case ISN_COMPAREFLOAT:
6646 case ISN_COMPAREFUNC:
6647 case ISN_COMPARELIST:
6648 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006649 case ISN_COMPARESPECIAL:
6650 case ISN_COMPARESTRING:
6651 case ISN_CONCAT:
6652 case ISN_DCALL:
6653 case ISN_DROP:
6654 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006655 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006656 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006657 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006658 case ISN_EXECCONCAT:
6659 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006660 case ISN_FOR:
6661 case ISN_FUNCREF:
6662 case ISN_INDEX:
6663 case ISN_JUMP:
6664 case ISN_LOAD:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006665 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006666 case ISN_LOADSCRIPT:
6667 case ISN_LOADREG:
6668 case ISN_LOADV:
6669 case ISN_NEGATENR:
6670 case ISN_NEWDICT:
6671 case ISN_NEWLIST:
6672 case ISN_OPNR:
6673 case ISN_OPFLOAT:
6674 case ISN_OPANY:
6675 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006676 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006677 case ISN_PUSHF:
6678 case ISN_PUSHNR:
6679 case ISN_PUSHBOOL:
6680 case ISN_PUSHSPEC:
6681 case ISN_RETURN:
6682 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006683 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006684 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006685 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006686 case ISN_STORESCRIPT:
6687 case ISN_THROW:
6688 case ISN_TRY:
6689 // nothing allocated
6690 break;
6691 }
6692}
6693
6694/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006695 * Free all instructions for "dfunc".
6696 */
6697 static void
6698delete_def_function_contents(dfunc_T *dfunc)
6699{
6700 int idx;
6701
6702 ga_clear(&dfunc->df_def_args_isn);
6703
6704 if (dfunc->df_instr != NULL)
6705 {
6706 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6707 delete_instr(dfunc->df_instr + idx);
6708 VIM_CLEAR(dfunc->df_instr);
6709 }
6710
6711 dfunc->df_deleted = TRUE;
6712}
6713
6714/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006715 * When a user function is deleted, delete any associated def function.
6716 */
6717 void
6718delete_def_function(ufunc_T *ufunc)
6719{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006720 if (ufunc->uf_dfunc_idx >= 0)
6721 {
6722 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6723 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006724
Bram Moolenaar20431c92020-03-20 18:39:46 +01006725 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006726 }
6727}
6728
6729#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006730/*
6731 * Free all functions defined with ":def".
6732 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006733 void
6734free_def_functions(void)
6735{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006736 int idx;
6737
6738 for (idx = 0; idx < def_functions.ga_len; ++idx)
6739 {
6740 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6741
6742 delete_def_function_contents(dfunc);
6743 }
6744
6745 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006746}
6747#endif
6748
6749
6750#endif // FEAT_EVAL