blob: 8b1dcd5d572fc42e42b32090528dce8cb5ad8ffe [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
Bram Moolenaarefd88552020-06-18 20:50:10 +020026// values for ctx_skip
27typedef enum {
28 SKIP_NOT, // condition is a constant, produce code
29 SKIP_YES, // condition is a constant, do NOT produce code
Bram Moolenaar280b0dc2020-06-20 13:29:03 +020030 SKIP_UNKNOWN // condition is not a constant, produce code
Bram Moolenaarefd88552020-06-18 20:50:10 +020031} skip_T;
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033/*
34 * Chain of jump instructions where the end label needs to be set.
35 */
36typedef struct endlabel_S endlabel_T;
37struct endlabel_S {
38 endlabel_T *el_next; // chain end_label locations
39 int el_end_label; // instruction idx where to set end
40};
41
42/*
43 * info specific for the scope of :if / elseif / else
44 */
45typedef struct {
Bram Moolenaarefd88552020-06-18 20:50:10 +020046 int is_seen_else;
47 int is_had_return; // every block ends in :return
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010048 int is_if_label; // instruction idx at IF or ELSEIF
49 endlabel_T *is_end_label; // instructions to set end label
50} ifscope_T;
51
52/*
53 * info specific for the scope of :while
54 */
55typedef struct {
56 int ws_top_label; // instruction idx at WHILE
57 endlabel_T *ws_end_label; // instructions to set end
58} whilescope_T;
59
60/*
61 * info specific for the scope of :for
62 */
63typedef struct {
64 int fs_top_label; // instruction idx at FOR
65 endlabel_T *fs_end_label; // break instructions
66} forscope_T;
67
68/*
69 * info specific for the scope of :try
70 */
71typedef struct {
72 int ts_try_label; // instruction idx at TRY
73 endlabel_T *ts_end_label; // jump to :finally or :endtry
74 int ts_catch_label; // instruction idx of last CATCH
75 int ts_caught_all; // "catch" without argument encountered
76} tryscope_T;
77
78typedef enum {
79 NO_SCOPE,
80 IF_SCOPE,
81 WHILE_SCOPE,
82 FOR_SCOPE,
83 TRY_SCOPE,
84 BLOCK_SCOPE
85} scopetype_T;
86
87/*
88 * Info for one scope, pointed to by "ctx_scope".
89 */
90typedef struct scope_S scope_T;
91struct scope_S {
92 scope_T *se_outer; // scope containing this one
93 scopetype_T se_type;
94 int se_local_count; // ctx_locals.ga_len before scope
Bram Moolenaarefd88552020-06-18 20:50:10 +020095 skip_T se_skip_save; // ctx_skip before the block
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010096 union {
97 ifscope_T se_if;
98 whilescope_T se_while;
99 forscope_T se_for;
100 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +0100101 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100102};
103
104/*
105 * Entry for "ctx_locals". Used for arguments and local variables.
106 */
107typedef struct {
108 char_u *lv_name;
109 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200110 int lv_idx; // index of the variable on the stack
111 int lv_from_outer; // when TRUE using ctx_outer scope
112 int lv_const; // when TRUE cannot be assigned to
113 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100114} lvar_T;
115
116/*
117 * Context for compiling lines of Vim script.
118 * Stores info about the local variables and condition stack.
119 */
120struct cctx_S {
121 ufunc_T *ctx_ufunc; // current function
122 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200123 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100124 garray_T ctx_instr; // generated instructions
125
126 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200127 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100128
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200129 int ctx_closure_count; // number of closures created in the
130 // function
131
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100132 garray_T ctx_imports; // imported items
133
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200134 skip_T ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135 scope_T *ctx_scope; // current scope, NULL at toplevel
Bram Moolenaarefd88552020-06-18 20:50:10 +0200136 int ctx_had_return; // last seen statement was "return"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100137
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200138 cctx_T *ctx_outer; // outer scope for lambda or nested
139 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200140 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200141
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100142 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200143 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100144};
145
Bram Moolenaar20431c92020-03-20 18:39:46 +0100146static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100147
148/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200149 * Lookup variable "name" in the local scope and return it.
150 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100151 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200152 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100153lookup_local(char_u *name, size_t len, cctx_T *cctx)
154{
155 int idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200156 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100157
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100158 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200159 return NULL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200160
161 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100162 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
163 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200164 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100165 if (STRNCMP(name, lvar->lv_name, len) == 0
166 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200167 {
168 lvar->lv_from_outer = FALSE;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200169 return lvar;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200170 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100171 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200172
173 // Find local in outer function scope.
174 if (cctx->ctx_outer != NULL)
175 {
176 lvar = lookup_local(name, len, cctx->ctx_outer);
177 if (lvar != NULL)
178 {
179 // TODO: are there situations we should not mark the outer scope as
180 // used?
181 cctx->ctx_outer_used = TRUE;
182 lvar->lv_from_outer = TRUE;
183 return lvar;
184 }
185 }
186
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200187 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100188}
189
190/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200191 * Lookup an argument in the current function and an enclosing function.
192 * Returns the argument index in "idxp"
193 * Returns the argument type in "type"
194 * Sets "gen_load_outer" to TRUE if found in outer scope.
195 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100196 */
197 static int
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200198lookup_arg(
199 char_u *name,
200 size_t len,
201 int *idxp,
202 type_T **type,
203 int *gen_load_outer,
204 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100205{
206 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200207 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100208
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100209 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200210 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100211 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
212 {
213 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
214
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200215 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
216 {
217 if (idxp != NULL)
218 {
219 // Arguments are located above the frame pointer. One further
220 // if there is a vararg argument
221 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
222 + STACK_FRAME_SIZE)
223 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
224
225 if (cctx->ctx_ufunc->uf_arg_types != NULL)
226 *type = cctx->ctx_ufunc->uf_arg_types[idx];
227 else
228 *type = &t_any;
229 }
230 return OK;
231 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100232 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100233
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200234 va_name = cctx->ctx_ufunc->uf_va_name;
235 if (va_name != NULL
236 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
237 {
238 if (idxp != NULL)
239 {
240 // varargs is always the last argument
241 *idxp = -STACK_FRAME_SIZE - 1;
242 *type = cctx->ctx_ufunc->uf_va_type;
243 }
244 return OK;
245 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100246
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200247 if (cctx->ctx_outer != NULL)
248 {
249 // Lookup the name for an argument of the outer function.
250 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
251 == OK)
252 {
253 *gen_load_outer = TRUE;
254 return OK;
255 }
256 }
257
258 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100259}
260
261/*
Bram Moolenaar84367732020-08-23 15:21:55 +0200262 * Returnd TRUE if the script context is Vim9 script.
263 */
264 static int
265script_is_vim9()
266{
267 return SCRIPT_ITEM(current_sctx.sc_sid)->sn_version == SCRIPT_VERSION_VIM9;
268}
269
270/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 * Lookup a variable in the current script.
Bram Moolenaar53900992020-08-22 19:02:02 +0200272 * If "vim9script" is TRUE the script must be Vim9 script. Used for "var"
273 * without "s:".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100274 * Returns OK or FAIL.
275 */
276 static int
Bram Moolenaar53900992020-08-22 19:02:02 +0200277lookup_script(char_u *name, size_t len, int vim9script)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100278{
279 int cc;
280 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
281 dictitem_T *di;
282
Bram Moolenaar84367732020-08-23 15:21:55 +0200283 if (vim9script && !script_is_vim9())
Bram Moolenaar53900992020-08-22 19:02:02 +0200284 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285 cc = name[len];
286 name[len] = NUL;
287 di = find_var_in_ht(ht, 0, name, TRUE);
288 name[len] = cc;
289 return di == NULL ? FAIL: OK;
290}
291
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100292/*
293 * Check if "p[len]" is already defined, either in script "import_sid" or in
294 * compilation context "cctx".
295 * Return FAIL and give an error if it defined.
296 */
297 int
Bram Moolenaarcbb6bdc2020-07-06 21:53:17 +0200298check_defined(char_u *p, size_t len, cctx_T *cctx)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100299{
Bram Moolenaarad486a02020-08-01 23:22:18 +0200300 int c = p[len];
301
302 p[len] = NUL;
Bram Moolenaar53900992020-08-22 19:02:02 +0200303 if (lookup_script(p, len, FALSE) == OK
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100304 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200305 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaareef21022020-08-01 22:16:43 +0200306 || lookup_arg(p, len, NULL, NULL, NULL, cctx) == OK))
Bram Moolenaarad486a02020-08-01 23:22:18 +0200307 || find_imported(p, len, cctx) != NULL
308 || find_func_even_dead(p, FALSE, cctx) != NULL)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100309 {
Bram Moolenaarad486a02020-08-01 23:22:18 +0200310 p[len] = c;
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +0200311 semsg(_(e_name_already_defined_str), p);
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100312 return FAIL;
313 }
Bram Moolenaarad486a02020-08-01 23:22:18 +0200314 p[len] = c;
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100315 return OK;
316}
317
Bram Moolenaar65b95452020-07-19 14:03:09 +0200318
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100319/////////////////////////////////////////////////////////////////////
320// Following generate_ functions expect the caller to call ga_grow().
321
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200322#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return NULL
323#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return OK
Bram Moolenaar080457c2020-03-03 21:53:32 +0100324
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100325/*
326 * Generate an instruction without arguments.
327 * Returns a pointer to the new instruction, NULL if failed.
328 */
329 static isn_T *
330generate_instr(cctx_T *cctx, isntype_T isn_type)
331{
332 garray_T *instr = &cctx->ctx_instr;
333 isn_T *isn;
334
Bram Moolenaar080457c2020-03-03 21:53:32 +0100335 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100336 if (ga_grow(instr, 1) == FAIL)
337 return NULL;
338 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
339 isn->isn_type = isn_type;
340 isn->isn_lnum = cctx->ctx_lnum + 1;
341 ++instr->ga_len;
342
343 return isn;
344}
345
346/*
347 * Generate an instruction without arguments.
348 * "drop" will be removed from the stack.
349 * Returns a pointer to the new instruction, NULL if failed.
350 */
351 static isn_T *
352generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
353{
354 garray_T *stack = &cctx->ctx_type_stack;
355
Bram Moolenaar080457c2020-03-03 21:53:32 +0100356 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100357 stack->ga_len -= drop;
358 return generate_instr(cctx, isn_type);
359}
360
361/*
362 * Generate instruction "isn_type" and put "type" on the type stack.
363 */
364 static isn_T *
365generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
366{
367 isn_T *isn;
368 garray_T *stack = &cctx->ctx_type_stack;
369
370 if ((isn = generate_instr(cctx, isn_type)) == NULL)
371 return NULL;
372
373 if (ga_grow(stack, 1) == FAIL)
374 return NULL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +0200375 ((type_T **)stack->ga_data)[stack->ga_len] = type == NULL ? &t_any : type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100376 ++stack->ga_len;
377
378 return isn;
379}
380
381/*
382 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200383 * But only for simple types.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100384 */
385 static int
386may_generate_2STRING(int offset, cctx_T *cctx)
387{
388 isn_T *isn;
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200389 isntype_T isntype = ISN_2STRING;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100390 garray_T *stack = &cctx->ctx_type_stack;
391 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
392
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200393 switch ((*type)->tt_type)
394 {
395 // nothing to be done
396 case VAR_STRING: return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100397
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200398 // conversion possible
399 case VAR_SPECIAL:
400 case VAR_BOOL:
401 case VAR_NUMBER:
402 case VAR_FLOAT:
403 break;
404
405 // conversion possible (with runtime check)
406 case VAR_ANY:
407 case VAR_UNKNOWN:
408 isntype = ISN_2STRING_ANY;
409 break;
410
411 // conversion not possible
412 case VAR_VOID:
413 case VAR_BLOB:
414 case VAR_FUNC:
415 case VAR_PARTIAL:
416 case VAR_LIST:
417 case VAR_DICT:
418 case VAR_JOB:
419 case VAR_CHANNEL:
420 to_string_error((*type)->tt_type);
421 return FAIL;
422 }
423
424 *type = &t_string;
425 if ((isn = generate_instr(cctx, isntype)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100426 return FAIL;
427 isn->isn_arg.number = offset;
428
429 return OK;
430}
431
432 static int
433check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
434{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200435 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100436 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200437 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100438 {
439 if (*op == '+')
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200440 emsg(_(e_wrong_argument_type_for_plus));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100441 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200442 semsg(_(e_char_requires_number_or_float_arguments), *op);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100443 return FAIL;
444 }
445 return OK;
446}
447
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200448 static int
449generate_add_instr(
450 cctx_T *cctx,
451 vartype_T vartype,
452 type_T *type1,
453 type_T *type2)
454{
455 isn_T *isn = generate_instr_drop(cctx,
456 vartype == VAR_NUMBER ? ISN_OPNR
457 : vartype == VAR_LIST ? ISN_ADDLIST
458 : vartype == VAR_BLOB ? ISN_ADDBLOB
459#ifdef FEAT_FLOAT
460 : vartype == VAR_FLOAT ? ISN_OPFLOAT
461#endif
462 : ISN_OPANY, 1);
463
464 if (vartype != VAR_LIST && vartype != VAR_BLOB
465 && type1->tt_type != VAR_ANY
466 && type2->tt_type != VAR_ANY
467 && check_number_or_float(
468 type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL)
469 return FAIL;
470
471 if (isn != NULL)
472 isn->isn_arg.op.op_type = EXPR_ADD;
473 return isn == NULL ? FAIL : OK;
474}
475
476/*
477 * Get the type to use for an instruction for an operation on "type1" and
478 * "type2". If they are matching use a type-specific instruction. Otherwise
479 * fall back to runtime type checking.
480 */
481 static vartype_T
482operator_type(type_T *type1, type_T *type2)
483{
484 if (type1->tt_type == type2->tt_type
485 && (type1->tt_type == VAR_NUMBER
486 || type1->tt_type == VAR_LIST
487#ifdef FEAT_FLOAT
488 || type1->tt_type == VAR_FLOAT
489#endif
490 || type1->tt_type == VAR_BLOB))
491 return type1->tt_type;
492 return VAR_ANY;
493}
494
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100495/*
496 * Generate an instruction with two arguments. The instruction depends on the
497 * type of the arguments.
498 */
499 static int
500generate_two_op(cctx_T *cctx, char_u *op)
501{
502 garray_T *stack = &cctx->ctx_type_stack;
503 type_T *type1;
504 type_T *type2;
505 vartype_T vartype;
506 isn_T *isn;
507
Bram Moolenaar080457c2020-03-03 21:53:32 +0100508 RETURN_OK_IF_SKIP(cctx);
509
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200510 // Get the known type of the two items on the stack.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100511 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
512 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200513 vartype = operator_type(type1, type2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100514
515 switch (*op)
516 {
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200517 case '+':
518 if (generate_add_instr(cctx, vartype, type1, type2) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100519 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100520 break;
521
522 case '-':
523 case '*':
524 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
525 op) == FAIL)
526 return FAIL;
527 if (vartype == VAR_NUMBER)
528 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
529#ifdef FEAT_FLOAT
530 else if (vartype == VAR_FLOAT)
531 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
532#endif
533 else
534 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
535 if (isn != NULL)
536 isn->isn_arg.op.op_type = *op == '*'
537 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
538 break;
539
Bram Moolenaar4c683752020-04-05 21:38:23 +0200540 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100541 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200542 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100543 && type2->tt_type != VAR_NUMBER))
544 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200545 emsg(_(e_percent_requires_number_arguments));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100546 return FAIL;
547 }
548 isn = generate_instr_drop(cctx,
549 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
550 if (isn != NULL)
551 isn->isn_arg.op.op_type = EXPR_REM;
552 break;
553 }
554
555 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200556 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100557 {
558 type_T *type = &t_any;
559
560#ifdef FEAT_FLOAT
561 // float+number and number+float results in float
562 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
563 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
564 type = &t_float;
565#endif
566 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
567 }
568
569 return OK;
570}
571
572/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200573 * Get the instruction to use for comparing "type1" with "type2"
574 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100575 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200576 static isntype_T
577get_compare_isn(exptype_T exptype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100578{
579 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100580
Bram Moolenaar4c683752020-04-05 21:38:23 +0200581 if (type1 == VAR_UNKNOWN)
582 type1 = VAR_ANY;
583 if (type2 == VAR_UNKNOWN)
584 type2 = VAR_ANY;
585
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100586 if (type1 == type2)
587 {
588 switch (type1)
589 {
590 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
591 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
592 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
593 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
594 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
595 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
596 case VAR_LIST: isntype = ISN_COMPARELIST; break;
597 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
598 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100599 default: isntype = ISN_COMPAREANY; break;
600 }
601 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200602 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100603 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
604 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
605 isntype = ISN_COMPAREANY;
606
607 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
608 && (isntype == ISN_COMPAREBOOL
609 || isntype == ISN_COMPARESPECIAL
610 || isntype == ISN_COMPARENR
611 || isntype == ISN_COMPAREFLOAT))
612 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200613 semsg(_(e_cannot_use_str_with_str),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100614 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200615 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100616 }
617 if (isntype == ISN_DROP
618 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
619 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
620 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
621 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
622 && exptype != EXPR_IS && exptype != EXPR_ISNOT
623 && (type1 == VAR_BLOB || type2 == VAR_BLOB
624 || type1 == VAR_LIST || type2 == VAR_LIST))))
625 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200626 semsg(_(e_cannot_compare_str_with_str),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100627 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200628 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100629 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200630 return isntype;
631}
632
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200633 int
634check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2)
635{
636 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
637 return FAIL;
638 return OK;
639}
640
Bram Moolenaara5565e42020-05-09 15:44:01 +0200641/*
642 * Generate an ISN_COMPARE* instruction with a boolean result.
643 */
644 static int
645generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
646{
647 isntype_T isntype;
648 isn_T *isn;
649 garray_T *stack = &cctx->ctx_type_stack;
650 vartype_T type1;
651 vartype_T type2;
652
653 RETURN_OK_IF_SKIP(cctx);
654
655 // Get the known type of the two items on the stack. If they are matching
656 // use a type-specific instruction. Otherwise fall back to runtime type
657 // checking.
658 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
659 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
660 isntype = get_compare_isn(exptype, type1, type2);
661 if (isntype == ISN_DROP)
662 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100663
664 if ((isn = generate_instr(cctx, isntype)) == NULL)
665 return FAIL;
666 isn->isn_arg.op.op_type = exptype;
667 isn->isn_arg.op.op_ic = ic;
668
669 // takes two arguments, puts one bool back
670 if (stack->ga_len >= 2)
671 {
672 --stack->ga_len;
673 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
674 }
675
676 return OK;
677}
678
679/*
680 * Generate an ISN_2BOOL instruction.
681 */
682 static int
683generate_2BOOL(cctx_T *cctx, int invert)
684{
685 isn_T *isn;
686 garray_T *stack = &cctx->ctx_type_stack;
687
Bram Moolenaar080457c2020-03-03 21:53:32 +0100688 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100689 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
690 return FAIL;
691 isn->isn_arg.number = invert;
692
693 // type becomes bool
694 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
695
696 return OK;
697}
698
699 static int
700generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
701{
702 isn_T *isn;
703 garray_T *stack = &cctx->ctx_type_stack;
704
Bram Moolenaar080457c2020-03-03 21:53:32 +0100705 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100706 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
707 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +0200708 // TODO: whole type, e.g. for a function also arg and return types
709 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100710 isn->isn_arg.type.ct_off = offset;
711
712 // type becomes vartype
Bram Moolenaar5adc55c2020-05-02 23:12:58 +0200713 ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100714
715 return OK;
716}
717
718/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200719 * Check that
720 * - "actual" is "expected" type or
721 * - "actual" is a type that can be "expected" type: add a runtime check; or
722 * - return FAIL.
723 */
724 static int
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200725need_type(
726 type_T *actual,
727 type_T *expected,
728 int offset,
729 cctx_T *cctx,
730 int silent)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200731{
Bram Moolenaar8b565c22020-08-30 23:24:20 +0200732 if (check_type(expected, actual, FALSE, 0) == OK)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200733 return OK;
734 if (actual->tt_type != VAR_ANY
735 && actual->tt_type != VAR_UNKNOWN
736 && !(actual->tt_type == VAR_FUNC
737 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
738 {
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200739 if (!silent)
740 type_mismatch(expected, actual);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200741 return FAIL;
742 }
743 generate_TYPECHECK(cctx, expected, offset);
744 return OK;
745}
746
747/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100748 * Generate an ISN_PUSHNR instruction.
749 */
750 static int
751generate_PUSHNR(cctx_T *cctx, varnumber_T number)
752{
753 isn_T *isn;
754
Bram Moolenaar080457c2020-03-03 21:53:32 +0100755 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100756 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
757 return FAIL;
758 isn->isn_arg.number = number;
759
760 return OK;
761}
762
763/*
764 * Generate an ISN_PUSHBOOL instruction.
765 */
766 static int
767generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
768{
769 isn_T *isn;
770
Bram Moolenaar080457c2020-03-03 21:53:32 +0100771 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100772 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
773 return FAIL;
774 isn->isn_arg.number = number;
775
776 return OK;
777}
778
779/*
780 * Generate an ISN_PUSHSPEC instruction.
781 */
782 static int
783generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
784{
785 isn_T *isn;
786
Bram Moolenaar080457c2020-03-03 21:53:32 +0100787 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100788 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
789 return FAIL;
790 isn->isn_arg.number = number;
791
792 return OK;
793}
794
795#ifdef FEAT_FLOAT
796/*
797 * Generate an ISN_PUSHF instruction.
798 */
799 static int
800generate_PUSHF(cctx_T *cctx, float_T fnumber)
801{
802 isn_T *isn;
803
Bram Moolenaar080457c2020-03-03 21:53:32 +0100804 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100805 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
806 return FAIL;
807 isn->isn_arg.fnumber = fnumber;
808
809 return OK;
810}
811#endif
812
813/*
814 * Generate an ISN_PUSHS instruction.
815 * Consumes "str".
816 */
817 static int
818generate_PUSHS(cctx_T *cctx, char_u *str)
819{
820 isn_T *isn;
821
Bram Moolenaar080457c2020-03-03 21:53:32 +0100822 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100823 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
824 return FAIL;
825 isn->isn_arg.string = str;
826
827 return OK;
828}
829
830/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100831 * Generate an ISN_PUSHCHANNEL instruction.
832 * Consumes "channel".
833 */
834 static int
835generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
836{
837 isn_T *isn;
838
Bram Moolenaar080457c2020-03-03 21:53:32 +0100839 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100840 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
841 return FAIL;
842 isn->isn_arg.channel = channel;
843
844 return OK;
845}
846
847/*
848 * Generate an ISN_PUSHJOB instruction.
849 * Consumes "job".
850 */
851 static int
852generate_PUSHJOB(cctx_T *cctx, job_T *job)
853{
854 isn_T *isn;
855
Bram Moolenaar080457c2020-03-03 21:53:32 +0100856 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100857 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100858 return FAIL;
859 isn->isn_arg.job = job;
860
861 return OK;
862}
863
864/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100865 * Generate an ISN_PUSHBLOB instruction.
866 * Consumes "blob".
867 */
868 static int
869generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
870{
871 isn_T *isn;
872
Bram Moolenaar080457c2020-03-03 21:53:32 +0100873 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100874 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
875 return FAIL;
876 isn->isn_arg.blob = blob;
877
878 return OK;
879}
880
881/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100882 * Generate an ISN_PUSHFUNC instruction with name "name".
883 * Consumes "name".
884 */
885 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200886generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100887{
888 isn_T *isn;
889
Bram Moolenaar080457c2020-03-03 21:53:32 +0100890 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200891 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100892 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +0200893 isn->isn_arg.string = name == NULL ? NULL : vim_strsave(name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100894
895 return OK;
896}
897
898/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +0200899 * Generate an ISN_GETITEM instruction with "index".
900 */
901 static int
902generate_GETITEM(cctx_T *cctx, int index)
903{
904 isn_T *isn;
905 garray_T *stack = &cctx->ctx_type_stack;
906 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
907 type_T *item_type = &t_any;
908
909 RETURN_OK_IF_SKIP(cctx);
910
Bram Moolenaarc7db5772020-07-21 20:55:50 +0200911 if (type->tt_type != VAR_LIST)
Bram Moolenaar47a519a2020-06-14 23:05:10 +0200912 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +0200913 // cannot happen, caller has checked the type
Bram Moolenaar47a519a2020-06-14 23:05:10 +0200914 emsg(_(e_listreq));
915 return FAIL;
916 }
Bram Moolenaarc7db5772020-07-21 20:55:50 +0200917 item_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +0200918 if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
919 return FAIL;
920 isn->isn_arg.number = index;
921
922 // add the item type to the type stack
923 if (ga_grow(stack, 1) == FAIL)
924 return FAIL;
925 ((type_T **)stack->ga_data)[stack->ga_len] = item_type;
926 ++stack->ga_len;
927 return OK;
928}
929
930/*
Bram Moolenaar9af78762020-06-16 11:34:42 +0200931 * Generate an ISN_SLICE instruction with "count".
932 */
933 static int
934generate_SLICE(cctx_T *cctx, int count)
935{
936 isn_T *isn;
937
938 RETURN_OK_IF_SKIP(cctx);
939 if ((isn = generate_instr(cctx, ISN_SLICE)) == NULL)
940 return FAIL;
941 isn->isn_arg.number = count;
942 return OK;
943}
944
945/*
946 * Generate an ISN_CHECKLEN instruction with "min_len".
947 */
948 static int
949generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK)
950{
951 isn_T *isn;
952
953 RETURN_OK_IF_SKIP(cctx);
954
955 if ((isn = generate_instr(cctx, ISN_CHECKLEN)) == NULL)
956 return FAIL;
957 isn->isn_arg.checklen.cl_min_len = min_len;
958 isn->isn_arg.checklen.cl_more_OK = more_OK;
959
960 return OK;
961}
962
963/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100964 * Generate an ISN_STORE instruction.
965 */
966 static int
967generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
968{
969 isn_T *isn;
970
Bram Moolenaar080457c2020-03-03 21:53:32 +0100971 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100972 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
973 return FAIL;
974 if (name != NULL)
975 isn->isn_arg.string = vim_strsave(name);
976 else
977 isn->isn_arg.number = idx;
978
979 return OK;
980}
981
982/*
983 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
984 */
985 static int
986generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
987{
988 isn_T *isn;
989
Bram Moolenaar080457c2020-03-03 21:53:32 +0100990 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100991 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
992 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100993 isn->isn_arg.storenr.stnr_idx = idx;
994 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100995
996 return OK;
997}
998
999/*
1000 * Generate an ISN_STOREOPT instruction
1001 */
1002 static int
1003generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1004{
1005 isn_T *isn;
1006
Bram Moolenaar080457c2020-03-03 21:53:32 +01001007 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1c199f92020-08-07 21:28:34 +02001008 if ((isn = generate_instr_drop(cctx, ISN_STOREOPT, 1)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001009 return FAIL;
1010 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1011 isn->isn_arg.storeopt.so_flags = opt_flags;
1012
1013 return OK;
1014}
1015
1016/*
1017 * Generate an ISN_LOAD or similar instruction.
1018 */
1019 static int
1020generate_LOAD(
1021 cctx_T *cctx,
1022 isntype_T isn_type,
1023 int idx,
1024 char_u *name,
1025 type_T *type)
1026{
1027 isn_T *isn;
1028
Bram Moolenaar080457c2020-03-03 21:53:32 +01001029 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001030 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1031 return FAIL;
1032 if (name != NULL)
1033 isn->isn_arg.string = vim_strsave(name);
1034 else
1035 isn->isn_arg.number = idx;
1036
1037 return OK;
1038}
1039
1040/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001041 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001042 */
1043 static int
1044generate_LOADV(
1045 cctx_T *cctx,
1046 char_u *name,
1047 int error)
1048{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001049 int di_flags;
1050 int vidx = find_vim_var(name, &di_flags);
1051 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001052
Bram Moolenaar080457c2020-03-03 21:53:32 +01001053 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001054 if (vidx < 0)
1055 {
1056 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001057 semsg(_(e_variable_not_found_str), name);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001058 return FAIL;
1059 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02001060 type = typval2type_vimvar(get_vim_var_tv(vidx), cctx->ctx_type_list);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001061
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001062 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001063}
1064
1065/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001066 * Generate an ISN_UNLET instruction.
1067 */
1068 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001069generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001070{
1071 isn_T *isn;
1072
1073 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001074 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001075 return FAIL;
1076 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1077 isn->isn_arg.unlet.ul_forceit = forceit;
1078
1079 return OK;
1080}
1081
1082/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083 * Generate an ISN_LOADS instruction.
1084 */
1085 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001086generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001087 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001088 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001089 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001090 int sid,
1091 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001092{
1093 isn_T *isn;
1094
Bram Moolenaar080457c2020-03-03 21:53:32 +01001095 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001096 if (isn_type == ISN_LOADS)
1097 isn = generate_instr_type(cctx, isn_type, type);
1098 else
1099 isn = generate_instr_drop(cctx, isn_type, 1);
1100 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001102 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1103 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001104
1105 return OK;
1106}
1107
1108/*
1109 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1110 */
1111 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001112generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001113 cctx_T *cctx,
1114 isntype_T isn_type,
1115 int sid,
1116 int idx,
1117 type_T *type)
1118{
1119 isn_T *isn;
1120
Bram Moolenaar080457c2020-03-03 21:53:32 +01001121 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001122 if (isn_type == ISN_LOADSCRIPT)
1123 isn = generate_instr_type(cctx, isn_type, type);
1124 else
1125 isn = generate_instr_drop(cctx, isn_type, 1);
1126 if (isn == NULL)
1127 return FAIL;
1128 isn->isn_arg.script.script_sid = sid;
1129 isn->isn_arg.script.script_idx = idx;
1130 return OK;
1131}
1132
1133/*
1134 * Generate an ISN_NEWLIST instruction.
1135 */
1136 static int
1137generate_NEWLIST(cctx_T *cctx, int count)
1138{
1139 isn_T *isn;
1140 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001141 type_T *type;
1142 type_T *member;
1143
Bram Moolenaar080457c2020-03-03 21:53:32 +01001144 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001145 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1146 return FAIL;
1147 isn->isn_arg.number = count;
1148
Bram Moolenaar127542b2020-08-09 17:22:04 +02001149 // get the member type from all the items on the stack.
Bram Moolenaar9c2b0662020-09-01 19:56:15 +02001150 if (count == 0)
1151 member = &t_void;
1152 else
1153 member = get_member_type_from_stack(
Bram Moolenaar127542b2020-08-09 17:22:04 +02001154 ((type_T **)stack->ga_data) + stack->ga_len, count, 1,
1155 cctx->ctx_type_list);
1156 type = get_list_type(member, cctx->ctx_type_list);
1157
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001158 // drop the value types
1159 stack->ga_len -= count;
1160
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001161 // add the list type to the type stack
1162 if (ga_grow(stack, 1) == FAIL)
1163 return FAIL;
1164 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1165 ++stack->ga_len;
1166
1167 return OK;
1168}
1169
1170/*
1171 * Generate an ISN_NEWDICT instruction.
1172 */
1173 static int
1174generate_NEWDICT(cctx_T *cctx, int count)
1175{
1176 isn_T *isn;
1177 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001178 type_T *type;
1179 type_T *member;
1180
Bram Moolenaar080457c2020-03-03 21:53:32 +01001181 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001182 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1183 return FAIL;
1184 isn->isn_arg.number = count;
1185
Bram Moolenaar9c2b0662020-09-01 19:56:15 +02001186 if (count == 0)
1187 member = &t_void;
1188 else
1189 member = get_member_type_from_stack(
Bram Moolenaar127542b2020-08-09 17:22:04 +02001190 ((type_T **)stack->ga_data) + stack->ga_len, count, 2,
1191 cctx->ctx_type_list);
1192 type = get_dict_type(member, cctx->ctx_type_list);
1193
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001194 // drop the key and value types
1195 stack->ga_len -= 2 * count;
1196
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001197 // add the dict type to the type stack
1198 if (ga_grow(stack, 1) == FAIL)
1199 return FAIL;
1200 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1201 ++stack->ga_len;
1202
1203 return OK;
1204}
1205
1206/*
1207 * Generate an ISN_FUNCREF instruction.
1208 */
1209 static int
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001210generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001211{
1212 isn_T *isn;
1213 garray_T *stack = &cctx->ctx_type_stack;
1214
Bram Moolenaar080457c2020-03-03 21:53:32 +01001215 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001216 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1217 return FAIL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001218 isn->isn_arg.funcref.fr_func = ufunc->uf_dfunc_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001219 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001220
1221 if (ga_grow(stack, 1) == FAIL)
1222 return FAIL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001223 ((type_T **)stack->ga_data)[stack->ga_len] =
1224 ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001225 ++stack->ga_len;
1226
1227 return OK;
1228}
1229
1230/*
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001231 * Generate an ISN_NEWFUNC instruction.
1232 */
1233 static int
1234generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
1235{
1236 isn_T *isn;
1237 char_u *name;
1238
1239 RETURN_OK_IF_SKIP(cctx);
1240 name = vim_strsave(lambda_name);
1241 if (name == NULL)
1242 return FAIL;
1243 if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
1244 return FAIL;
1245 isn->isn_arg.newfunc.nf_lambda = name;
1246 isn->isn_arg.newfunc.nf_global = func_name;
1247
1248 return OK;
1249}
1250
1251/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001252 * Generate an ISN_JUMP instruction.
1253 */
1254 static int
1255generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1256{
1257 isn_T *isn;
1258 garray_T *stack = &cctx->ctx_type_stack;
1259
Bram Moolenaar080457c2020-03-03 21:53:32 +01001260 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001261 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1262 return FAIL;
1263 isn->isn_arg.jump.jump_when = when;
1264 isn->isn_arg.jump.jump_where = where;
1265
1266 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1267 --stack->ga_len;
1268
1269 return OK;
1270}
1271
1272 static int
1273generate_FOR(cctx_T *cctx, int loop_idx)
1274{
1275 isn_T *isn;
1276 garray_T *stack = &cctx->ctx_type_stack;
1277
Bram Moolenaar080457c2020-03-03 21:53:32 +01001278 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001279 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1280 return FAIL;
1281 isn->isn_arg.forloop.for_idx = loop_idx;
1282
1283 if (ga_grow(stack, 1) == FAIL)
1284 return FAIL;
1285 // type doesn't matter, will be stored next
1286 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1287 ++stack->ga_len;
1288
1289 return OK;
1290}
1291
1292/*
1293 * Generate an ISN_BCALL instruction.
Bram Moolenaar389df252020-07-09 21:20:47 +02001294 * "method_call" is TRUE for "value->method()"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001295 * Return FAIL if the number of arguments is wrong.
1296 */
1297 static int
Bram Moolenaar389df252020-07-09 21:20:47 +02001298generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001299{
1300 isn_T *isn;
1301 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar389df252020-07-09 21:20:47 +02001302 int argoff;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001303 type_T *argtypes[MAX_FUNC_ARGS];
1304 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001305
Bram Moolenaar080457c2020-03-03 21:53:32 +01001306 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar389df252020-07-09 21:20:47 +02001307 argoff = check_internal_func(func_idx, argcount);
1308 if (argoff < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001309 return FAIL;
1310
Bram Moolenaar389df252020-07-09 21:20:47 +02001311 if (method_call && argoff > 1)
1312 {
1313 if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
1314 return FAIL;
1315 isn->isn_arg.shuffle.shfl_item = argcount;
1316 isn->isn_arg.shuffle.shfl_up = argoff - 1;
1317 }
1318
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001319 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1320 return FAIL;
1321 isn->isn_arg.bfunc.cbf_idx = func_idx;
1322 isn->isn_arg.bfunc.cbf_argcount = argcount;
1323
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001324 for (i = 0; i < argcount; ++i)
1325 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1326
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001327 stack->ga_len -= argcount; // drop the arguments
1328 if (ga_grow(stack, 1) == FAIL)
1329 return FAIL;
1330 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001331 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001332 ++stack->ga_len; // add return value
1333
1334 return OK;
1335}
1336
1337/*
1338 * Generate an ISN_DCALL or ISN_UCALL instruction.
1339 * Return FAIL if the number of arguments is wrong.
1340 */
1341 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001342generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001343{
1344 isn_T *isn;
1345 garray_T *stack = &cctx->ctx_type_stack;
1346 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001347 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001348
Bram Moolenaar080457c2020-03-03 21:53:32 +01001349 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001350 if (argcount > regular_args && !has_varargs(ufunc))
1351 {
1352 semsg(_(e_toomanyarg), ufunc->uf_name);
1353 return FAIL;
1354 }
1355 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1356 {
1357 semsg(_(e_toofewarg), ufunc->uf_name);
1358 return FAIL;
1359 }
1360
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001361 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001362 {
1363 int i;
1364
1365 for (i = 0; i < argcount; ++i)
1366 {
1367 type_T *expected;
1368 type_T *actual;
1369
1370 if (i < regular_args)
1371 {
1372 if (ufunc->uf_arg_types == NULL)
1373 continue;
1374 expected = ufunc->uf_arg_types[i];
1375 }
Bram Moolenaar79e8db92020-08-14 22:16:33 +02001376 else if (ufunc->uf_va_type == NULL)
1377 // possibly a lambda
1378 expected = &t_any;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001379 else
1380 expected = ufunc->uf_va_type->tt_member;
1381 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001382 if (need_type(actual, expected, -argcount + i, cctx, TRUE) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001383 {
1384 arg_type_mismatch(expected, actual, i + 1);
1385 return FAIL;
1386 }
1387 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001388 if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001389 if (compile_def_function(ufunc, ufunc->uf_ret_type == NULL, NULL)
1390 == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02001391 return FAIL;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001392 }
1393
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001394 if ((isn = generate_instr(cctx,
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001395 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
Bram Moolenaar822ba242020-05-24 23:00:18 +02001396 : ISN_UCALL)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001397 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001398 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001399 {
1400 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1401 isn->isn_arg.dfunc.cdf_argcount = argcount;
1402 }
1403 else
1404 {
1405 // A user function may be deleted and redefined later, can't use the
1406 // ufunc pointer, need to look it up again at runtime.
1407 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1408 isn->isn_arg.ufunc.cuf_argcount = argcount;
1409 }
1410
1411 stack->ga_len -= argcount; // drop the arguments
1412 if (ga_grow(stack, 1) == FAIL)
1413 return FAIL;
1414 // add return value
1415 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1416 ++stack->ga_len;
1417
1418 return OK;
1419}
1420
1421/*
1422 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1423 */
1424 static int
1425generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1426{
1427 isn_T *isn;
1428 garray_T *stack = &cctx->ctx_type_stack;
1429
Bram Moolenaar080457c2020-03-03 21:53:32 +01001430 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001431 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1432 return FAIL;
1433 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1434 isn->isn_arg.ufunc.cuf_argcount = argcount;
1435
1436 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001437 if (ga_grow(stack, 1) == FAIL)
1438 return FAIL;
1439 // add return value
1440 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1441 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001442
1443 return OK;
1444}
1445
1446/*
1447 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001448 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001449 */
1450 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001451generate_PCALL(
1452 cctx_T *cctx,
1453 int argcount,
1454 char_u *name,
1455 type_T *type,
1456 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001457{
1458 isn_T *isn;
1459 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001460 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001461
Bram Moolenaar080457c2020-03-03 21:53:32 +01001462 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001463
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001464 if (type->tt_type == VAR_ANY)
1465 ret_type = &t_any;
1466 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001467 {
1468 if (type->tt_argcount != -1)
1469 {
1470 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1471
1472 if (argcount < type->tt_min_argcount - varargs)
1473 {
1474 semsg(_(e_toofewarg), "[reference]");
1475 return FAIL;
1476 }
1477 if (!varargs && argcount > type->tt_argcount)
1478 {
1479 semsg(_(e_toomanyarg), "[reference]");
1480 return FAIL;
1481 }
1482 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001483 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001484 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001485 else
1486 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001487 semsg(_(e_not_callable_type_str), name);
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001488 return FAIL;
1489 }
1490
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001491 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1492 return FAIL;
1493 isn->isn_arg.pfunc.cpf_top = at_top;
1494 isn->isn_arg.pfunc.cpf_argcount = argcount;
1495
1496 stack->ga_len -= argcount; // drop the arguments
1497
1498 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001499 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001500
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001501 // If partial is above the arguments it must be cleared and replaced with
1502 // the return value.
1503 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1504 return FAIL;
1505
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001506 return OK;
1507}
1508
1509/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001510 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001511 */
1512 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001513generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001514{
1515 isn_T *isn;
1516 garray_T *stack = &cctx->ctx_type_stack;
1517 type_T *type;
1518
Bram Moolenaar080457c2020-03-03 21:53:32 +01001519 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001520 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001521 return FAIL;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001522 isn->isn_arg.string = vim_strnsave(name, len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001523
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001524 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001525 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001526 if (type->tt_type != VAR_DICT && type != &t_any)
1527 {
1528 emsg(_(e_dictreq));
1529 return FAIL;
1530 }
1531 // change dict type to dict member type
1532 if (type->tt_type == VAR_DICT)
1533 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001534
1535 return OK;
1536}
1537
1538/*
1539 * Generate an ISN_ECHO instruction.
1540 */
1541 static int
1542generate_ECHO(cctx_T *cctx, int with_white, int count)
1543{
1544 isn_T *isn;
1545
Bram Moolenaar080457c2020-03-03 21:53:32 +01001546 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001547 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1548 return FAIL;
1549 isn->isn_arg.echo.echo_with_white = with_white;
1550 isn->isn_arg.echo.echo_count = count;
1551
1552 return OK;
1553}
1554
Bram Moolenaarad39c092020-02-26 18:23:43 +01001555/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001556 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001557 */
1558 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001559generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001560{
1561 isn_T *isn;
1562
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001563 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001564 return FAIL;
1565 isn->isn_arg.number = count;
1566
1567 return OK;
1568}
1569
Bram Moolenaarc3516f72020-09-08 22:45:35 +02001570/*
1571 * Generate an ISN_PUT instruction.
1572 */
1573 static int
1574generate_PUT(cctx_T *cctx, int regname, linenr_T lnum)
1575{
1576 isn_T *isn;
1577
1578 RETURN_OK_IF_SKIP(cctx);
1579 if ((isn = generate_instr(cctx, ISN_PUT)) == NULL)
1580 return FAIL;
1581 isn->isn_arg.put.put_regname = regname;
1582 isn->isn_arg.put.put_lnum = lnum;
1583 return OK;
1584}
1585
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001586 static int
1587generate_EXEC(cctx_T *cctx, char_u *line)
1588{
1589 isn_T *isn;
1590
Bram Moolenaar080457c2020-03-03 21:53:32 +01001591 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001592 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1593 return FAIL;
1594 isn->isn_arg.string = vim_strsave(line);
1595 return OK;
1596}
1597
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001598 static int
1599generate_EXECCONCAT(cctx_T *cctx, int count)
1600{
1601 isn_T *isn;
1602
1603 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1604 return FAIL;
1605 isn->isn_arg.number = count;
1606 return OK;
1607}
1608
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609/*
1610 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001611 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001612 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001613 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001614reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1615{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001616 lvar_T *lvar;
1617
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001618 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001619 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001620 emsg_namelen(_(e_str_is_used_as_argument), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001621 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001622 }
1623
1624 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001625 return NULL;
1626 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001627
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001628 // Every local variable uses the next entry on the stack. We could re-use
1629 // the last ones when leaving a scope, but then variables used in a closure
1630 // might get overwritten. To keep things simple do not re-use stack
1631 // entries. This is less efficient, but memory is cheap these days.
1632 lvar->lv_idx = cctx->ctx_locals_count++;
1633
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001634 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001635 lvar->lv_const = isConst;
1636 lvar->lv_type = type;
1637
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001638 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001639}
1640
1641/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001642 * Remove local variables above "new_top".
1643 */
1644 static void
1645unwind_locals(cctx_T *cctx, int new_top)
1646{
1647 if (cctx->ctx_locals.ga_len > new_top)
1648 {
1649 int idx;
1650 lvar_T *lvar;
1651
1652 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1653 {
1654 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1655 vim_free(lvar->lv_name);
1656 }
1657 }
1658 cctx->ctx_locals.ga_len = new_top;
1659}
1660
1661/*
1662 * Free all local variables.
1663 */
1664 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001665free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001666{
1667 unwind_locals(cctx, 0);
1668 ga_clear(&cctx->ctx_locals);
1669}
1670
1671/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001672 * Find "name" in script-local items of script "sid".
1673 * Returns the index in "sn_var_vals" if found.
1674 * If found but not in "sn_var_vals" returns -1.
1675 * If not found returns -2.
1676 */
1677 int
1678get_script_item_idx(int sid, char_u *name, int check_writable)
1679{
1680 hashtab_T *ht;
1681 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001682 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001683 int idx;
1684
1685 // First look the name up in the hashtable.
Bram Moolenaare3d46852020-08-29 13:39:17 +02001686 if (!SCRIPT_ID_VALID(sid))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001687 return -1;
1688 ht = &SCRIPT_VARS(sid);
1689 di = find_var_in_ht(ht, 0, name, TRUE);
1690 if (di == NULL)
1691 return -2;
1692
1693 // Now find the svar_T index in sn_var_vals.
1694 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1695 {
1696 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1697
1698 if (sv->sv_tv == &di->di_tv)
1699 {
1700 if (check_writable && sv->sv_const)
1701 semsg(_(e_readonlyvar), name);
1702 return idx;
1703 }
1704 }
1705 return -1;
1706}
1707
1708/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02001709 * Find "name" in imported items of the current script or in "cctx" if not
1710 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001711 */
1712 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001713find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001714{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001715 int idx;
1716
Bram Moolenaare3d46852020-08-29 13:39:17 +02001717 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02001718 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001719 if (cctx != NULL)
1720 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1721 {
1722 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
1723 + idx;
1724
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001725 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1726 : STRLEN(import->imp_name) == len
1727 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001728 return import;
1729 }
1730
Bram Moolenaarefa94442020-08-08 22:16:00 +02001731 return find_imported_in_script(name, len, current_sctx.sc_sid);
1732}
1733
1734 imported_T *
1735find_imported_in_script(char_u *name, size_t len, int sid)
1736{
Bram Moolenaare3d46852020-08-29 13:39:17 +02001737 scriptitem_T *si;
Bram Moolenaarefa94442020-08-08 22:16:00 +02001738 int idx;
1739
Bram Moolenaare3d46852020-08-29 13:39:17 +02001740 if (!SCRIPT_ID_VALID(sid))
1741 return NULL;
1742 si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001743 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1744 {
1745 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
1746
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001747 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1748 : STRLEN(import->imp_name) == len
1749 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001750 return import;
1751 }
1752 return NULL;
1753}
1754
1755/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001756 * Free all imported variables.
1757 */
1758 static void
1759free_imported(cctx_T *cctx)
1760{
1761 int idx;
1762
1763 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1764 {
1765 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
1766
1767 vim_free(import->imp_name);
1768 }
1769 ga_clear(&cctx->ctx_imports);
1770}
1771
1772/*
Bram Moolenaar23c55272020-06-21 16:58:13 +02001773 * Return TRUE if "p" points at a "#" but not at "#{".
1774 */
Bram Moolenaar75783bd2020-07-19 14:41:58 +02001775 int
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001776vim9_comment_start(char_u *p)
Bram Moolenaar23c55272020-06-21 16:58:13 +02001777{
1778 return p[0] == '#' && p[1] != '{';
1779}
1780
1781/*
1782 * Return a pointer to the next line that isn't empty or only contains a
1783 * comment. Skips over white space.
1784 * Returns NULL if there is none.
1785 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02001786 char_u *
1787peek_next_line_from_context(cctx_T *cctx)
Bram Moolenaar23c55272020-06-21 16:58:13 +02001788{
1789 int lnum = cctx->ctx_lnum;
1790
1791 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
1792 {
1793 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02001794 char_u *p;
Bram Moolenaar23c55272020-06-21 16:58:13 +02001795
Bram Moolenaarba60cc42020-08-12 19:15:33 +02001796 // ignore NULLs inserted for continuation lines
1797 if (line != NULL)
1798 {
1799 p = skipwhite(line);
1800 if (*p != NUL && !vim9_comment_start(p))
1801 return p;
1802 }
Bram Moolenaar23c55272020-06-21 16:58:13 +02001803 }
1804 return NULL;
1805}
1806
1807/*
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02001808 * Called when checking for a following operator at "arg". When the rest of
1809 * the line is empty or only a comment, peek the next line. If there is a next
1810 * line return a pointer to it and set "nextp".
1811 * Otherwise skip over white space.
1812 */
1813 static char_u *
1814may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
1815{
1816 char_u *p = skipwhite(arg);
1817
1818 *nextp = NULL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001819 if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02001820 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02001821 *nextp = peek_next_line_from_context(cctx);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02001822 if (*nextp != NULL)
1823 return *nextp;
1824 }
1825 return p;
1826}
1827
1828/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02001829 * Get the next line of the function from "cctx".
Bram Moolenaar23c55272020-06-21 16:58:13 +02001830 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
Bram Moolenaare6085c52020-04-12 20:19:16 +02001831 * Returns NULL when at the end.
1832 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02001833 char_u *
Bram Moolenaar23c55272020-06-21 16:58:13 +02001834next_line_from_context(cctx_T *cctx, int skip_comment)
Bram Moolenaare6085c52020-04-12 20:19:16 +02001835{
Bram Moolenaar7a092242020-04-16 22:10:49 +02001836 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02001837
1838 do
1839 {
1840 ++cctx->ctx_lnum;
1841 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02001842 {
1843 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02001844 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02001845 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02001846 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02001847 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02001848 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar23c55272020-06-21 16:58:13 +02001849 } while (line == NULL || *skipwhite(line) == NUL
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02001850 || (skip_comment && vim9_comment_start(skipwhite(line))));
Bram Moolenaare6085c52020-04-12 20:19:16 +02001851 return line;
1852}
1853
1854/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02001855 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02001856 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02001857 * Return FAIL if beyond the last line, "*arg" is unmodified then.
1858 */
1859 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02001860may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02001861{
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001862 if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02001863 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02001864 char_u *next = next_line_from_context(cctx, TRUE);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02001865
1866 if (next == NULL)
1867 return FAIL;
1868 *arg = skipwhite(next);
1869 }
1870 return OK;
1871}
1872
Bram Moolenaara7eedf32020-07-10 21:50:41 +02001873/*
1874 * Idem, and give an error when failed.
1875 */
1876 static int
1877may_get_next_line_error(char_u *whitep, char_u **arg, cctx_T *cctx)
1878{
1879 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1880 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001881 emsg(_(e_line_incomplete));
Bram Moolenaara7eedf32020-07-10 21:50:41 +02001882 return FAIL;
1883 }
1884 return OK;
1885}
1886
1887
Bram Moolenaara5565e42020-05-09 15:44:01 +02001888// Structure passed between the compile_expr* functions to keep track of
1889// constants that have been parsed but for which no code was produced yet. If
1890// possible expressions on these constants are applied at compile time. If
1891// that is not possible, the code to push the constants needs to be generated
1892// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02001893// Using 50 should be more than enough of 5 levels of ().
1894#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02001895typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02001896 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02001897 int pp_used; // active entries in pp_tv[]
1898} ppconst_T;
1899
Bram Moolenaar1c747212020-05-09 18:28:34 +02001900static int compile_expr0(char_u **arg, cctx_T *cctx);
1901static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
1902
Bram Moolenaara5565e42020-05-09 15:44:01 +02001903/*
1904 * Generate a PUSH instruction for "tv".
1905 * "tv" will be consumed or cleared.
1906 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
1907 */
1908 static int
1909generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
1910{
1911 if (tv != NULL)
1912 {
1913 switch (tv->v_type)
1914 {
1915 case VAR_UNKNOWN:
1916 break;
1917 case VAR_BOOL:
1918 generate_PUSHBOOL(cctx, tv->vval.v_number);
1919 break;
1920 case VAR_SPECIAL:
1921 generate_PUSHSPEC(cctx, tv->vval.v_number);
1922 break;
1923 case VAR_NUMBER:
1924 generate_PUSHNR(cctx, tv->vval.v_number);
1925 break;
1926#ifdef FEAT_FLOAT
1927 case VAR_FLOAT:
1928 generate_PUSHF(cctx, tv->vval.v_float);
1929 break;
1930#endif
1931 case VAR_BLOB:
1932 generate_PUSHBLOB(cctx, tv->vval.v_blob);
1933 tv->vval.v_blob = NULL;
1934 break;
1935 case VAR_STRING:
1936 generate_PUSHS(cctx, tv->vval.v_string);
1937 tv->vval.v_string = NULL;
1938 break;
1939 default:
1940 iemsg("constant type not supported");
1941 clear_tv(tv);
1942 return FAIL;
1943 }
1944 tv->v_type = VAR_UNKNOWN;
1945 }
1946 return OK;
1947}
1948
1949/*
1950 * Generate code for any ppconst entries.
1951 */
1952 static int
1953generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
1954{
1955 int i;
1956 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02001957 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02001958
Bram Moolenaar9b68c822020-06-18 19:31:08 +02001959 cctx->ctx_skip = SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02001960 for (i = 0; i < ppconst->pp_used; ++i)
1961 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
1962 ret = FAIL;
1963 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02001964 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02001965 return ret;
1966}
1967
1968/*
1969 * Clear ppconst constants. Used when failing.
1970 */
1971 static void
1972clear_ppconst(ppconst_T *ppconst)
1973{
1974 int i;
1975
1976 for (i = 0; i < ppconst->pp_used; ++i)
1977 clear_tv(&ppconst->pp_tv[i]);
1978 ppconst->pp_used = 0;
1979}
1980
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02001981/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001982 * Generate an instruction to load script-local variable "name", without the
1983 * leading "s:".
1984 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001985 */
1986 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001987compile_load_scriptvar(
1988 cctx_T *cctx,
1989 char_u *name, // variable NUL terminated
1990 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001991 char_u **end, // end of variable
1992 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001993{
Bram Moolenaare3d46852020-08-29 13:39:17 +02001994 scriptitem_T *si;
1995 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001996 imported_T *import;
1997
Bram Moolenaare3d46852020-08-29 13:39:17 +02001998 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
1999 return FAIL;
2000 si = SCRIPT_ITEM(current_sctx.sc_sid);
2001 idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002002 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002003 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002004 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002005 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2006 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002007 }
2008 if (idx >= 0)
2009 {
2010 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2011
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002012 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002013 current_sctx.sc_sid, idx, sv->sv_type);
2014 return OK;
2015 }
2016
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002017 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002018 if (import != NULL)
2019 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002020 if (import->imp_all)
2021 {
2022 char_u *p = skipwhite(*end);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002023 char_u *exp_name;
2024 int cc;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002025 ufunc_T *ufunc;
2026 type_T *type;
2027
2028 // Used "import * as Name", need to lookup the member.
2029 if (*p != '.')
2030 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002031 semsg(_(e_expected_dot_after_name_str), start);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002032 return FAIL;
2033 }
2034 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002035 if (VIM_ISWHITE(*p))
2036 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002037 emsg(_(e_no_white_space_allowed_after_dot));
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002038 return FAIL;
2039 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002040
Bram Moolenaar1c991142020-07-04 13:15:31 +02002041 // isolate one name
2042 exp_name = p;
2043 while (eval_isnamec(*p))
2044 ++p;
2045 cc = *p;
2046 *p = NUL;
2047
2048 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type);
2049 *p = cc;
2050 p = skipwhite(p);
2051
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002052 // TODO: what if it is a function?
2053 if (idx < 0)
2054 return FAIL;
2055 *end = p;
2056
2057 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2058 import->imp_sid,
2059 idx,
2060 type);
2061 }
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002062 else if (import->imp_funcname != NULL)
2063 generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002064 else
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002065 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2066 import->imp_sid,
2067 import->imp_var_vals_idx,
2068 import->imp_type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002069 return OK;
2070 }
2071
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002072 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002073 semsg(_(e_item_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002074 return FAIL;
2075}
2076
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002077 static int
2078generate_funcref(cctx_T *cctx, char_u *name)
2079{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002080 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002081
2082 if (ufunc == NULL)
2083 return FAIL;
2084
Bram Moolenaarb8070e32020-07-23 20:56:04 +02002085 // Need to compile any default values to get the argument types.
2086 if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
2087 if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
2088 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002089 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002090}
2091
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002092/*
2093 * Compile a variable name into a load instruction.
2094 * "end" points to just after the name.
2095 * When "error" is FALSE do not give an error when not found.
2096 */
2097 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002098compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002099{
2100 type_T *type;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002101 char_u *name = NULL;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002102 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002103 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002104 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002105
2106 if (*(*arg + 1) == ':')
2107 {
2108 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002109 if (end <= *arg + 2)
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002110 {
2111 isntype_T isn_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002112
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002113 switch (**arg)
2114 {
2115 case 'g': isn_type = ISN_LOADGDICT; break;
2116 case 'w': isn_type = ISN_LOADWDICT; break;
2117 case 't': isn_type = ISN_LOADTDICT; break;
2118 case 'b': isn_type = ISN_LOADBDICT; break;
2119 default:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002120 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002121 goto theend;
2122 }
2123 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
2124 goto theend;
2125 res = OK;
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002126 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002127 else
2128 {
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002129 isntype_T isn_type = ISN_DROP;
2130
2131 name = vim_strnsave(*arg + 2, end - (*arg + 2));
2132 if (name == NULL)
2133 return FAIL;
2134
2135 switch (**arg)
2136 {
2137 case 'v': res = generate_LOADV(cctx, name, error);
2138 break;
2139 case 's': res = compile_load_scriptvar(cctx, name,
2140 NULL, NULL, error);
2141 break;
2142 case 'g': isn_type = ISN_LOADG; break;
2143 case 'w': isn_type = ISN_LOADW; break;
2144 case 't': isn_type = ISN_LOADT; break;
2145 case 'b': isn_type = ISN_LOADB; break;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002146 default: semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002147 goto theend;
2148 }
2149 if (isn_type != ISN_DROP)
2150 {
2151 // Global, Buffer-local, Window-local and Tabpage-local
2152 // variables can be defined later, thus we don't check if it
2153 // exists, give error at runtime.
2154 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
2155 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002156 }
2157 }
2158 else
2159 {
2160 size_t len = end - *arg;
2161 int idx;
2162 int gen_load = FALSE;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002163 int gen_load_outer = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002164
2165 name = vim_strnsave(*arg, end - *arg);
2166 if (name == NULL)
2167 return FAIL;
2168
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002169 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002170 {
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002171 if (!gen_load_outer)
2172 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002173 }
2174 else
2175 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002176 lvar_T *lvar = lookup_local(*arg, len, cctx);
2177
2178 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002179 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002180 type = lvar->lv_type;
2181 idx = lvar->lv_idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002182 if (lvar->lv_from_outer)
2183 gen_load_outer = TRUE;
2184 else
2185 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002186 }
2187 else
2188 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02002189 // "var" can be script-local even without using "s:" if it
Bram Moolenaar53900992020-08-22 19:02:02 +02002190 // already exists in a Vim9 script or when it's imported.
2191 if (lookup_script(*arg, len, TRUE) == OK
2192 || find_imported(name, 0, cctx) != NULL)
2193 res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002194
Bram Moolenaara5565e42020-05-09 15:44:01 +02002195 // When the name starts with an uppercase letter or "x:" it
2196 // can be a user defined function.
Bram Moolenaar53900992020-08-22 19:02:02 +02002197 // TODO: this is just guessing
Bram Moolenaara5565e42020-05-09 15:44:01 +02002198 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2199 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002200 }
2201 }
2202 if (gen_load)
2203 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002204 if (gen_load_outer)
Bram Moolenaarfd777482020-08-12 19:42:01 +02002205 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002206 res = generate_LOAD(cctx, ISN_LOADOUTER, idx, NULL, type);
Bram Moolenaarfd777482020-08-12 19:42:01 +02002207 cctx->ctx_outer_used = TRUE;
2208 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002209 }
2210
2211 *arg = end;
2212
2213theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002214 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002215 semsg(_(e_variable_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002216 vim_free(name);
2217 return res;
2218}
2219
2220/*
2221 * Compile the argument expressions.
2222 * "arg" points to just after the "(" and is advanced to after the ")"
2223 */
2224 static int
2225compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2226{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002227 char_u *p = *arg;
2228 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002229
Bram Moolenaare6085c52020-04-12 20:19:16 +02002230 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002232 if (may_get_next_line(whitep, &p, cctx) == FAIL)
2233 goto failret;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002234 if (*p == ')')
2235 {
2236 *arg = p + 1;
2237 return OK;
2238 }
2239
Bram Moolenaara5565e42020-05-09 15:44:01 +02002240 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002241 return FAIL;
2242 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002243
2244 if (*p != ',' && *skipwhite(p) == ',')
2245 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002246 semsg(_(e_no_white_space_allowed_before_str), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002247 p = skipwhite(p);
2248 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002249 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002250 {
2251 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002252 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002253 semsg(_(e_white_space_required_after_str), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002254 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002255 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002256 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002257 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002258failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002259 emsg(_(e_missing_close));
2260 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002261}
2262
2263/*
2264 * Compile a function call: name(arg1, arg2)
2265 * "arg" points to "name", "arg + varlen" to the "(".
2266 * "argcount_init" is 1 for "value->method()"
2267 * Instructions:
2268 * EVAL arg1
2269 * EVAL arg2
2270 * BCALL / DCALL / UCALL
2271 */
2272 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02002273compile_call(
2274 char_u **arg,
2275 size_t varlen,
2276 cctx_T *cctx,
2277 ppconst_T *ppconst,
2278 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002279{
2280 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002281 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002282 int argcount = argcount_init;
2283 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002284 char_u fname_buf[FLEN_FIXED + 1];
2285 char_u *tofree = NULL;
2286 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002287 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002288 int res = FAIL;
Bram Moolenaara1773442020-08-12 15:21:22 +02002289 int is_autoload;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002290
Bram Moolenaara5565e42020-05-09 15:44:01 +02002291 // we can evaluate "has('name')" at compile time
2292 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
2293 {
2294 char_u *s = skipwhite(*arg + varlen + 1);
2295 typval_T argvars[2];
2296
2297 argvars[0].v_type = VAR_UNKNOWN;
2298 if (*s == '"')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002299 (void)eval_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002300 else if (*s == '\'')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002301 (void)eval_lit_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002302 s = skipwhite(s);
2303 if (*s == ')' && argvars[0].v_type == VAR_STRING)
2304 {
2305 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
2306
2307 *arg = s + 1;
2308 argvars[1].v_type = VAR_UNKNOWN;
2309 tv->v_type = VAR_NUMBER;
2310 tv->vval.v_number = 0;
2311 f_has(argvars, tv);
2312 clear_tv(&argvars[0]);
2313 ++ppconst->pp_used;
2314 return OK;
2315 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002316 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002317 }
2318
2319 if (generate_ppconst(cctx, ppconst) == FAIL)
2320 return FAIL;
2321
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002322 if (varlen >= sizeof(namebuf))
2323 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002324 semsg(_(e_name_too_long_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002325 return FAIL;
2326 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002327 vim_strncpy(namebuf, *arg, varlen);
2328 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002329
2330 *arg = skipwhite(*arg + varlen + 1);
2331 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002332 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002333
Bram Moolenaara1773442020-08-12 15:21:22 +02002334 is_autoload = vim_strchr(name, '#') != NULL;
2335 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002336 {
2337 int idx;
2338
2339 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002340 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002341 if (idx >= 0)
Bram Moolenaar389df252020-07-09 21:20:47 +02002342 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002343 else
2344 semsg(_(e_unknownfunc), namebuf);
2345 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002346 }
2347
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002348 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002349 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002350 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002351 {
2352 res = generate_CALL(cctx, ufunc, argcount);
2353 goto theend;
2354 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002355
2356 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002357 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaara1773442020-08-12 15:21:22 +02002358 // Not for eome#Func(), it will be loaded later.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002359 p = namebuf;
Bram Moolenaara1773442020-08-12 15:21:22 +02002360 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
Bram Moolenaara26b9702020-04-18 19:53:28 +02002361 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002362 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002363 garray_T *stack = &cctx->ctx_type_stack;
2364 type_T *type;
2365
2366 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2367 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002368 goto theend;
2369 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002370
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002371 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002372 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaara1773442020-08-12 15:21:22 +02002373 if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload)
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002374 res = generate_UCALL(cctx, name, argcount);
2375 else
2376 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002377
2378theend:
2379 vim_free(tofree);
2380 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002381}
2382
2383// like NAMESPACE_CHAR but with 'a' and 'l'.
2384#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2385
2386/*
2387 * Find the end of a variable or function name. Unlike find_name_end() this
2388 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002389 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002390 * Return a pointer to just after the name. Equal to "arg" if there is no
2391 * valid name.
2392 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002393 static char_u *
2394to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395{
2396 char_u *p;
2397
2398 // Quick check for valid starting character.
2399 if (!eval_isnamec1(*arg))
2400 return arg;
2401
2402 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2403 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2404 // and can be used in slice "[n:]".
2405 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002406 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002407 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2408 break;
2409 return p;
2410}
2411
2412/*
2413 * Like to_name_end() but also skip over a list or dict constant.
Bram Moolenaar1c991142020-07-04 13:15:31 +02002414 * This intentionally does not handle line continuation.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002415 */
2416 char_u *
2417to_name_const_end(char_u *arg)
2418{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002419 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002420 typval_T rettv;
2421
2422 if (p == arg && *arg == '[')
2423 {
2424
2425 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002426 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002427 p = arg;
2428 }
2429 else if (p == arg && *arg == '#' && arg[1] == '{')
2430 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002431 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002432 ++p;
Bram Moolenaar8ea93902020-06-27 14:11:53 +02002433 if (eval_dict(&p, &rettv, NULL, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002434 p = arg;
2435 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002436
2437 return p;
2438}
2439
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002440/*
2441 * parse a list: [expr, expr]
2442 * "*arg" points to the '['.
2443 */
2444 static int
2445compile_list(char_u **arg, cctx_T *cctx)
2446{
2447 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002448 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002449 int count = 0;
2450
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002451 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002452 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002453 if (may_get_next_line(whitep, &p, cctx) == FAIL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01002454 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002455 semsg(_(e_list_end), *arg);
2456 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002457 }
Bram Moolenaardb199212020-08-12 18:01:53 +02002458 if (*p == ',')
2459 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002460 semsg(_(e_no_white_space_allowed_before_str), ",");
Bram Moolenaardb199212020-08-12 18:01:53 +02002461 return FAIL;
2462 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002463 if (*p == ']')
2464 {
2465 ++p;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002466 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002467 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02002468 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002469 break;
2470 ++count;
2471 if (*p == ',')
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02002472 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002473 ++p;
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02002474 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
2475 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002476 semsg(_(e_white_space_required_after_str), ",");
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02002477 return FAIL;
2478 }
2479 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002480 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002481 p = skipwhite(p);
2482 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002483 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002484
2485 generate_NEWLIST(cctx, count);
2486 return OK;
2487}
2488
2489/*
2490 * parse a lambda: {arg, arg -> expr}
2491 * "*arg" points to the '{'.
2492 */
2493 static int
2494compile_lambda(char_u **arg, cctx_T *cctx)
2495{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002496 typval_T rettv;
2497 ufunc_T *ufunc;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002498 evalarg_T evalarg;
2499
2500 CLEAR_FIELD(evalarg);
2501 evalarg.eval_flags = EVAL_EVALUATE;
2502 evalarg.eval_cctx = cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002503
2504 // Get the funcref in "rettv".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002505 if (get_lambda_tv(arg, &rettv, &evalarg) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002506 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002507
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002508 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002509 ++ufunc->uf_refcount;
2510 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002511 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002512
2513 // The function will have one line: "return {expr}".
2514 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002515 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002516
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02002517 clear_evalarg(&evalarg, NULL);
2518
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02002519 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar5a849da2020-08-08 16:47:30 +02002520 {
2521 // The return type will now be known.
2522 set_function_type(ufunc);
2523
2524 return generate_FUNCREF(cctx, ufunc);
2525 }
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002526
2527 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002528 return FAIL;
2529}
2530
2531/*
2532 * Compile a lamda call: expr->{lambda}(args)
2533 * "arg" points to the "{".
2534 */
2535 static int
2536compile_lambda_call(char_u **arg, cctx_T *cctx)
2537{
2538 ufunc_T *ufunc;
2539 typval_T rettv;
2540 int argcount = 1;
2541 int ret = FAIL;
2542
2543 // Get the funcref in "rettv".
Bram Moolenaare40fbc22020-06-27 18:06:45 +02002544 if (get_lambda_tv(arg, &rettv, &EVALARG_EVALUATE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002545 return FAIL;
2546
2547 if (**arg != '(')
2548 {
2549 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002550 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002551 else
2552 semsg(_(e_missing_paren), "lambda");
2553 clear_tv(&rettv);
2554 return FAIL;
2555 }
2556
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002557 ufunc = rettv.vval.v_partial->pt_func;
2558 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002559 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002560 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002561
2562 // The function will have one line: "return {expr}".
2563 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002564 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002565
2566 // compile the arguments
2567 *arg = skipwhite(*arg + 1);
2568 if (compile_arguments(arg, cctx, &argcount) == OK)
2569 // call the compiled function
2570 ret = generate_CALL(cctx, ufunc, argcount);
2571
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002572 if (ret == FAIL)
2573 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002574 return ret;
2575}
2576
2577/*
2578 * parse a dict: {'key': val} or #{key: val}
2579 * "*arg" points to the '{'.
2580 */
2581 static int
2582compile_dict(char_u **arg, cctx_T *cctx, int literal)
2583{
2584 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaarf1a23682020-07-13 18:55:48 +02002585 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002586 int count = 0;
2587 dict_T *d = dict_alloc();
2588 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002589 char_u *whitep = *arg;
2590 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002591
2592 if (d == NULL)
2593 return FAIL;
2594 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002595 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002596 {
2597 char_u *key = NULL;
2598
Bram Moolenaar23c55272020-06-21 16:58:13 +02002599 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002600 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002601 *arg = NULL;
2602 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002603 }
2604
2605 if (**arg == '}')
2606 break;
2607
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002608 if (literal)
2609 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002610 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002611
Bram Moolenaar2c330432020-04-13 14:41:35 +02002612 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002613 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002614 semsg(_(e_invalid_key_str), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002615 return FAIL;
2616 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002617 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002618 if (generate_PUSHS(cctx, key) == FAIL)
2619 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002620 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002621 }
2622 else
2623 {
2624 isn_T *isn;
2625
Bram Moolenaara5565e42020-05-09 15:44:01 +02002626 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002627 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002628 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2629 if (isn->isn_type == ISN_PUSHS)
2630 key = isn->isn_arg.string;
Bram Moolenaarf1a23682020-07-13 18:55:48 +02002631 else
2632 {
2633 type_T *keytype = ((type_T **)stack->ga_data)
2634 [stack->ga_len - 1];
2635 if (need_type(keytype, &t_string, -1, cctx, FALSE) == FAIL)
2636 return FAIL;
2637 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002638 }
2639
2640 // Check for duplicate keys, if using string keys.
2641 if (key != NULL)
2642 {
2643 item = dict_find(d, key, -1);
2644 if (item != NULL)
2645 {
2646 semsg(_(e_duplicate_key), key);
2647 goto failret;
2648 }
2649 item = dictitem_alloc(key);
2650 if (item != NULL)
2651 {
2652 item->di_tv.v_type = VAR_UNKNOWN;
2653 item->di_tv.v_lock = 0;
2654 if (dict_add(d, item) == FAIL)
2655 dictitem_free(item);
2656 }
2657 }
2658
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002659 if (**arg != ':')
2660 {
Bram Moolenaar17a836c2020-08-12 17:35:58 +02002661 if (*skipwhite(*arg) == ':')
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002662 semsg(_(e_no_white_space_allowed_before_str), ":");
Bram Moolenaar17a836c2020-08-12 17:35:58 +02002663 else
2664 semsg(_(e_missing_dict_colon), *arg);
2665 return FAIL;
2666 }
2667 whitep = *arg + 1;
2668 if (!IS_WHITE_OR_NUL(*whitep))
2669 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002670 semsg(_(e_white_space_required_after_str), ":");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002671 return FAIL;
2672 }
2673
2674 *arg = skipwhite(*arg + 1);
Bram Moolenaar23c55272020-06-21 16:58:13 +02002675 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002676 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002677 *arg = NULL;
2678 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002679 }
2680
Bram Moolenaara5565e42020-05-09 15:44:01 +02002681 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002682 return FAIL;
2683 ++count;
2684
Bram Moolenaar2c330432020-04-13 14:41:35 +02002685 whitep = *arg;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002686 *arg = skipwhite(*arg);
2687 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002688 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002689 *arg = NULL;
2690 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002691 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002692 if (**arg == '}')
2693 break;
2694 if (**arg != ',')
2695 {
2696 semsg(_(e_missing_dict_comma), *arg);
2697 goto failret;
2698 }
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02002699 if (IS_WHITE_OR_NUL(*whitep))
2700 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02002701 semsg(_(e_no_white_space_allowed_before_str), ",");
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02002702 return FAIL;
2703 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002704 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002705 *arg = skipwhite(*arg + 1);
2706 }
2707
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002708 *arg = *arg + 1;
2709
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002710 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002711 p = skipwhite(*arg);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002712 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002713 *arg += STRLEN(*arg);
2714
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002715 dict_unref(d);
2716 return generate_NEWDICT(cctx, count);
2717
2718failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002719 if (*arg == NULL)
2720 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002721 dict_unref(d);
2722 return FAIL;
2723}
2724
2725/*
2726 * Compile "&option".
2727 */
2728 static int
2729compile_get_option(char_u **arg, cctx_T *cctx)
2730{
2731 typval_T rettv;
2732 char_u *start = *arg;
2733 int ret;
2734
2735 // parse the option and get the current value to get the type.
2736 rettv.v_type = VAR_UNKNOWN;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002737 ret = eval_option(arg, &rettv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002738 if (ret == OK)
2739 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002740 // include the '&' in the name, eval_option() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002741 char_u *name = vim_strnsave(start, *arg - start);
2742 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2743
2744 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2745 vim_free(name);
2746 }
2747 clear_tv(&rettv);
2748
2749 return ret;
2750}
2751
2752/*
2753 * Compile "$VAR".
2754 */
2755 static int
2756compile_get_env(char_u **arg, cctx_T *cctx)
2757{
2758 char_u *start = *arg;
2759 int len;
2760 int ret;
2761 char_u *name;
2762
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002763 ++*arg;
2764 len = get_env_len(arg);
2765 if (len == 0)
2766 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002767 semsg(_(e_syntax_error_at_str), start - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002768 return FAIL;
2769 }
2770
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002771 // include the '$' in the name, eval_env_var() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002772 name = vim_strnsave(start, len + 1);
2773 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2774 vim_free(name);
2775 return ret;
2776}
2777
2778/*
2779 * Compile "@r".
2780 */
2781 static int
2782compile_get_register(char_u **arg, cctx_T *cctx)
2783{
2784 int ret;
2785
2786 ++*arg;
2787 if (**arg == NUL)
2788 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002789 semsg(_(e_syntax_error_at_str), *arg - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002790 return FAIL;
2791 }
Bram Moolenaar7226e5b2020-08-02 17:33:26 +02002792 if (!valid_yank_reg(**arg, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002793 {
2794 emsg_invreg(**arg);
2795 return FAIL;
2796 }
2797 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2798 ++*arg;
2799 return ret;
2800}
2801
2802/*
2803 * Apply leading '!', '-' and '+' to constant "rettv".
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002804 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002805 */
2806 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002807apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002808{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002809 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002810
2811 // this works from end to start
2812 while (p > start)
2813 {
2814 --p;
2815 if (*p == '-' || *p == '+')
2816 {
2817 // only '-' has an effect, for '+' we only check the type
2818#ifdef FEAT_FLOAT
2819 if (rettv->v_type == VAR_FLOAT)
2820 {
2821 if (*p == '-')
2822 rettv->vval.v_float = -rettv->vval.v_float;
2823 }
2824 else
2825#endif
2826 {
2827 varnumber_T val;
2828 int error = FALSE;
2829
2830 // tv_get_number_chk() accepts a string, but we don't want that
2831 // here
2832 if (check_not_string(rettv) == FAIL)
2833 return FAIL;
2834 val = tv_get_number_chk(rettv, &error);
2835 clear_tv(rettv);
2836 if (error)
2837 return FAIL;
2838 if (*p == '-')
2839 val = -val;
2840 rettv->v_type = VAR_NUMBER;
2841 rettv->vval.v_number = val;
2842 }
2843 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002844 else if (numeric_only)
2845 {
2846 ++p;
2847 break;
2848 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002849 else
2850 {
2851 int v = tv2bool(rettv);
2852
2853 // '!' is permissive in the type.
2854 clear_tv(rettv);
2855 rettv->v_type = VAR_BOOL;
2856 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2857 }
2858 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002859 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002860 return OK;
2861}
2862
2863/*
2864 * Recognize v: variables that are constants and set "rettv".
2865 */
2866 static void
2867get_vim_constant(char_u **arg, typval_T *rettv)
2868{
2869 if (STRNCMP(*arg, "v:true", 6) == 0)
2870 {
2871 rettv->v_type = VAR_BOOL;
2872 rettv->vval.v_number = VVAL_TRUE;
2873 *arg += 6;
2874 }
2875 else if (STRNCMP(*arg, "v:false", 7) == 0)
2876 {
2877 rettv->v_type = VAR_BOOL;
2878 rettv->vval.v_number = VVAL_FALSE;
2879 *arg += 7;
2880 }
2881 else if (STRNCMP(*arg, "v:null", 6) == 0)
2882 {
2883 rettv->v_type = VAR_SPECIAL;
2884 rettv->vval.v_number = VVAL_NULL;
2885 *arg += 6;
2886 }
2887 else if (STRNCMP(*arg, "v:none", 6) == 0)
2888 {
2889 rettv->v_type = VAR_SPECIAL;
2890 rettv->vval.v_number = VVAL_NONE;
2891 *arg += 6;
2892 }
2893}
2894
Bram Moolenaar696ba232020-07-29 21:20:41 +02002895 exptype_T
Bram Moolenaar61a89812020-05-07 16:58:17 +02002896get_compare_type(char_u *p, int *len, int *type_is)
2897{
2898 exptype_T type = EXPR_UNKNOWN;
2899 int i;
2900
2901 switch (p[0])
2902 {
2903 case '=': if (p[1] == '=')
2904 type = EXPR_EQUAL;
2905 else if (p[1] == '~')
2906 type = EXPR_MATCH;
2907 break;
2908 case '!': if (p[1] == '=')
2909 type = EXPR_NEQUAL;
2910 else if (p[1] == '~')
2911 type = EXPR_NOMATCH;
2912 break;
2913 case '>': if (p[1] != '=')
2914 {
2915 type = EXPR_GREATER;
2916 *len = 1;
2917 }
2918 else
2919 type = EXPR_GEQUAL;
2920 break;
2921 case '<': if (p[1] != '=')
2922 {
2923 type = EXPR_SMALLER;
2924 *len = 1;
2925 }
2926 else
2927 type = EXPR_SEQUAL;
2928 break;
2929 case 'i': if (p[1] == 's')
2930 {
2931 // "is" and "isnot"; but not a prefix of a name
2932 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
2933 *len = 5;
2934 i = p[*len];
2935 if (!isalnum(i) && i != '_')
2936 {
2937 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
2938 *type_is = TRUE;
2939 }
2940 }
2941 break;
2942 }
2943 return type;
2944}
2945
2946/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002947 * Compile code to apply '-', '+' and '!'.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002948 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002949 */
2950 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002951compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002952{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002953 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002954
2955 // this works from end to start
2956 while (p > start)
2957 {
2958 --p;
2959 if (*p == '-' || *p == '+')
2960 {
2961 int negate = *p == '-';
2962 isn_T *isn;
2963
2964 // TODO: check type
2965 while (p > start && (p[-1] == '-' || p[-1] == '+'))
2966 {
2967 --p;
2968 if (*p == '-')
2969 negate = !negate;
2970 }
2971 // only '-' has an effect, for '+' we only check the type
2972 if (negate)
2973 isn = generate_instr(cctx, ISN_NEGATENR);
2974 else
2975 isn = generate_instr(cctx, ISN_CHECKNR);
2976 if (isn == NULL)
2977 return FAIL;
2978 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002979 else if (numeric_only)
2980 {
2981 ++p;
2982 break;
2983 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002984 else
2985 {
2986 int invert = TRUE;
2987
2988 while (p > start && p[-1] == '!')
2989 {
2990 --p;
2991 invert = !invert;
2992 }
2993 if (generate_2BOOL(cctx, invert) == FAIL)
2994 return FAIL;
2995 }
2996 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02002997 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002998 return OK;
2999}
3000
3001/*
3002 * Compile whatever comes after "name" or "name()".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003003 * Advances "*arg" only when something was recognized.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003004 */
3005 static int
3006compile_subscript(
3007 char_u **arg,
3008 cctx_T *cctx,
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003009 char_u *start_leader,
3010 char_u **end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003011 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003012{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003013 char_u *name_start = *end_leader;
3014
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003015 for (;;)
3016 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003017 char_u *p = skipwhite(*arg);
3018
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003019 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003020 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003021 char_u *next = peek_next_line_from_context(cctx);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003022
3023 // If a following line starts with "->{" or "->X" advance to that
3024 // line, so that a line break before "->" is allowed.
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003025 // Also if a following line starts with ".x".
3026 if (next != NULL &&
3027 ((next[0] == '-' && next[1] == '>'
3028 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003029 || (next[0] == '.' && eval_isdictc(next[1]))))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003030 {
3031 next = next_line_from_context(cctx, TRUE);
3032 if (next == NULL)
3033 return FAIL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003034 *arg = next;
3035 p = skipwhite(*arg);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003036 }
3037 }
3038
Bram Moolenaar2d6b20d2020-07-25 19:30:59 +02003039 // Do not skip over white space to find the "(", "exeucte 'x' ()" is
3040 // not a function call.
3041 if (**arg == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003042 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003043 garray_T *stack = &cctx->ctx_type_stack;
3044 type_T *type;
3045 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003046
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003047 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003048 return FAIL;
3049
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003050 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003051 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3052
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003053 *arg = skipwhite(p + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003054 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3055 return FAIL;
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003056 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003057 return FAIL;
3058 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003059 else if (*p == '-' && p[1] == '>')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003060 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003061 char_u *pstart = p;
3062
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003063 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003064 return FAIL;
3065
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003066 // something->method()
3067 // Apply the '!', '-' and '+' first:
3068 // -1.0->func() works like (-1.0)->func()
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003069 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003070 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003071
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003072 p += 2;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003073 *arg = skipwhite(p);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003074 // No line break supported right after "->".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003075 if (**arg == '{')
3076 {
3077 // lambda call: list->{lambda}
3078 if (compile_lambda_call(arg, cctx) == FAIL)
3079 return FAIL;
3080 }
3081 else
3082 {
3083 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003084 p = *arg;
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003085 if (!eval_isnamec1(*p))
3086 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003087 semsg(_(e_trailing_arg), pstart);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003088 return FAIL;
3089 }
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003090 if (ASCII_ISALPHA(*p) && p[1] == ':')
3091 p += 2;
Bram Moolenaarc5da1fb2020-08-05 15:43:44 +02003092 for ( ; eval_isnamec(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003093 ;
3094 if (*p != '(')
3095 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003096 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003097 return FAIL;
3098 }
3099 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02003100 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003101 return FAIL;
3102 }
3103 }
Bram Moolenaarbadd8482020-07-31 22:38:17 +02003104 else if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003105 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003106 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003107 type_T **typep;
Bram Moolenaar56acb092020-08-16 14:48:19 +02003108 type_T *valtype;
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003109 vartype_T vtype;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003110 int is_slice = FALSE;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003111
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003112 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003113 // dict member: dict[key]
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003114 // string index: text[123]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003115 // TODO: blob index
3116 // TODO: more arguments
3117 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003118 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003119 return FAIL;
3120
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003121 ++p;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003122 *arg = skipwhite(p);
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003123 if (may_get_next_line_error(p, arg, cctx) == FAIL)
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003124 return FAIL;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003125 if (**arg == ':')
3126 // missing first index is equal to zero
3127 generate_PUSHNR(cctx, 0);
3128 else
3129 {
3130 if (compile_expr0(arg, cctx) == FAIL)
3131 return FAIL;
3132 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3133 return FAIL;
3134 *arg = skipwhite(*arg);
3135 }
3136 if (**arg == ':')
3137 {
3138 *arg = skipwhite(*arg + 1);
3139 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3140 return FAIL;
3141 if (**arg == ']')
3142 // missing second index is equal to end of string
3143 generate_PUSHNR(cctx, -1);
3144 else
3145 {
3146 if (compile_expr0(arg, cctx) == FAIL)
3147 return FAIL;
3148 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3149 return FAIL;
3150 *arg = skipwhite(*arg);
3151 }
3152 is_slice = TRUE;
3153 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003154
3155 if (**arg != ']')
3156 {
3157 emsg(_(e_missbrac));
3158 return FAIL;
3159 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003160 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003161
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003162 // We can index a list and a dict. If we don't know the type
3163 // we can use the index value type.
3164 // TODO: If we don't know use an instruction to figure it out at
3165 // runtime.
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003166 typep = ((type_T **)stack->ga_data) + stack->ga_len
3167 - (is_slice ? 3 : 2);
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003168 vtype = (*typep)->tt_type;
Bram Moolenaar56acb092020-08-16 14:48:19 +02003169 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3170 // If the index is a string, the variable must be a Dict.
3171 if (*typep == &t_any && valtype == &t_string)
3172 vtype = VAR_DICT;
3173 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB)
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003174 {
Bram Moolenaar56acb092020-08-16 14:48:19 +02003175 if (need_type(valtype, &t_number, -1, cctx, FALSE) == FAIL)
3176 return FAIL;
3177 if (is_slice)
3178 {
3179 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2];
3180 if (need_type(valtype, &t_number, -2, cctx, FALSE) == FAIL)
3181 return FAIL;
3182 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003183 }
Bram Moolenaar56acb092020-08-16 14:48:19 +02003184
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003185 if (vtype == VAR_DICT)
3186 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003187 if (is_slice)
3188 {
3189 emsg(_(e_cannot_slice_dictionary));
3190 return FAIL;
3191 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003192 if ((*typep)->tt_type == VAR_DICT)
3193 *typep = (*typep)->tt_member;
Bram Moolenaar7892b952020-07-20 22:09:34 +02003194 else
3195 {
3196 if (need_type(*typep, &t_dict_any, -2, cctx, FALSE) == FAIL)
3197 return FAIL;
3198 *typep = &t_any;
3199 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003200 if (may_generate_2STRING(-1, cctx) == FAIL)
3201 return FAIL;
3202 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
3203 return FAIL;
3204 }
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003205 else if (vtype == VAR_STRING)
3206 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003207 *typep = &t_string;
3208 if ((is_slice
3209 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
3210 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003211 return FAIL;
3212 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003213 else if (vtype == VAR_BLOB)
3214 {
3215 emsg("Sorry, blob index and slice not implemented yet");
3216 return FAIL;
3217 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003218 else if (vtype == VAR_LIST || *typep == &t_any)
Bram Moolenaarb13af502020-02-17 21:12:08 +01003219 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003220 if (is_slice)
3221 {
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003222 if (generate_instr_drop(cctx,
3223 vtype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
3224 2) == FAIL)
Bram Moolenaared591872020-08-15 22:14:53 +02003225 return FAIL;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003226 }
Bram Moolenaared591872020-08-15 22:14:53 +02003227 else
3228 {
3229 if ((*typep)->tt_type == VAR_LIST)
3230 *typep = (*typep)->tt_member;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003231 if (generate_instr_drop(cctx,
3232 vtype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX,
3233 1) == FAIL)
Bram Moolenaared591872020-08-15 22:14:53 +02003234 return FAIL;
3235 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003236 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003237 else
3238 {
Bram Moolenaar56acb092020-08-16 14:48:19 +02003239 emsg(_(e_string_list_dict_or_blob_required));
Bram Moolenaarb13af502020-02-17 21:12:08 +01003240 return FAIL;
3241 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003242 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003243 else if (*p == '.' && p[1] != '.')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003244 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003245 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003246 return FAIL;
3247
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003248 *arg = p + 1;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003249 if (may_get_next_line(*arg, arg, cctx) == FAIL)
3250 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003251 // dictionary member: dict.name
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003252 p = *arg;
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003253 if (eval_isdictc(*p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003254 while (eval_isnamec(*p))
3255 MB_PTR_ADV(p);
3256 if (p == *arg)
3257 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003258 semsg(_(e_syntax_error_at_str), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003259 return FAIL;
3260 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003261 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003262 return FAIL;
3263 *arg = p;
3264 }
3265 else
3266 break;
3267 }
3268
3269 // TODO - see handle_subscript():
3270 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3271 // Don't do this when "Func" is already a partial that was bound
3272 // explicitly (pt_auto is FALSE).
3273
3274 return OK;
3275}
3276
3277/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003278 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
3279 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003280 *
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003281 * If the value is a constant "ppconst->pp_ret" will be set.
3282 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003283 *
3284 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003285 */
3286
3287/*
3288 * number number constant
3289 * 0zFFFFFFFF Blob constant
3290 * "string" string constant
3291 * 'string' literal string constant
3292 * &option-name option value
3293 * @r register contents
3294 * identifier variable value
3295 * function() function call
3296 * $VAR environment variable
3297 * (expression) nested expression
3298 * [expr, expr] List
3299 * {key: val, key: val} Dictionary
3300 * #{key: val, key: val} Dictionary with literal keys
3301 *
3302 * Also handle:
3303 * ! in front logical NOT
3304 * - in front unary minus
3305 * + in front unary plus (ignored)
3306 * trailing (arg) funcref/partial call
3307 * trailing [] subscript in String or List
3308 * trailing .name entry in Dictionary
3309 * trailing ->name() method call
3310 */
3311 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003312compile_expr7(
3313 char_u **arg,
3314 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003315 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003316{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003317 char_u *start_leader, *end_leader;
3318 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003319 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02003320 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003321
3322 /*
3323 * Skip '!', '-' and '+' characters. They are handled later.
3324 */
3325 start_leader = *arg;
3326 while (**arg == '!' || **arg == '-' || **arg == '+')
3327 *arg = skipwhite(*arg + 1);
3328 end_leader = *arg;
3329
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003330 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003331 switch (**arg)
3332 {
3333 /*
3334 * Number constant.
3335 */
3336 case '0': // also for blob starting with 0z
3337 case '1':
3338 case '2':
3339 case '3':
3340 case '4':
3341 case '5':
3342 case '6':
3343 case '7':
3344 case '8':
3345 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003346 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003347 return FAIL;
Bram Moolenaar4301a722020-08-11 20:51:08 +02003348 // Apply "-" and "+" just before the number now, right to
3349 // left. Matters especially when "->" follows. Stops at
3350 // '!'.
3351 if (apply_leader(rettv, TRUE,
3352 start_leader, &end_leader) == FAIL)
3353 {
3354 clear_tv(rettv);
3355 return FAIL;
3356 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003357 break;
3358
3359 /*
3360 * String constant: "string".
3361 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003362 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003363 return FAIL;
3364 break;
3365
3366 /*
3367 * Literal string constant: 'str''ing'.
3368 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003369 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003370 return FAIL;
3371 break;
3372
3373 /*
3374 * Constant Vim variable.
3375 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003376 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003377 ret = NOTDONE;
3378 break;
3379
3380 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02003381 * "true" constant
3382 */
3383 case 't': if (STRNCMP(*arg, "true", 4) == 0
3384 && !eval_isnamec((*arg)[4]))
3385 {
3386 *arg += 4;
3387 rettv->v_type = VAR_BOOL;
3388 rettv->vval.v_number = VVAL_TRUE;
3389 }
3390 else
3391 ret = NOTDONE;
3392 break;
3393
3394 /*
3395 * "false" constant
3396 */
3397 case 'f': if (STRNCMP(*arg, "false", 5) == 0
3398 && !eval_isnamec((*arg)[5]))
3399 {
3400 *arg += 5;
3401 rettv->v_type = VAR_BOOL;
3402 rettv->vval.v_number = VVAL_FALSE;
3403 }
3404 else
3405 ret = NOTDONE;
3406 break;
3407
3408 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003409 * List: [expr, expr]
3410 */
3411 case '[': ret = compile_list(arg, cctx);
3412 break;
3413
3414 /*
3415 * Dictionary: #{key: val, key: val}
3416 */
3417 case '#': if ((*arg)[1] == '{')
3418 {
3419 ++*arg;
3420 ret = compile_dict(arg, cctx, TRUE);
3421 }
3422 else
3423 ret = NOTDONE;
3424 break;
3425
3426 /*
3427 * Lambda: {arg, arg -> expr}
3428 * Dictionary: {'key': val, 'key': val}
3429 */
3430 case '{': {
3431 char_u *start = skipwhite(*arg + 1);
3432
3433 // Find out what comes after the arguments.
3434 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003435 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003436 if (ret != FAIL && *start == '>')
3437 ret = compile_lambda(arg, cctx);
3438 else
3439 ret = compile_dict(arg, cctx, FALSE);
3440 }
3441 break;
3442
3443 /*
3444 * Option value: &name
3445 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02003446 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
3447 return FAIL;
3448 ret = compile_get_option(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003449 break;
3450
3451 /*
3452 * Environment variable: $VAR.
3453 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02003454 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
3455 return FAIL;
3456 ret = compile_get_env(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003457 break;
3458
3459 /*
3460 * Register contents: @r.
3461 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02003462 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
3463 return FAIL;
3464 ret = compile_get_register(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003465 break;
3466 /*
3467 * nested expression: (expression).
3468 */
3469 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaar1c747212020-05-09 18:28:34 +02003470
3471 // recursive!
3472 if (ppconst->pp_used <= PPSIZE - 10)
3473 {
3474 ret = compile_expr1(arg, cctx, ppconst);
3475 }
3476 else
3477 {
3478 // Not enough space in ppconst, flush constants.
3479 if (generate_ppconst(cctx, ppconst) == FAIL)
3480 return FAIL;
3481 ret = compile_expr0(arg, cctx);
3482 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003483 *arg = skipwhite(*arg);
3484 if (**arg == ')')
3485 ++*arg;
3486 else if (ret == OK)
3487 {
3488 emsg(_(e_missing_close));
3489 ret = FAIL;
3490 }
3491 break;
3492
3493 default: ret = NOTDONE;
3494 break;
3495 }
3496 if (ret == FAIL)
3497 return FAIL;
3498
Bram Moolenaar1c747212020-05-09 18:28:34 +02003499 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003500 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02003501 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaara5565e42020-05-09 15:44:01 +02003502 clear_tv(rettv);
3503 else
3504 // A constant expression can possibly be handled compile time,
3505 // return the value instead of generating code.
3506 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003507 }
3508 else if (ret == NOTDONE)
3509 {
3510 char_u *p;
3511 int r;
3512
3513 if (!eval_isnamec1(**arg))
3514 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003515 semsg(_(e_name_expected), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003516 return FAIL;
3517 }
3518
3519 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003520 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003521 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02003522 {
3523 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
3524 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003525 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02003526 {
3527 if (generate_ppconst(cctx, ppconst) == FAIL)
3528 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003529 r = compile_load(arg, p, cctx, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003530 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003531 if (r == FAIL)
3532 return FAIL;
3533 }
3534
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003535 // Handle following "[]", ".member", etc.
3536 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003537 if (compile_subscript(arg, cctx, start_leader, &end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02003538 ppconst) == FAIL)
3539 return FAIL;
3540 if (ppconst->pp_used > 0)
3541 {
3542 // apply the '!', '-' and '+' before the constant
3543 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003544 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02003545 return FAIL;
3546 return OK;
3547 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003548 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003549 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003550 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003551}
3552
3553/*
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02003554 * Give the "white on both sides" error, taking the operator from "p[len]".
3555 */
3556 void
3557error_white_both(char_u *op, int len)
3558{
3559 char_u buf[10];
3560
3561 vim_strncpy(buf, op, len);
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02003562 semsg(_(e_white_space_required_before_and_after_str), buf);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02003563}
3564
3565/*
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003566 * <type>expr7: runtime type check / conversion
3567 */
3568 static int
3569compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3570{
3571 type_T *want_type = NULL;
3572
3573 // Recognize <type>
3574 if (**arg == '<' && eval_isnamec1((*arg)[1]))
3575 {
3576 int called_emsg_before = called_emsg;
3577
3578 ++*arg;
3579 want_type = parse_type(arg, cctx->ctx_type_list);
3580 if (called_emsg != called_emsg_before)
3581 return FAIL;
3582
3583 if (**arg != '>')
3584 {
3585 if (*skipwhite(*arg) == '>')
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02003586 semsg(_(e_no_white_space_allowed_before_str), ">");
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003587 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003588 emsg(_(e_missing_gt));
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003589 return FAIL;
3590 }
3591 ++*arg;
3592 if (may_get_next_line_error(*arg - 1, arg, cctx) == FAIL)
3593 return FAIL;
3594 }
3595
3596 if (compile_expr7(arg, cctx, ppconst) == FAIL)
3597 return FAIL;
3598
3599 if (want_type != NULL)
3600 {
3601 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaard1103582020-08-14 22:44:25 +02003602 type_T *actual;
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003603
Bram Moolenaard1103582020-08-14 22:44:25 +02003604 generate_ppconst(cctx, ppconst);
3605 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar8b565c22020-08-30 23:24:20 +02003606 if (check_type(want_type, actual, FALSE, 0) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003607 {
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003608 if (need_type(actual, want_type, -1, cctx, FALSE) == FAIL)
3609 return FAIL;
3610 }
3611 }
3612
3613 return OK;
3614}
3615
3616/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003617 * * number multiplication
3618 * / number division
3619 * % number modulo
3620 */
3621 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003622compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003623{
3624 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003625 char_u *next;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003626 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003627
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003628 // get the first expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003629 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003630 return FAIL;
3631
3632 /*
3633 * Repeat computing, until no "*", "/" or "%" is following.
3634 */
3635 for (;;)
3636 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003637 op = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003638 if (*op != '*' && *op != '/' && *op != '%')
3639 break;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003640 if (next != NULL)
3641 {
3642 *arg = next_line_from_context(cctx, TRUE);
3643 op = skipwhite(*arg);
3644 }
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003645
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003646 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003647 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02003648 error_white_both(op, 1);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003649 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003650 }
3651 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003652 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003653 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003654
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003655 // get the second expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02003656 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003657 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003658
3659 if (ppconst->pp_used == ppconst_used + 2
3660 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3661 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003662 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003663 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3664 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003665 varnumber_T res = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003666
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003667 // both are numbers: compute the result
3668 switch (*op)
3669 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003670 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003671 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003672 case '/': res = tv1->vval.v_number / tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003673 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003674 case '%': res = tv1->vval.v_number % tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003675 break;
3676 }
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003677 tv1->vval.v_number = res;
3678 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003679 }
3680 else
3681 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003682 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003683 generate_two_op(cctx, op);
3684 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003685 }
3686
3687 return OK;
3688}
3689
3690/*
3691 * + number addition
3692 * - number subtraction
3693 * .. string concatenation
3694 */
3695 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003696compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003697{
3698 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003699 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003700 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003701 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003702
3703 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02003704 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003705 return FAIL;
3706
3707 /*
3708 * Repeat computing, until no "+", "-" or ".." is following.
3709 */
3710 for (;;)
3711 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003712 op = may_peek_next_line(cctx, *arg, &next);
3713 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003714 break;
3715 oplen = (*op == '.' ? 2 : 1);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003716 if (next != NULL)
3717 {
3718 *arg = next_line_from_context(cctx, TRUE);
3719 op = skipwhite(*arg);
3720 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003721
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003722 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003723 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02003724 error_white_both(op, oplen);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003725 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003726 }
3727
3728 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003729 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003730 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003731
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003732 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02003733 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003734 return FAIL;
3735
Bram Moolenaara5565e42020-05-09 15:44:01 +02003736 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003737 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02003738 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
3739 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
3740 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3741 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003742 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003743 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3744 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003745
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003746 // concat/subtract/add constant numbers
3747 if (*op == '+')
3748 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
3749 else if (*op == '-')
3750 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
3751 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003752 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003753 // concatenate constant strings
3754 char_u *s1 = tv1->vval.v_string;
3755 char_u *s2 = tv2->vval.v_string;
3756 size_t len1 = STRLEN(s1);
3757
3758 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
3759 if (tv1->vval.v_string == NULL)
3760 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003761 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003762 return FAIL;
3763 }
3764 mch_memmove(tv1->vval.v_string, s1, len1);
3765 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003766 vim_free(s1);
3767 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003768 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003769 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003770 }
3771 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003772 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003773 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003774 if (*op == '.')
3775 {
3776 if (may_generate_2STRING(-2, cctx) == FAIL
3777 || may_generate_2STRING(-1, cctx) == FAIL)
3778 return FAIL;
3779 generate_instr_drop(cctx, ISN_CONCAT, 1);
3780 }
3781 else
3782 generate_two_op(cctx, op);
3783 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003784 }
3785
3786 return OK;
3787}
3788
3789/*
3790 * expr5a == expr5b
3791 * expr5a =~ expr5b
3792 * expr5a != expr5b
3793 * expr5a !~ expr5b
3794 * expr5a > expr5b
3795 * expr5a >= expr5b
3796 * expr5a < expr5b
3797 * expr5a <= expr5b
3798 * expr5a is expr5b
3799 * expr5a isnot expr5b
3800 *
3801 * Produces instructions:
3802 * EVAL expr5a Push result of "expr5a"
3803 * EVAL expr5b Push result of "expr5b"
3804 * COMPARE one of the compare instructions
3805 */
3806 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003807compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003808{
3809 exptype_T type = EXPR_UNKNOWN;
3810 char_u *p;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003811 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003812 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003813 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003814 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003815
3816 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02003817 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003818 return FAIL;
3819
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003820 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003821 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003822
3823 /*
3824 * If there is a comparative operator, use it.
3825 */
3826 if (type != EXPR_UNKNOWN)
3827 {
3828 int ic = FALSE; // Default: do not ignore case
3829
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003830 if (next != NULL)
3831 {
3832 *arg = next_line_from_context(cctx, TRUE);
3833 p = skipwhite(*arg);
3834 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003835 if (type_is && (p[len] == '?' || p[len] == '#'))
3836 {
3837 semsg(_(e_invexpr2), *arg);
3838 return FAIL;
3839 }
3840 // extra question mark appended: ignore case
3841 if (p[len] == '?')
3842 {
3843 ic = TRUE;
3844 ++len;
3845 }
3846 // extra '#' appended: match case (ignored)
3847 else if (p[len] == '#')
3848 ++len;
3849 // nothing appended: match case
3850
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003851 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003852 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02003853 error_white_both(p, len);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003854 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003855 }
3856
3857 // get the second variable
3858 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003859 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003860 return FAIL;
3861
Bram Moolenaara5565e42020-05-09 15:44:01 +02003862 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003863 return FAIL;
3864
Bram Moolenaara5565e42020-05-09 15:44:01 +02003865 if (ppconst->pp_used == ppconst_used + 2)
3866 {
3867 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
3868 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
3869 int ret;
3870
3871 // Both sides are a constant, compute the result now.
3872 // First check for a valid combination of types, this is more
3873 // strict than typval_compare().
Bram Moolenaar543e6f32020-07-10 22:45:38 +02003874 if (check_compare_types(type, tv1, tv2) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02003875 ret = FAIL;
3876 else
3877 {
3878 ret = typval_compare(tv1, tv2, type, ic);
3879 tv1->v_type = VAR_BOOL;
3880 tv1->vval.v_number = tv1->vval.v_number
3881 ? VVAL_TRUE : VVAL_FALSE;
3882 clear_tv(tv2);
3883 --ppconst->pp_used;
3884 }
3885 return ret;
3886 }
3887
3888 generate_ppconst(cctx, ppconst);
3889 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003890 }
3891
3892 return OK;
3893}
3894
Bram Moolenaar7f141552020-05-09 17:35:53 +02003895static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
3896
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003897/*
3898 * Compile || or &&.
3899 */
3900 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003901compile_and_or(
3902 char_u **arg,
3903 cctx_T *cctx,
3904 char *op,
3905 ppconst_T *ppconst,
3906 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003907{
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003908 char_u *next;
3909 char_u *p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003910 int opchar = *op;
3911
3912 if (p[0] == opchar && p[1] == opchar)
3913 {
3914 garray_T *instr = &cctx->ctx_instr;
3915 garray_T end_ga;
3916
3917 /*
3918 * Repeat until there is no following "||" or "&&"
3919 */
3920 ga_init2(&end_ga, sizeof(int), 10);
3921 while (p[0] == opchar && p[1] == opchar)
3922 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003923 if (next != NULL)
3924 {
3925 *arg = next_line_from_context(cctx, TRUE);
3926 p = skipwhite(*arg);
3927 }
3928
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003929 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3930 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02003931 semsg(_(e_white_space_required_before_and_after_str), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003932 return FAIL;
3933 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003934
Bram Moolenaara5565e42020-05-09 15:44:01 +02003935 // TODO: use ppconst if the value is a constant
3936 generate_ppconst(cctx, ppconst);
3937
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003938 if (ga_grow(&end_ga, 1) == FAIL)
3939 {
3940 ga_clear(&end_ga);
3941 return FAIL;
3942 }
3943 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3944 ++end_ga.ga_len;
3945 generate_JUMP(cctx, opchar == '|'
3946 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3947
3948 // eval the next expression
3949 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003950 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003951 return FAIL;
3952
Bram Moolenaara5565e42020-05-09 15:44:01 +02003953 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
3954 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003955 {
3956 ga_clear(&end_ga);
3957 return FAIL;
3958 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02003959
3960 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003961 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003962 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003963
3964 // Fill in the end label in all jumps.
3965 while (end_ga.ga_len > 0)
3966 {
3967 isn_T *isn;
3968
3969 --end_ga.ga_len;
3970 isn = ((isn_T *)instr->ga_data)
3971 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3972 isn->isn_arg.jump.jump_where = instr->ga_len;
3973 }
3974 ga_clear(&end_ga);
3975 }
3976
3977 return OK;
3978}
3979
3980/*
3981 * expr4a && expr4a && expr4a logical AND
3982 *
3983 * Produces instructions:
3984 * EVAL expr4a Push result of "expr4a"
3985 * JUMP_AND_KEEP_IF_FALSE end
3986 * EVAL expr4b Push result of "expr4b"
3987 * JUMP_AND_KEEP_IF_FALSE end
3988 * EVAL expr4c Push result of "expr4c"
3989 * end:
3990 */
3991 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003992compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003993{
Bram Moolenaara5565e42020-05-09 15:44:01 +02003994 int ppconst_used = ppconst->pp_used;
3995
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003996 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02003997 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003998 return FAIL;
3999
4000 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004001 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004002}
4003
4004/*
4005 * expr3a || expr3b || expr3c logical OR
4006 *
4007 * Produces instructions:
4008 * EVAL expr3a Push result of "expr3a"
4009 * JUMP_AND_KEEP_IF_TRUE end
4010 * EVAL expr3b Push result of "expr3b"
4011 * JUMP_AND_KEEP_IF_TRUE end
4012 * EVAL expr3c Push result of "expr3c"
4013 * end:
4014 */
4015 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004016compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004017{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004018 int ppconst_used = ppconst->pp_used;
4019
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004020 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004021 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004022 return FAIL;
4023
4024 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004025 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004026}
4027
4028/*
4029 * Toplevel expression: expr2 ? expr1a : expr1b
4030 *
4031 * Produces instructions:
4032 * EVAL expr2 Push result of "expr"
4033 * JUMP_IF_FALSE alt jump if false
4034 * EVAL expr1a
4035 * JUMP_ALWAYS end
4036 * alt: EVAL expr1b
4037 * end:
4038 */
4039 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004040compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004041{
4042 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004043 int ppconst_used = ppconst->pp_used;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004044 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004045
Bram Moolenaar3988f642020-08-27 22:43:03 +02004046 // Ignore all kinds of errors when not producing code.
4047 if (cctx->ctx_skip == SKIP_YES)
4048 {
4049 skip_expr(arg);
4050 return OK;
4051 }
4052
Bram Moolenaar61a89812020-05-07 16:58:17 +02004053 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004054 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004055 return FAIL;
4056
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004057 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004058 if (*p == '?')
4059 {
4060 garray_T *instr = &cctx->ctx_instr;
4061 garray_T *stack = &cctx->ctx_type_stack;
4062 int alt_idx = instr->ga_len;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004063 int end_idx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004064 isn_T *isn;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004065 type_T *type1 = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004066 type_T *type2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004067 int has_const_expr = FALSE;
4068 int const_value = FALSE;
4069 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004070
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004071 if (next != NULL)
4072 {
4073 *arg = next_line_from_context(cctx, TRUE);
4074 p = skipwhite(*arg);
4075 }
4076
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004077 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4078 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02004079 semsg(_(e_white_space_required_before_and_after_str), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004080 return FAIL;
4081 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004082
Bram Moolenaara5565e42020-05-09 15:44:01 +02004083 if (ppconst->pp_used == ppconst_used + 1)
4084 {
4085 // the condition is a constant, we know whether the ? or the :
4086 // expression is to be evaluated.
4087 has_const_expr = TRUE;
4088 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4089 clear_tv(&ppconst->pp_tv[ppconst_used]);
4090 --ppconst->pp_used;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004091 cctx->ctx_skip = save_skip == SKIP_YES || !const_value
4092 ? SKIP_YES : SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004093 }
4094 else
4095 {
4096 generate_ppconst(cctx, ppconst);
4097 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4098 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004099
4100 // evaluate the second expression; any type is accepted
4101 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004102 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004103 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004104 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004105 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004106
Bram Moolenaara5565e42020-05-09 15:44:01 +02004107 if (!has_const_expr)
4108 {
4109 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004110
Bram Moolenaara5565e42020-05-09 15:44:01 +02004111 // remember the type and drop it
4112 --stack->ga_len;
4113 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004114
Bram Moolenaara5565e42020-05-09 15:44:01 +02004115 end_idx = instr->ga_len;
4116 generate_JUMP(cctx, JUMP_ALWAYS, 0);
4117
4118 // jump here from JUMP_IF_FALSE
4119 isn = ((isn_T *)instr->ga_data) + alt_idx;
4120 isn->isn_arg.jump.jump_where = instr->ga_len;
4121 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004122
4123 // Check for the ":".
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004124 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004125 if (*p != ':')
4126 {
4127 emsg(_(e_missing_colon));
4128 return FAIL;
4129 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004130 if (next != NULL)
4131 {
4132 *arg = next_line_from_context(cctx, TRUE);
4133 p = skipwhite(*arg);
4134 }
4135
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004136 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4137 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02004138 semsg(_(e_white_space_required_before_and_after_str), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004139 return FAIL;
4140 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004141
4142 // evaluate the third expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004143 if (has_const_expr)
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004144 cctx->ctx_skip = save_skip == SKIP_YES || const_value
4145 ? SKIP_YES : SKIP_NOT;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004146 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004147 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004148 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004149 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004150 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004151
Bram Moolenaara5565e42020-05-09 15:44:01 +02004152 if (!has_const_expr)
4153 {
4154 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004155
Bram Moolenaara5565e42020-05-09 15:44:01 +02004156 // If the types differ, the result has a more generic type.
4157 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4158 common_type(type1, type2, &type2, cctx->ctx_type_list);
4159
4160 // jump here from JUMP_ALWAYS
4161 isn = ((isn_T *)instr->ga_data) + end_idx;
4162 isn->isn_arg.jump.jump_where = instr->ga_len;
4163 }
4164
4165 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004166 }
4167 return OK;
4168}
4169
4170/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004171 * Toplevel expression.
4172 */
4173 static int
4174compile_expr0(char_u **arg, cctx_T *cctx)
4175{
4176 ppconst_T ppconst;
4177
4178 CLEAR_FIELD(ppconst);
4179 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4180 {
4181 clear_ppconst(&ppconst);
4182 return FAIL;
4183 }
4184 if (generate_ppconst(cctx, &ppconst) == FAIL)
4185 return FAIL;
4186 return OK;
4187}
4188
4189/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004190 * compile "return [expr]"
4191 */
4192 static char_u *
4193compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4194{
4195 char_u *p = arg;
4196 garray_T *stack = &cctx->ctx_type_stack;
4197 type_T *stack_type;
4198
4199 if (*p != NUL && *p != '|' && *p != '\n')
4200 {
4201 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02004202 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004203 return NULL;
4204
4205 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4206 if (set_return_type)
4207 cctx->ctx_ufunc->uf_ret_type = stack_type;
Bram Moolenaar05a55512020-07-05 15:52:19 +02004208 else
4209 {
4210 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
4211 && stack_type->tt_type != VAR_VOID
4212 && stack_type->tt_type != VAR_UNKNOWN)
4213 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004214 emsg(_(e_returning_value_in_function_without_return_type));
Bram Moolenaar05a55512020-07-05 15:52:19 +02004215 return NULL;
4216 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02004217 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
4218 cctx, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004219 return NULL;
Bram Moolenaar05a55512020-07-05 15:52:19 +02004220 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004221 }
4222 else
4223 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004224 // "set_return_type" cannot be TRUE, only used for a lambda which
4225 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004226 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4227 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004228 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004229 emsg(_(e_missing_return_value));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004230 return NULL;
4231 }
4232
4233 // No argument, return zero.
4234 generate_PUSHNR(cctx, 0);
4235 }
4236
4237 if (generate_instr(cctx, ISN_RETURN) == NULL)
4238 return NULL;
4239
4240 // "return val | endif" is possible
4241 return skipwhite(p);
4242}
4243
4244/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004245 * Get a line from the compilation context, compatible with exarg_T getline().
4246 * Return a pointer to the line in allocated memory.
4247 * Return NULL for end-of-file or some error.
4248 */
4249 static char_u *
4250exarg_getline(
4251 int c UNUSED,
4252 void *cookie,
4253 int indent UNUSED,
Bram Moolenaar66250c92020-08-20 15:02:42 +02004254 getline_opt_T options UNUSED)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004255{
4256 cctx_T *cctx = (cctx_T *)cookie;
Bram Moolenaar66250c92020-08-20 15:02:42 +02004257 char_u *p;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004258
Bram Moolenaar66250c92020-08-20 15:02:42 +02004259 for (;;)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004260 {
Bram Moolenaar66250c92020-08-20 15:02:42 +02004261 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4262 return NULL;
4263 ++cctx->ctx_lnum;
4264 p = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
4265 // Comment lines result in NULL pointers, skip them.
4266 if (p != NULL)
4267 return vim_strsave(p);
Bram Moolenaar04b12692020-05-04 23:24:44 +02004268 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02004269}
4270
4271/*
4272 * Compile a nested :def command.
4273 */
4274 static char_u *
4275compile_nested_function(exarg_T *eap, cctx_T *cctx)
4276{
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004277 int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
Bram Moolenaar04b12692020-05-04 23:24:44 +02004278 char_u *name_start = eap->arg;
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004279 char_u *name_end = to_name_end(eap->arg, TRUE);
Bram Moolenaareef21022020-08-01 22:16:43 +02004280 char_u *lambda_name;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004281 lvar_T *lvar;
4282 ufunc_T *ufunc;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004283 int r;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004284
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004285 // Only g:Func() can use a namespace.
4286 if (name_start[1] == ':' && !is_global)
4287 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004288 semsg(_(e_namespace_not_supported_str), name_start);
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004289 return NULL;
4290 }
Bram Moolenaareef21022020-08-01 22:16:43 +02004291 if (check_defined(name_start, name_end - name_start, cctx) == FAIL)
4292 return NULL;
4293
Bram Moolenaar04b12692020-05-04 23:24:44 +02004294 eap->arg = name_end;
4295 eap->getline = exarg_getline;
4296 eap->cookie = cctx;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004297 eap->skip = cctx->ctx_skip == SKIP_YES;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004298 eap->forceit = FALSE;
Bram Moolenaareef21022020-08-01 22:16:43 +02004299 lambda_name = get_lambda_name();
4300 ufunc = def_function(eap, lambda_name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02004301
Bram Moolenaar822ba242020-05-24 23:00:18 +02004302 if (ufunc == NULL)
Bram Moolenaar7a3330f2020-08-27 23:57:57 +02004303 return eap->skip ? (char_u *)"" : NULL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02004304 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
Bram Moolenaar822ba242020-05-24 23:00:18 +02004305 && compile_def_function(ufunc, TRUE, cctx) == FAIL)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004306 return NULL;
4307
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004308 if (is_global)
4309 {
4310 char_u *func_name = vim_strnsave(name_start + 2,
4311 name_end - name_start - 2);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004312
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004313 if (func_name == NULL)
4314 r = FAIL;
4315 else
Bram Moolenaareef21022020-08-01 22:16:43 +02004316 r = generate_NEWFUNC(cctx, lambda_name, func_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004317 }
4318 else
4319 {
4320 // Define a local variable for the function reference.
4321 lvar = reserve_local(cctx, name_start, name_end - name_start,
4322 TRUE, ufunc->uf_func_type);
Bram Moolenaareef21022020-08-01 22:16:43 +02004323 if (lvar == NULL)
4324 return NULL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02004325 if (generate_FUNCREF(cctx, ufunc) == FAIL)
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004326 return NULL;
4327 r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
4328 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02004329
Bram Moolenaar61a89812020-05-07 16:58:17 +02004330 // TODO: warning for trailing text?
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004331 return r == FAIL ? NULL : (char_u *)"";
Bram Moolenaar04b12692020-05-04 23:24:44 +02004332}
4333
4334/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004335 * Return the length of an assignment operator, or zero if there isn't one.
4336 */
4337 int
4338assignment_len(char_u *p, int *heredoc)
4339{
4340 if (*p == '=')
4341 {
4342 if (p[1] == '<' && p[2] == '<')
4343 {
4344 *heredoc = TRUE;
4345 return 3;
4346 }
4347 return 1;
4348 }
4349 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4350 return 2;
4351 if (STRNCMP(p, "..=", 3) == 0)
4352 return 3;
4353 return 0;
4354}
4355
4356// words that cannot be used as a variable
4357static char *reserved[] = {
4358 "true",
4359 "false",
4360 NULL
4361};
4362
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004363typedef enum {
4364 dest_local,
4365 dest_option,
4366 dest_env,
4367 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004368 dest_buffer,
4369 dest_window,
4370 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004371 dest_vimvar,
4372 dest_script,
4373 dest_reg,
4374} assign_dest_T;
4375
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004376/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004377 * Generate the load instruction for "name".
4378 */
4379 static void
4380generate_loadvar(
4381 cctx_T *cctx,
4382 assign_dest_T dest,
4383 char_u *name,
4384 lvar_T *lvar,
4385 type_T *type)
4386{
4387 switch (dest)
4388 {
4389 case dest_option:
4390 // TODO: check the option exists
4391 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
4392 break;
4393 case dest_global:
4394 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4395 break;
4396 case dest_buffer:
4397 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4398 break;
4399 case dest_window:
4400 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4401 break;
4402 case dest_tab:
4403 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4404 break;
4405 case dest_script:
4406 compile_load_scriptvar(cctx,
4407 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
4408 break;
4409 case dest_env:
4410 // Include $ in the name here
4411 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4412 break;
4413 case dest_reg:
4414 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
4415 break;
4416 case dest_vimvar:
4417 generate_LOADV(cctx, name + 2, TRUE);
4418 break;
4419 case dest_local:
4420 if (lvar->lv_from_outer)
4421 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx,
4422 NULL, type);
4423 else
4424 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
4425 break;
4426 }
4427}
4428
Bram Moolenaare55b1c02020-06-21 15:52:59 +02004429 void
4430vim9_declare_error(char_u *name)
4431{
4432 char *scope = "";
4433
4434 switch (*name)
4435 {
Bram Moolenaar7fe87552020-06-21 20:38:28 +02004436 case 'g': scope = _("global"); break;
4437 case 'b': scope = _("buffer"); break;
4438 case 'w': scope = _("window"); break;
4439 case 't': scope = _("tab"); break;
4440 case 'v': scope = "v:"; break;
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02004441 case '$': semsg(_(e_cannot_declare_an_environment_variable), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004442 return;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004443 case '&': semsg(_(e_cannot_declare_an_option), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004444 return;
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02004445 case '@': semsg(_(e_cannot_declare_a_register_str), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004446 return;
Bram Moolenaar7fe87552020-06-21 20:38:28 +02004447 default: return;
Bram Moolenaare55b1c02020-06-21 15:52:59 +02004448 }
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02004449 semsg(_(e_cannot_declare_a_scope_variable), scope, name);
Bram Moolenaare55b1c02020-06-21 15:52:59 +02004450}
4451
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004452/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004453 * Compile declaration and assignment:
4454 * "let var", "let var = expr", "const var = expr" and "var = expr"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004455 * "arg" points to "var".
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004456 * Return NULL for an error.
4457 * Return "arg" if it does not look like a variable list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004458 */
4459 static char_u *
4460compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4461{
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004462 char_u *var_start;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004463 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004464 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004465 char_u *ret = NULL;
4466 int var_count = 0;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004467 int var_idx;
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02004468 int scriptvar_sid = 0;
4469 int scriptvar_idx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004470 int semicolon = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004471 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004472 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004473 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004474 int oplen = 0;
4475 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004476 type_T *type = &t_any;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004477 type_T *member_type = &t_any;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004478 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004479 char_u *sp;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004480 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004481
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004482 // Skip over the "var" or "[var, var]" to get to any "=".
4483 p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
4484 if (p == NULL)
4485 return *arg == '[' ? arg : NULL;
4486
4487 if (var_count > 0 && is_decl)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004488 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02004489 // TODO: should we allow this, and figure out type inference from list
4490 // members?
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004491 emsg(_(e_cannot_use_list_for_declaration));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004492 return NULL;
4493 }
4494
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004495 sp = p;
4496 p = skipwhite(p);
4497 op = p;
4498 oplen = assignment_len(p, &heredoc);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004499
4500 if (var_count > 0 && oplen == 0)
4501 // can be something like "[1, 2]->func()"
4502 return arg;
4503
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004504 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4505 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004506 error_white_both(op, oplen);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004507 return NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02004508 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004509
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004510 if (heredoc)
4511 {
4512 list_T *l;
4513 listitem_T *li;
4514
4515 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02004516 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004517 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004518 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004519
4520 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004521 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004522 {
4523 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4524 li->li_tv.vval.v_string = NULL;
4525 }
4526 generate_NEWLIST(cctx, l->lv_len);
4527 type = &t_list_string;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004528 member_type = &t_list_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004529 list_free(l);
4530 p += STRLEN(p);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004531 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004532 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004533 else if (var_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004534 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004535 // for "[var, var] = expr" evaluate the expression here, loop over the
4536 // list of variables below.
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004537
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004538 p = skipwhite(op + oplen);
4539 if (compile_expr0(&p, cctx) == FAIL)
4540 return NULL;
4541 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004542
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004543 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004544 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004545 type_T *stacktype;
4546
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004547 stacktype = stack->ga_len == 0 ? &t_void
4548 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004549 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004550 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004551 emsg(_(e_cannot_use_void_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004552 goto theend;
4553 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02004554 if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004555 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02004556 // TODO: check the length of a constant list here
Bram Moolenaar9af78762020-06-16 11:34:42 +02004557 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
4558 semicolon);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004559 }
4560 }
4561
4562 /*
4563 * Loop over variables in "[var, var] = expr".
4564 * For "var = expr" and "let var: type" this is done only once.
4565 */
4566 if (var_count > 0)
4567 var_start = skipwhite(arg + 1); // skip over the "["
4568 else
4569 var_start = arg;
4570 for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
4571 {
4572 char_u *var_end = skip_var_one(var_start, FALSE);
4573 size_t varlen;
4574 int new_local = FALSE;
4575 int opt_type;
4576 int opt_flags = 0;
4577 assign_dest_T dest = dest_local;
4578 int vimvaridx = -1;
4579 lvar_T *lvar = NULL;
4580 lvar_T arg_lvar;
4581 int has_type = FALSE;
4582 int has_index = FALSE;
4583 int instr_count = -1;
4584
Bram Moolenaar65821722020-08-02 18:58:54 +02004585 if (*var_start == '@')
4586 p = var_start + 2;
4587 else
4588 {
Bram Moolenaar2e800952020-08-23 19:34:48 +02004589 // skip over the leading "&", "&l:", "&g:" and "$"
4590 p = skip_option_env_lead(var_start);
Bram Moolenaar65821722020-08-02 18:58:54 +02004591 p = to_name_end(p, TRUE);
4592 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004593
4594 // "a: type" is declaring variable "a" with a type, not "a:".
4595 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
4596 --var_end;
4597 if (is_decl && p == var_start + 2 && p[-1] == ':')
4598 --p;
4599
4600 varlen = p - var_start;
4601 vim_free(name);
4602 name = vim_strnsave(var_start, varlen);
4603 if (name == NULL)
4604 return NULL;
4605 if (!heredoc)
4606 type = &t_any;
4607
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004608 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004609 {
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004610 int declare_error = FALSE;
4611
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004612 if (*var_start == '&')
4613 {
4614 int cc;
4615 long numval;
4616
4617 dest = dest_option;
4618 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004619 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004620 emsg(_(e_const_option));
4621 goto theend;
4622 }
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004623 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004624 p = var_start;
4625 p = find_option_end(&p, &opt_flags);
4626 if (p == NULL)
4627 {
4628 // cannot happen?
4629 emsg(_(e_letunexp));
4630 goto theend;
4631 }
4632 cc = *p;
4633 *p = NUL;
Bram Moolenaar2e800952020-08-23 19:34:48 +02004634 opt_type = get_option_value(skip_option_env_lead(var_start),
4635 &numval, NULL, opt_flags);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004636 *p = cc;
4637 if (opt_type == -3)
4638 {
4639 semsg(_(e_unknown_option), var_start);
4640 goto theend;
4641 }
4642 if (opt_type == -2 || opt_type == 0)
4643 type = &t_string;
4644 else
4645 type = &t_number; // both number and boolean option
4646 }
4647 else if (*var_start == '$')
4648 {
4649 dest = dest_env;
4650 type = &t_string;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004651 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004652 }
4653 else if (*var_start == '@')
4654 {
Bram Moolenaar65821722020-08-02 18:58:54 +02004655 if (!valid_yank_reg(var_start[1], FALSE) || var_start[1] == '.')
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004656 {
4657 emsg_invreg(var_start[1]);
4658 goto theend;
4659 }
4660 dest = dest_reg;
4661 type = &t_string;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004662 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004663 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02004664 else if (varlen > 1 && STRNCMP(var_start, "g:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004665 {
4666 dest = dest_global;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004667 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004668 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02004669 else if (varlen > 1 && STRNCMP(var_start, "b:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004670 {
4671 dest = dest_buffer;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004672 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004673 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02004674 else if (varlen > 1 && STRNCMP(var_start, "w:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004675 {
4676 dest = dest_window;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004677 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004678 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02004679 else if (varlen > 1 && STRNCMP(var_start, "t:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004680 {
4681 dest = dest_tab;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004682 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004683 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02004684 else if (varlen > 1 && STRNCMP(var_start, "v:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004685 {
4686 typval_T *vtv;
4687 int di_flags;
4688
4689 vimvaridx = find_vim_var(name + 2, &di_flags);
4690 if (vimvaridx < 0)
4691 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004692 semsg(_(e_variable_not_found_str), var_start);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004693 goto theend;
4694 }
4695 // We use the current value of "sandbox" here, is that OK?
4696 if (var_check_ro(di_flags, name, FALSE))
4697 goto theend;
4698 dest = dest_vimvar;
4699 vtv = get_vim_var_tv(vimvaridx);
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02004700 type = typval2type_vimvar(vtv, cctx->ctx_type_list);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004701 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004702 }
4703 else
4704 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02004705 int idx;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004706
4707 for (idx = 0; reserved[idx] != NULL; ++idx)
4708 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004709 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004710 semsg(_(e_cannot_use_reserved_name), name);
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004711 goto theend;
4712 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004713
4714 lvar = lookup_local(var_start, varlen, cctx);
4715 if (lvar == NULL)
4716 {
4717 CLEAR_FIELD(arg_lvar);
4718 if (lookup_arg(var_start, varlen,
4719 &arg_lvar.lv_idx, &arg_lvar.lv_type,
4720 &arg_lvar.lv_from_outer, cctx) == OK)
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004721 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004722 if (is_decl)
4723 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004724 semsg(_(e_str_is_used_as_argument), name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004725 goto theend;
4726 }
4727 lvar = &arg_lvar;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004728 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004729 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004730 if (lvar != NULL)
4731 {
4732 if (is_decl)
4733 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004734 semsg(_(e_variable_already_declared), name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004735 goto theend;
4736 }
4737 else if (lvar->lv_const)
4738 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004739 semsg(_(e_cannot_assign_to_constant), name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004740 goto theend;
4741 }
4742 }
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004743 else
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004744 {
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004745 int script_namespace = varlen > 1
4746 && STRNCMP(var_start, "s:", 2) == 0;
4747 int script_var = (script_namespace
Bram Moolenaar53900992020-08-22 19:02:02 +02004748 ? lookup_script(var_start + 2, varlen - 2, FALSE)
4749 : lookup_script(var_start, varlen, TRUE)) == OK;
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004750 imported_T *import =
4751 find_imported(var_start, varlen, cctx);
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02004752
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004753 if (script_namespace || script_var || import != NULL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004754 {
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004755 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4756
4757 if (is_decl)
4758 {
4759 if (script_namespace)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004760 semsg(_(e_cannot_declare_script_variable_in_function),
Bram Moolenaar33afa242020-07-29 19:18:00 +02004761 name);
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004762 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004763 semsg(_(e_variable_already_declared_in_script),
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004764 name);
4765 goto theend;
4766 }
4767 else if (cctx->ctx_ufunc->uf_script_ctx_version
4768 == SCRIPT_VERSION_VIM9
4769 && script_namespace
4770 && !script_var && import == NULL)
4771 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004772 semsg(_(e_unknown_variable_str), name);
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004773 goto theend;
4774 }
4775
4776 dest = dest_script;
4777
4778 // existing script-local variables should have a type
4779 scriptvar_sid = current_sctx.sc_sid;
4780 if (import != NULL)
4781 scriptvar_sid = import->imp_sid;
Bram Moolenaare3d46852020-08-29 13:39:17 +02004782 if (SCRIPT_ID_VALID(scriptvar_sid))
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004783 {
Bram Moolenaare3d46852020-08-29 13:39:17 +02004784 scriptvar_idx = get_script_item_idx(scriptvar_sid,
4785 rawname, TRUE);
4786 if (scriptvar_idx > 0)
4787 {
4788 scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
4789 svar_T *sv =
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004790 ((svar_T *)si->sn_var_vals.ga_data)
4791 + scriptvar_idx;
Bram Moolenaare3d46852020-08-29 13:39:17 +02004792 type = sv->sv_type;
4793 }
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004794 }
4795 }
4796 else if (name[1] == ':' && name[2] != NUL)
4797 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004798 semsg(_(e_cannot_use_namespaced_variable), name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004799 goto theend;
4800 }
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004801 else if (!is_decl)
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02004802 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004803 semsg(_(e_unknown_variable_str), name);
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02004804 goto theend;
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02004805 }
Bram Moolenaarfa211f32020-08-07 22:00:26 +02004806 else if (check_defined(var_start, varlen, cctx) == FAIL)
4807 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004808 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004809 }
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02004810
4811 if (declare_error)
4812 {
4813 vim9_declare_error(name);
4814 goto theend;
4815 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004816 }
4817
4818 // handle "a:name" as a name, not index "name" on "a"
4819 if (varlen > 1 || var_start[varlen] != ':')
4820 p = var_end;
4821
4822 if (dest != dest_option)
4823 {
4824 if (is_decl && *p == ':')
4825 {
4826 // parse optional type: "let var: type = expr"
4827 if (!VIM_ISWHITE(p[1]))
4828 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02004829 semsg(_(e_white_space_required_after_str), ":");
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004830 goto theend;
4831 }
4832 p = skipwhite(p + 1);
4833 type = parse_type(&p, cctx->ctx_type_list);
4834 has_type = TRUE;
4835 }
4836 else if (lvar != NULL)
4837 type = lvar->lv_type;
4838 }
4839
4840 if (oplen == 3 && !heredoc && dest != dest_global
4841 && type->tt_type != VAR_STRING
4842 && type->tt_type != VAR_ANY)
4843 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004844 emsg(_(e_can_only_concatenate_to_string));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004845 goto theend;
4846 }
4847
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004848 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004849 {
4850 if (oplen > 1 && !heredoc)
4851 {
4852 // +=, /=, etc. require an existing variable
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004853 semsg(_(e_cannot_use_operator_on_new_variable), name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004854 goto theend;
4855 }
4856
4857 // new local variable
Bram Moolenaar98b4f142020-08-08 15:46:01 +02004858 if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
4859 && var_wrong_func_name(name, TRUE))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004860 goto theend;
4861 lvar = reserve_local(cctx, var_start, varlen,
4862 cmdidx == CMD_const, type);
4863 if (lvar == NULL)
4864 goto theend;
4865 new_local = TRUE;
4866 }
4867
4868 member_type = type;
4869 if (var_end > var_start + varlen)
4870 {
4871 // Something follows after the variable: "var[idx]".
4872 if (is_decl)
4873 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004874 emsg(_(e_cannot_use_index_when_declaring_variable));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004875 goto theend;
4876 }
4877
4878 if (var_start[varlen] == '[')
4879 {
4880 has_index = TRUE;
4881 if (type->tt_member == NULL)
Bram Moolenaar2caa1592020-08-01 15:53:19 +02004882 member_type = &t_any;
4883 else
4884 member_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004885 }
4886 else
4887 {
4888 semsg("Not supported yet: %s", var_start);
4889 goto theend;
4890 }
4891 }
4892 else if (lvar == &arg_lvar)
4893 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004894 semsg(_(e_cannot_assign_to_argument), name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004895 goto theend;
4896 }
4897
4898 if (!heredoc)
4899 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004900 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004901 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004902 if (oplen > 0 && var_count == 0)
4903 {
4904 // skip over the "=" and the expression
4905 p = skipwhite(op + oplen);
4906 compile_expr0(&p, cctx);
4907 }
4908 }
4909 else if (oplen > 0)
4910 {
4911 type_T *stacktype;
4912
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004913 // For "var = expr" evaluate the expression.
4914 if (var_count == 0)
4915 {
4916 int r;
4917
4918 // for "+=", "*=", "..=" etc. first load the current value
4919 if (*op != '=')
4920 {
4921 generate_loadvar(cctx, dest, name, lvar, type);
4922
4923 if (has_index)
4924 {
4925 // TODO: get member from list or dict
4926 emsg("Index with operation not supported yet");
4927 goto theend;
4928 }
4929 }
4930
4931 // Compile the expression. Temporarily hide the new local
4932 // variable here, it is not available to this expression.
4933 if (new_local)
4934 --cctx->ctx_locals.ga_len;
4935 instr_count = instr->ga_len;
4936 p = skipwhite(op + oplen);
4937 r = compile_expr0(&p, cctx);
4938 if (new_local)
4939 ++cctx->ctx_locals.ga_len;
4940 if (r == FAIL)
4941 goto theend;
4942 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02004943 else if (semicolon && var_idx == var_count - 1)
4944 {
4945 // For "[var; var] = expr" get the rest of the list
4946 if (generate_SLICE(cctx, var_count - 1) == FAIL)
4947 goto theend;
4948 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004949 else
4950 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004951 // For "[var, var] = expr" get the "var_idx" item from the
4952 // list.
4953 if (generate_GETITEM(cctx, var_idx) == FAIL)
4954 return FAIL;
4955 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004956
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004957 stacktype = stack->ga_len == 0 ? &t_void
Bram Moolenaar6802cce2020-07-19 15:49:49 +02004958 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004959 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004960 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004961 if (new_local && !has_type)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004962 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004963 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004964 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004965 emsg(_(e_cannot_use_void_value));
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004966 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004967 }
Bram Moolenaar98b4f142020-08-08 15:46:01 +02004968 else if ((stacktype->tt_type == VAR_FUNC
4969 || stacktype->tt_type == VAR_PARTIAL)
4970 && var_wrong_func_name(name, TRUE))
4971 {
4972 goto theend;
4973 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004974 else
4975 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004976 // An empty list or dict has a &t_void member,
4977 // for a variable that implies &t_any.
4978 if (stacktype == &t_list_empty)
4979 lvar->lv_type = &t_list_any;
4980 else if (stacktype == &t_dict_empty)
4981 lvar->lv_type = &t_dict_any;
4982 else
4983 lvar->lv_type = stacktype;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004984 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004985 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02004986 else if (*op == '=')
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004987 {
4988 type_T *use_type = lvar->lv_type;
4989
Bram Moolenaar93ad1472020-08-19 22:02:41 +02004990 // without operator type is here, otherwise below
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004991 if (has_index)
4992 {
4993 use_type = use_type->tt_member;
4994 if (use_type == NULL)
4995 use_type = &t_void;
4996 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02004997 if (need_type(stacktype, use_type, -1, cctx, FALSE)
Bram Moolenaar93ad1472020-08-19 22:02:41 +02004998 == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02004999 goto theend;
5000 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005001 }
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005002 else if (*p != '=' && need_type(stacktype, member_type, -1,
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005003 cctx, FALSE) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005004 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005005 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005006 else if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005007 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005008 emsg(_(e_const_requires_a_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005009 goto theend;
5010 }
5011 else if (!has_type || dest == dest_option)
5012 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005013 emsg(_(e_type_or_initialization_required));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005014 goto theend;
5015 }
5016 else
5017 {
5018 // variables are always initialized
5019 if (ga_grow(instr, 1) == FAIL)
5020 goto theend;
5021 switch (member_type->tt_type)
5022 {
5023 case VAR_BOOL:
5024 generate_PUSHBOOL(cctx, VVAL_FALSE);
5025 break;
5026 case VAR_FLOAT:
5027#ifdef FEAT_FLOAT
5028 generate_PUSHF(cctx, 0.0);
5029#endif
5030 break;
5031 case VAR_STRING:
5032 generate_PUSHS(cctx, NULL);
5033 break;
5034 case VAR_BLOB:
5035 generate_PUSHBLOB(cctx, NULL);
5036 break;
5037 case VAR_FUNC:
5038 generate_PUSHFUNC(cctx, NULL, &t_func_void);
5039 break;
5040 case VAR_LIST:
5041 generate_NEWLIST(cctx, 0);
5042 break;
5043 case VAR_DICT:
5044 generate_NEWDICT(cctx, 0);
5045 break;
5046 case VAR_JOB:
5047 generate_PUSHJOB(cctx, NULL);
5048 break;
5049 case VAR_CHANNEL:
5050 generate_PUSHCHANNEL(cctx, NULL);
5051 break;
5052 case VAR_NUMBER:
5053 case VAR_UNKNOWN:
5054 case VAR_ANY:
5055 case VAR_PARTIAL:
5056 case VAR_VOID:
5057 case VAR_SPECIAL: // cannot happen
5058 generate_PUSHNR(cctx, 0);
5059 break;
5060 }
5061 }
5062 if (var_count == 0)
5063 end = p;
5064 }
5065
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005066 // no need to parse more when skipping
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005067 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005068 break;
5069
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005070 if (oplen > 0 && *op != '=')
5071 {
Bram Moolenaar93ad1472020-08-19 22:02:41 +02005072 type_T *expected;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005073 type_T *stacktype;
5074
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005075 if (*op == '.')
5076 expected = &t_string;
Bram Moolenaar93ad1472020-08-19 22:02:41 +02005077 else
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02005078 expected = member_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005079 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar93ad1472020-08-19 22:02:41 +02005080 if (
5081#ifdef FEAT_FLOAT
5082 // If variable is float operation with number is OK.
5083 !(expected == &t_float && stacktype == &t_number) &&
5084#endif
5085 need_type(stacktype, expected, -1, cctx, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005086 goto theend;
5087
5088 if (*op == '.')
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02005089 {
5090 if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL)
5091 goto theend;
5092 }
5093 else if (*op == '+')
5094 {
5095 if (generate_add_instr(cctx,
5096 operator_type(member_type, stacktype),
5097 member_type, stacktype) == FAIL)
5098 goto theend;
5099 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02005100 else if (generate_two_op(cctx, op) == FAIL)
5101 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005102 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005103
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005104 if (has_index)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005105 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005106 int r;
5107
5108 // Compile the "idx" in "var[idx]".
5109 if (new_local)
5110 --cctx->ctx_locals.ga_len;
5111 p = skipwhite(var_start + varlen + 1);
5112 r = compile_expr0(&p, cctx);
5113 if (new_local)
5114 ++cctx->ctx_locals.ga_len;
5115 if (r == FAIL)
5116 goto theend;
5117 if (*skipwhite(p) != ']')
5118 {
Bram Moolenaard1103582020-08-14 22:44:25 +02005119 // this should not happen
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005120 emsg(_(e_missbrac));
5121 goto theend;
5122 }
Bram Moolenaar2caa1592020-08-01 15:53:19 +02005123 if (type == &t_any)
5124 {
5125 type_T *idx_type = ((type_T **)stack->ga_data)[
5126 stack->ga_len - 1];
5127 // Index on variable of unknown type: guess the type from the
5128 // index type: number is dict, otherwise dict.
5129 // TODO: should do the assignment at runtime
5130 if (idx_type->tt_type == VAR_NUMBER)
5131 type = &t_list_any;
5132 else
5133 type = &t_dict_any;
5134 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005135 if (type->tt_type == VAR_DICT
5136 && may_generate_2STRING(-1, cctx) == FAIL)
5137 goto theend;
5138 if (type->tt_type == VAR_LIST
5139 && ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005140 != VAR_NUMBER)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005141 {
5142 emsg(_(e_number_exp));
5143 goto theend;
5144 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005145
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005146 // Load the dict or list. On the stack we then have:
5147 // - value
5148 // - index
5149 // - variable
5150 generate_loadvar(cctx, dest, name, lvar, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005151
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005152 if (type->tt_type == VAR_LIST)
5153 {
5154 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL)
5155 return FAIL;
5156 }
5157 else if (type->tt_type == VAR_DICT)
5158 {
5159 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL)
5160 return FAIL;
5161 }
5162 else
5163 {
5164 emsg(_(e_listreq));
5165 goto theend;
5166 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005167 }
5168 else
5169 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005170 switch (dest)
5171 {
5172 case dest_option:
Bram Moolenaar2e800952020-08-23 19:34:48 +02005173 generate_STOREOPT(cctx, skip_option_env_lead(name),
5174 opt_flags);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005175 break;
5176 case dest_global:
5177 // include g: with the name, easier to execute that way
5178 generate_STORE(cctx, ISN_STOREG, 0, name);
5179 break;
5180 case dest_buffer:
5181 // include b: with the name, easier to execute that way
5182 generate_STORE(cctx, ISN_STOREB, 0, name);
5183 break;
5184 case dest_window:
5185 // include w: with the name, easier to execute that way
5186 generate_STORE(cctx, ISN_STOREW, 0, name);
5187 break;
5188 case dest_tab:
5189 // include t: with the name, easier to execute that way
5190 generate_STORE(cctx, ISN_STORET, 0, name);
5191 break;
5192 case dest_env:
5193 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5194 break;
5195 case dest_reg:
5196 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5197 break;
5198 case dest_vimvar:
5199 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5200 break;
5201 case dest_script:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005202 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005203 if (scriptvar_idx < 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005204 {
5205 char_u *name_s = name;
5206
5207 // Include s: in the name for store_var()
5208 if (name[1] != ':')
5209 {
5210 int len = (int)STRLEN(name) + 3;
5211
5212 name_s = alloc(len);
5213 if (name_s == NULL)
5214 name_s = name;
5215 else
5216 vim_snprintf((char *)name_s, len,
5217 "s:%s", name);
5218 }
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005219 generate_OLDSCRIPT(cctx, ISN_STORES, name_s,
5220 scriptvar_sid, type);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005221 if (name_s != name)
5222 vim_free(name_s);
5223 }
5224 else
5225 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005226 scriptvar_sid, scriptvar_idx, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005227 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005228 break;
5229 case dest_local:
5230 if (lvar != NULL)
5231 {
5232 isn_T *isn = ((isn_T *)instr->ga_data)
5233 + instr->ga_len - 1;
5234
5235 // optimization: turn "var = 123" from ISN_PUSHNR +
5236 // ISN_STORE into ISN_STORENR
5237 if (!lvar->lv_from_outer
5238 && instr->ga_len == instr_count + 1
5239 && isn->isn_type == ISN_PUSHNR)
5240 {
5241 varnumber_T val = isn->isn_arg.number;
5242
5243 isn->isn_type = ISN_STORENR;
5244 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
5245 isn->isn_arg.storenr.stnr_val = val;
5246 if (stack->ga_len > 0)
5247 --stack->ga_len;
5248 }
5249 else if (lvar->lv_from_outer)
5250 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005251 NULL);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005252 else
5253 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5254 }
5255 break;
5256 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005257 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005258
5259 if (var_idx + 1 < var_count)
5260 var_start = skipwhite(var_end + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005261 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005262
5263 // for "[var, var] = expr" drop the "expr" value
Bram Moolenaar9af78762020-06-16 11:34:42 +02005264 if (var_count > 0 && !semicolon)
5265 {
5266 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5267 goto theend;
5268 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005269
Bram Moolenaarb2097502020-07-19 17:17:02 +02005270 ret = skipwhite(end);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005271
5272theend:
5273 vim_free(name);
5274 return ret;
5275}
5276
5277/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005278 * Check if "name" can be "unlet".
5279 */
5280 int
5281check_vim9_unlet(char_u *name)
5282{
5283 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
5284 {
Bram Moolenaar84367732020-08-23 15:21:55 +02005285 // "unlet s:var" is allowed in legacy script.
5286 if (*name == 's' && !script_is_vim9())
5287 return OK;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005288 semsg(_(e_cannot_unlet_str), name);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005289 return FAIL;
5290 }
5291 return OK;
5292}
5293
5294/*
5295 * Callback passed to ex_unletlock().
5296 */
5297 static int
5298compile_unlet(
5299 lval_T *lvp,
5300 char_u *name_end,
5301 exarg_T *eap,
5302 int deep UNUSED,
5303 void *coookie)
5304{
5305 cctx_T *cctx = coookie;
5306
5307 if (lvp->ll_tv == NULL)
5308 {
5309 char_u *p = lvp->ll_name;
5310 int cc = *name_end;
5311 int ret = OK;
5312
5313 // Normal name. Only supports g:, w:, t: and b: namespaces.
5314 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005315 if (*p == '$')
5316 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
5317 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005318 ret = FAIL;
5319 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005320 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005321
5322 *name_end = cc;
5323 return ret;
5324 }
5325
5326 // TODO: unlet {list}[idx]
5327 // TODO: unlet {dict}[key]
5328 emsg("Sorry, :unlet not fully implemented yet");
5329 return FAIL;
5330}
5331
5332/*
5333 * compile "unlet var", "lock var" and "unlock var"
5334 * "arg" points to "var".
5335 */
5336 static char_u *
5337compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
5338{
5339 char_u *p = arg;
5340
5341 if (eap->cmdidx != CMD_unlet)
5342 {
5343 emsg("Sorry, :lock and unlock not implemented yet");
5344 return NULL;
5345 }
5346
5347 if (*p == '!')
5348 {
5349 p = skipwhite(p + 1);
5350 eap->forceit = TRUE;
5351 }
5352
5353 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
5354 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5355}
5356
5357/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005358 * Compile an :import command.
5359 */
5360 static char_u *
5361compile_import(char_u *arg, cctx_T *cctx)
5362{
Bram Moolenaar1c991142020-07-04 13:15:31 +02005363 return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005364}
5365
5366/*
5367 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
5368 */
5369 static int
5370compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
5371{
5372 garray_T *instr = &cctx->ctx_instr;
5373 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
5374
5375 if (endlabel == NULL)
5376 return FAIL;
5377 endlabel->el_next = *el;
5378 *el = endlabel;
5379 endlabel->el_end_label = instr->ga_len;
5380
5381 generate_JUMP(cctx, when, 0);
5382 return OK;
5383}
5384
5385 static void
5386compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
5387{
5388 garray_T *instr = &cctx->ctx_instr;
5389
5390 while (*el != NULL)
5391 {
5392 endlabel_T *cur = (*el);
5393 isn_T *isn;
5394
5395 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
5396 isn->isn_arg.jump.jump_where = instr->ga_len;
5397 *el = cur->el_next;
5398 vim_free(cur);
5399 }
5400}
5401
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005402 static void
5403compile_free_jump_to_end(endlabel_T **el)
5404{
5405 while (*el != NULL)
5406 {
5407 endlabel_T *cur = (*el);
5408
5409 *el = cur->el_next;
5410 vim_free(cur);
5411 }
5412}
5413
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005414/*
5415 * Create a new scope and set up the generic items.
5416 */
5417 static scope_T *
5418new_scope(cctx_T *cctx, scopetype_T type)
5419{
5420 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
5421
5422 if (scope == NULL)
5423 return NULL;
5424 scope->se_outer = cctx->ctx_scope;
5425 cctx->ctx_scope = scope;
5426 scope->se_type = type;
5427 scope->se_local_count = cctx->ctx_locals.ga_len;
5428 return scope;
5429}
5430
5431/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005432 * Free the current scope and go back to the outer scope.
5433 */
5434 static void
5435drop_scope(cctx_T *cctx)
5436{
5437 scope_T *scope = cctx->ctx_scope;
5438
5439 if (scope == NULL)
5440 {
5441 iemsg("calling drop_scope() without a scope");
5442 return;
5443 }
5444 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005445 switch (scope->se_type)
5446 {
5447 case IF_SCOPE:
5448 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
5449 case FOR_SCOPE:
5450 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
5451 case WHILE_SCOPE:
5452 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
5453 case TRY_SCOPE:
5454 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
5455 case NO_SCOPE:
5456 case BLOCK_SCOPE:
5457 break;
5458 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005459 vim_free(scope);
5460}
5461
5462/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005463 * compile "if expr"
5464 *
5465 * "if expr" Produces instructions:
5466 * EVAL expr Push result of "expr"
5467 * JUMP_IF_FALSE end
5468 * ... body ...
5469 * end:
5470 *
5471 * "if expr | else" Produces instructions:
5472 * EVAL expr Push result of "expr"
5473 * JUMP_IF_FALSE else
5474 * ... body ...
5475 * JUMP_ALWAYS end
5476 * else:
5477 * ... body ...
5478 * end:
5479 *
5480 * "if expr1 | elseif expr2 | else" Produces instructions:
5481 * EVAL expr Push result of "expr"
5482 * JUMP_IF_FALSE elseif
5483 * ... body ...
5484 * JUMP_ALWAYS end
5485 * elseif:
5486 * EVAL expr Push result of "expr"
5487 * JUMP_IF_FALSE else
5488 * ... body ...
5489 * JUMP_ALWAYS end
5490 * else:
5491 * ... body ...
5492 * end:
5493 */
5494 static char_u *
5495compile_if(char_u *arg, cctx_T *cctx)
5496{
5497 char_u *p = arg;
5498 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005499 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005500 scope_T *scope;
Bram Moolenaarefd88552020-06-18 20:50:10 +02005501 skip_T skip_save = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005502 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005503
Bram Moolenaara5565e42020-05-09 15:44:01 +02005504 CLEAR_FIELD(ppconst);
5505 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005506 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02005507 clear_ppconst(&ppconst);
5508 return NULL;
5509 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02005510 if (cctx->ctx_skip == SKIP_YES)
5511 clear_ppconst(&ppconst);
5512 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaara5565e42020-05-09 15:44:01 +02005513 {
5514 // The expression results in a constant.
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005515 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005516 clear_ppconst(&ppconst);
5517 }
5518 else
5519 {
5520 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005521 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005522 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005523 return NULL;
5524 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005525
5526 scope = new_scope(cctx, IF_SCOPE);
5527 if (scope == NULL)
5528 return NULL;
Bram Moolenaarefd88552020-06-18 20:50:10 +02005529 scope->se_skip_save = skip_save;
5530 // "is_had_return" will be reset if any block does not end in :return
5531 scope->se_u.se_if.is_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005532
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005533 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005534 {
5535 // "where" is set when ":elseif", "else" or ":endif" is found
5536 scope->se_u.se_if.is_if_label = instr->ga_len;
5537 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5538 }
5539 else
5540 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005541
5542 return p;
5543}
5544
5545 static char_u *
5546compile_elseif(char_u *arg, cctx_T *cctx)
5547{
5548 char_u *p = arg;
5549 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005550 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005551 isn_T *isn;
5552 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005553 ppconst_T ppconst;
Bram Moolenaar749639e2020-08-27 23:08:47 +02005554 skip_T save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005555
5556 if (scope == NULL || scope->se_type != IF_SCOPE)
5557 {
5558 emsg(_(e_elseif_without_if));
5559 return NULL;
5560 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005561 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02005562 if (!cctx->ctx_had_return)
5563 scope->se_u.se_if.is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005564
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005565 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005566 {
5567 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005568 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005569 return NULL;
5570 // previous "if" or "elseif" jumps here
5571 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5572 isn->isn_arg.jump.jump_where = instr->ga_len;
5573 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005574
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005575 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02005576 CLEAR_FIELD(ppconst);
Bram Moolenaar749639e2020-08-27 23:08:47 +02005577 if (cctx->ctx_skip == SKIP_YES)
5578 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005579 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005580 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02005581 clear_ppconst(&ppconst);
5582 return NULL;
5583 }
Bram Moolenaar749639e2020-08-27 23:08:47 +02005584 cctx->ctx_skip = save_skip;
Bram Moolenaarefd88552020-06-18 20:50:10 +02005585 if (scope->se_skip_save == SKIP_YES)
5586 clear_ppconst(&ppconst);
5587 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaar7f141552020-05-09 17:35:53 +02005588 {
5589 // The expression results in a constant.
5590 // TODO: how about nesting?
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005591 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005592 clear_ppconst(&ppconst);
5593 scope->se_u.se_if.is_if_label = -1;
5594 }
5595 else
5596 {
5597 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005598 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005599 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005600 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005601
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005602 // "where" is set when ":elseif", "else" or ":endif" is found
5603 scope->se_u.se_if.is_if_label = instr->ga_len;
5604 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5605 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005606
5607 return p;
5608}
5609
5610 static char_u *
5611compile_else(char_u *arg, cctx_T *cctx)
5612{
5613 char_u *p = arg;
5614 garray_T *instr = &cctx->ctx_instr;
5615 isn_T *isn;
5616 scope_T *scope = cctx->ctx_scope;
5617
5618 if (scope == NULL || scope->se_type != IF_SCOPE)
5619 {
5620 emsg(_(e_else_without_if));
5621 return NULL;
5622 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005623 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02005624 if (!cctx->ctx_had_return)
5625 scope->se_u.se_if.is_had_return = FALSE;
5626 scope->se_u.se_if.is_seen_else = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005627
Bram Moolenaarefd88552020-06-18 20:50:10 +02005628 if (scope->se_skip_save != SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005629 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02005630 // jump from previous block to the end, unless the else block is empty
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005631 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005632 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02005633 if (!cctx->ctx_had_return
5634 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
5635 JUMP_ALWAYS, cctx) == FAIL)
5636 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005637 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005638
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005639 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02005640 {
5641 if (scope->se_u.se_if.is_if_label >= 0)
5642 {
5643 // previous "if" or "elseif" jumps here
5644 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5645 isn->isn_arg.jump.jump_where = instr->ga_len;
5646 scope->se_u.se_if.is_if_label = -1;
5647 }
5648 }
5649
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02005650 if (cctx->ctx_skip != SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02005651 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
5652 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005653
5654 return p;
5655}
5656
5657 static char_u *
5658compile_endif(char_u *arg, cctx_T *cctx)
5659{
5660 scope_T *scope = cctx->ctx_scope;
5661 ifscope_T *ifscope;
5662 garray_T *instr = &cctx->ctx_instr;
5663 isn_T *isn;
5664
5665 if (scope == NULL || scope->se_type != IF_SCOPE)
5666 {
5667 emsg(_(e_endif_without_if));
5668 return NULL;
5669 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005670 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005671 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02005672 if (!cctx->ctx_had_return)
5673 ifscope->is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005674
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005675 if (scope->se_u.se_if.is_if_label >= 0)
5676 {
5677 // previous "if" or "elseif" jumps here
5678 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5679 isn->isn_arg.jump.jump_where = instr->ga_len;
5680 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005681 // Fill in the "end" label in jumps at the end of the blocks.
5682 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02005683 cctx->ctx_skip = scope->se_skip_save;
5684
5685 // If all the blocks end in :return and there is an :else then the
5686 // had_return flag is set.
5687 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005688
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005689 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005690 return arg;
5691}
5692
5693/*
5694 * compile "for var in expr"
5695 *
5696 * Produces instructions:
5697 * PUSHNR -1
5698 * STORE loop-idx Set index to -1
5699 * EVAL expr Push result of "expr"
5700 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5701 * - if beyond end, jump to "end"
5702 * - otherwise get item from list and push it
5703 * STORE var Store item in "var"
5704 * ... body ...
5705 * JUMP top Jump back to repeat
5706 * end: DROP Drop the result of "expr"
5707 *
5708 */
5709 static char_u *
5710compile_for(char_u *arg, cctx_T *cctx)
5711{
5712 char_u *p;
5713 size_t varlen;
5714 garray_T *instr = &cctx->ctx_instr;
5715 garray_T *stack = &cctx->ctx_type_stack;
5716 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005717 lvar_T *loop_lvar; // loop iteration variable
5718 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005719 type_T *vartype;
5720
5721 // TODO: list of variables: "for [key, value] in dict"
5722 // parse "var"
5723 for (p = arg; eval_isnamec1(*p); ++p)
5724 ;
5725 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005726 var_lvar = lookup_local(arg, varlen, cctx);
5727 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005728 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005729 semsg(_(e_variable_already_declared), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005730 return NULL;
5731 }
5732
5733 // consume "in"
5734 p = skipwhite(p);
5735 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5736 {
5737 emsg(_(e_missing_in));
5738 return NULL;
5739 }
5740 p = skipwhite(p + 2);
5741
5742
5743 scope = new_scope(cctx, FOR_SCOPE);
5744 if (scope == NULL)
5745 return NULL;
5746
5747 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005748 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5749 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005750 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005751 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005752 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005753 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005754 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005755
5756 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005757 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5758 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005759 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005760 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005761 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005762 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005763 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005764
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005765 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005766
5767 // compile "expr", it remains on the stack until "endfor"
5768 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005769 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005770 {
5771 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005772 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005773 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005774
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02005775 // Now that we know the type of "var", check that it is a list, now or at
5776 // runtime.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005777 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005778 if (need_type(vartype, &t_list_any, -1, cctx, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005779 {
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005780 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005781 return NULL;
5782 }
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02005783 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005784 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005785
5786 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005787 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005788
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005789 generate_FOR(cctx, loop_lvar->lv_idx);
5790 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005791
5792 return arg;
5793}
5794
5795/*
5796 * compile "endfor"
5797 */
5798 static char_u *
5799compile_endfor(char_u *arg, cctx_T *cctx)
5800{
5801 garray_T *instr = &cctx->ctx_instr;
5802 scope_T *scope = cctx->ctx_scope;
5803 forscope_T *forscope;
5804 isn_T *isn;
5805
5806 if (scope == NULL || scope->se_type != FOR_SCOPE)
5807 {
5808 emsg(_(e_for));
5809 return NULL;
5810 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005811 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005812 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005813 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005814
5815 // At end of ":for" scope jump back to the FOR instruction.
5816 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5817
5818 // Fill in the "end" label in the FOR statement so it can jump here
5819 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5820 isn->isn_arg.forloop.for_end = instr->ga_len;
5821
5822 // Fill in the "end" label any BREAK statements
5823 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5824
5825 // Below the ":for" scope drop the "expr" list from the stack.
5826 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5827 return NULL;
5828
5829 vim_free(scope);
5830
5831 return arg;
5832}
5833
5834/*
5835 * compile "while expr"
5836 *
5837 * Produces instructions:
5838 * top: EVAL expr Push result of "expr"
5839 * JUMP_IF_FALSE end jump if false
5840 * ... body ...
5841 * JUMP top Jump back to repeat
5842 * end:
5843 *
5844 */
5845 static char_u *
5846compile_while(char_u *arg, cctx_T *cctx)
5847{
5848 char_u *p = arg;
5849 garray_T *instr = &cctx->ctx_instr;
5850 scope_T *scope;
5851
5852 scope = new_scope(cctx, WHILE_SCOPE);
5853 if (scope == NULL)
5854 return NULL;
5855
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005856 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005857
5858 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02005859 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005860 return NULL;
5861
5862 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005863 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005864 JUMP_IF_FALSE, cctx) == FAIL)
5865 return FAIL;
5866
5867 return p;
5868}
5869
5870/*
5871 * compile "endwhile"
5872 */
5873 static char_u *
5874compile_endwhile(char_u *arg, cctx_T *cctx)
5875{
5876 scope_T *scope = cctx->ctx_scope;
5877
5878 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5879 {
5880 emsg(_(e_while));
5881 return NULL;
5882 }
5883 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005884 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005885
5886 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005887 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005888
5889 // Fill in the "end" label in the WHILE statement so it can jump here.
5890 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005891 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005892
5893 vim_free(scope);
5894
5895 return arg;
5896}
5897
5898/*
5899 * compile "continue"
5900 */
5901 static char_u *
5902compile_continue(char_u *arg, cctx_T *cctx)
5903{
5904 scope_T *scope = cctx->ctx_scope;
5905
5906 for (;;)
5907 {
5908 if (scope == NULL)
5909 {
5910 emsg(_(e_continue));
5911 return NULL;
5912 }
5913 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5914 break;
5915 scope = scope->se_outer;
5916 }
5917
5918 // Jump back to the FOR or WHILE instruction.
5919 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005920 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5921 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005922 return arg;
5923}
5924
5925/*
5926 * compile "break"
5927 */
5928 static char_u *
5929compile_break(char_u *arg, cctx_T *cctx)
5930{
5931 scope_T *scope = cctx->ctx_scope;
5932 endlabel_T **el;
5933
5934 for (;;)
5935 {
5936 if (scope == NULL)
5937 {
5938 emsg(_(e_break));
5939 return NULL;
5940 }
5941 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5942 break;
5943 scope = scope->se_outer;
5944 }
5945
5946 // Jump to the end of the FOR or WHILE loop.
5947 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005948 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005949 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005950 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005951 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5952 return FAIL;
5953
5954 return arg;
5955}
5956
5957/*
5958 * compile "{" start of block
5959 */
5960 static char_u *
5961compile_block(char_u *arg, cctx_T *cctx)
5962{
5963 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5964 return NULL;
5965 return skipwhite(arg + 1);
5966}
5967
5968/*
5969 * compile end of block: drop one scope
5970 */
5971 static void
5972compile_endblock(cctx_T *cctx)
5973{
5974 scope_T *scope = cctx->ctx_scope;
5975
5976 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005977 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005978 vim_free(scope);
5979}
5980
5981/*
5982 * compile "try"
5983 * Creates a new scope for the try-endtry, pointing to the first catch and
5984 * finally.
5985 * Creates another scope for the "try" block itself.
5986 * TRY instruction sets up exception handling at runtime.
5987 *
5988 * "try"
5989 * TRY -> catch1, -> finally push trystack entry
5990 * ... try block
5991 * "throw {exception}"
5992 * EVAL {exception}
5993 * THROW create exception
5994 * ... try block
5995 * " catch {expr}"
5996 * JUMP -> finally
5997 * catch1: PUSH exeception
5998 * EVAL {expr}
5999 * MATCH
6000 * JUMP nomatch -> catch2
6001 * CATCH remove exception
6002 * ... catch block
6003 * " catch"
6004 * JUMP -> finally
6005 * catch2: CATCH remove exception
6006 * ... catch block
6007 * " finally"
6008 * finally:
6009 * ... finally block
6010 * " endtry"
6011 * ENDTRY pop trystack entry, may rethrow
6012 */
6013 static char_u *
6014compile_try(char_u *arg, cctx_T *cctx)
6015{
6016 garray_T *instr = &cctx->ctx_instr;
6017 scope_T *try_scope;
6018 scope_T *scope;
6019
6020 // scope that holds the jumps that go to catch/finally/endtry
6021 try_scope = new_scope(cctx, TRY_SCOPE);
6022 if (try_scope == NULL)
6023 return NULL;
6024
6025 // "catch" is set when the first ":catch" is found.
6026 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006027 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006028 if (generate_instr(cctx, ISN_TRY) == NULL)
6029 return NULL;
6030
6031 // scope for the try block itself
6032 scope = new_scope(cctx, BLOCK_SCOPE);
6033 if (scope == NULL)
6034 return NULL;
6035
6036 return arg;
6037}
6038
6039/*
6040 * compile "catch {expr}"
6041 */
6042 static char_u *
6043compile_catch(char_u *arg, cctx_T *cctx UNUSED)
6044{
6045 scope_T *scope = cctx->ctx_scope;
6046 garray_T *instr = &cctx->ctx_instr;
6047 char_u *p;
6048 isn_T *isn;
6049
6050 // end block scope from :try or :catch
6051 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6052 compile_endblock(cctx);
6053 scope = cctx->ctx_scope;
6054
6055 // Error if not in a :try scope
6056 if (scope == NULL || scope->se_type != TRY_SCOPE)
6057 {
6058 emsg(_(e_catch));
6059 return NULL;
6060 }
6061
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006062 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006063 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006064 emsg(_(e_catch_unreachable_after_catch_all));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006065 return NULL;
6066 }
6067
6068 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006069 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006070 JUMP_ALWAYS, cctx) == FAIL)
6071 return NULL;
6072
6073 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006074 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006075 if (isn->isn_arg.try.try_catch == 0)
6076 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006077 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006078 {
6079 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006080 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006081 isn->isn_arg.jump.jump_where = instr->ga_len;
6082 }
6083
6084 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02006085 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006086 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006087 scope->se_u.se_try.ts_caught_all = TRUE;
6088 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006089 }
6090 else
6091 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006092 char_u *end;
6093 char_u *pat;
6094 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006095 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006096 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006097
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006098 // Push v:exception, push {expr} and MATCH
6099 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
6100
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006101 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006102 if (*end != *p)
6103 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02006104 semsg(_(e_separator_mismatch_str), p);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006105 vim_free(tofree);
6106 return FAIL;
6107 }
6108 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006109 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006110 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006111 len = (int)(end - tofree);
6112 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006113 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006114 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006115 if (pat == NULL)
6116 return FAIL;
6117 if (generate_PUSHS(cctx, pat) == FAIL)
6118 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006119
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006120 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
6121 return NULL;
6122
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006123 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006124 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
6125 return NULL;
6126 }
6127
6128 if (generate_instr(cctx, ISN_CATCH) == NULL)
6129 return NULL;
6130
6131 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6132 return NULL;
6133 return p;
6134}
6135
6136 static char_u *
6137compile_finally(char_u *arg, cctx_T *cctx)
6138{
6139 scope_T *scope = cctx->ctx_scope;
6140 garray_T *instr = &cctx->ctx_instr;
6141 isn_T *isn;
6142
6143 // end block scope from :try or :catch
6144 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6145 compile_endblock(cctx);
6146 scope = cctx->ctx_scope;
6147
6148 // Error if not in a :try scope
6149 if (scope == NULL || scope->se_type != TRY_SCOPE)
6150 {
6151 emsg(_(e_finally));
6152 return NULL;
6153 }
6154
6155 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006156 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006157 if (isn->isn_arg.try.try_finally != 0)
6158 {
6159 emsg(_(e_finally_dup));
6160 return NULL;
6161 }
6162
6163 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006164 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006165
Bram Moolenaar585fea72020-04-02 22:33:21 +02006166 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006167 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006168 {
6169 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006170 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006171 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaare8593122020-07-18 15:17:02 +02006172 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006173 }
6174
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006175 // TODO: set index in ts_finally_label jumps
6176
6177 return arg;
6178}
6179
6180 static char_u *
6181compile_endtry(char_u *arg, cctx_T *cctx)
6182{
6183 scope_T *scope = cctx->ctx_scope;
6184 garray_T *instr = &cctx->ctx_instr;
6185 isn_T *isn;
6186
6187 // end block scope from :catch or :finally
6188 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6189 compile_endblock(cctx);
6190 scope = cctx->ctx_scope;
6191
6192 // Error if not in a :try scope
6193 if (scope == NULL || scope->se_type != TRY_SCOPE)
6194 {
6195 if (scope == NULL)
6196 emsg(_(e_no_endtry));
6197 else if (scope->se_type == WHILE_SCOPE)
6198 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01006199 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006200 emsg(_(e_endfor));
6201 else
6202 emsg(_(e_endif));
6203 return NULL;
6204 }
6205
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006206 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006207 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
6208 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006209 emsg(_(e_missing_catch_or_finally));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006210 return NULL;
6211 }
6212
6213 // Fill in the "end" label in jumps at the end of the blocks, if not done
6214 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006215 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006216
6217 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaare8593122020-07-18 15:17:02 +02006218 if (isn->isn_arg.try.try_catch == 0)
6219 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006220 if (isn->isn_arg.try.try_finally == 0)
6221 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaare8593122020-07-18 15:17:02 +02006222
6223 if (scope->se_u.se_try.ts_catch_label != 0)
6224 {
6225 // Last catch without match jumps here
6226 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
6227 isn->isn_arg.jump.jump_where = instr->ga_len;
6228 }
6229
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006230 compile_endblock(cctx);
6231
6232 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
6233 return NULL;
6234 return arg;
6235}
6236
6237/*
6238 * compile "throw {expr}"
6239 */
6240 static char_u *
6241compile_throw(char_u *arg, cctx_T *cctx UNUSED)
6242{
6243 char_u *p = skipwhite(arg);
6244
Bram Moolenaara5565e42020-05-09 15:44:01 +02006245 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006246 return NULL;
6247 if (may_generate_2STRING(-1, cctx) == FAIL)
6248 return NULL;
6249 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
6250 return NULL;
6251
6252 return p;
6253}
6254
6255/*
6256 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006257 * compile "echomsg expr"
6258 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01006259 * compile "execute expr"
6260 */
6261 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006262compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006263{
6264 char_u *p = arg;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02006265 char_u *prev;
Bram Moolenaarad39c092020-02-26 18:23:43 +01006266 int count = 0;
6267
6268 for (;;)
6269 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006270 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006271 return NULL;
6272 ++count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02006273 prev = p;
Bram Moolenaarad39c092020-02-26 18:23:43 +01006274 p = skipwhite(p);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02006275 if (ends_excmd2(prev, p))
Bram Moolenaarad39c092020-02-26 18:23:43 +01006276 break;
6277 }
6278
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006279 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
6280 generate_ECHO(cctx, cmdidx == CMD_echo, count);
6281 else if (cmdidx == CMD_execute)
6282 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
6283 else if (cmdidx == CMD_echomsg)
6284 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
6285 else
6286 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006287 return p;
6288}
6289
6290/*
Bram Moolenaarc3516f72020-09-08 22:45:35 +02006291 * :put r
6292 * :put ={expr}
6293 */
6294 static char_u *
6295compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
6296{
6297 char_u *line = arg;
6298 linenr_T lnum;
6299 char *errormsg;
6300 int above = FALSE;
6301
6302 if (*arg == '!')
6303 {
6304 above = TRUE;
6305 line = skipwhite(arg + 1);
6306 }
6307 eap->regname = *line;
6308
6309 if (eap->regname == '=')
6310 {
6311 char_u *p = line + 1;
6312
6313 if (compile_expr0(&p, cctx) == FAIL)
6314 return NULL;
6315 line = p;
6316 }
6317 else if (eap->regname != NUL)
6318 ++line;
6319
6320 // TODO: if the range is something like "$" need to evaluate at runtime
6321 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
6322 return NULL;
6323 if (eap->addr_count == 0)
6324 lnum = -1;
6325 else
6326 lnum = eap->line2;
6327 if (above)
6328 --lnum;
6329
6330 generate_PUT(cctx, eap->regname, lnum);
6331 return line;
6332}
6333
6334/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006335 * A command that is not compiled, execute with legacy code.
6336 */
6337 static char_u *
6338compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
6339{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006340 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006341 int has_expr = FALSE;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006342 char_u *nextcmd = (char_u *)"";
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006343
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006344 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006345 goto theend;
6346
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006347 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006348 {
6349 long argt = excmd_get_argt(eap->cmdidx);
6350 int usefilter = FALSE;
6351
6352 has_expr = argt & (EX_XFILE | EX_EXPAND);
6353
6354 // If the command can be followed by a bar, find the bar and truncate
6355 // it, so that the following command can be compiled.
6356 // The '|' is overwritten with a NUL, it is put back below.
6357 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
6358 && *eap->arg == '!')
6359 // :w !filter or :r !filter or :r! filter
6360 usefilter = TRUE;
6361 if ((argt & EX_TRLBAR) && !usefilter)
6362 {
Bram Moolenaarb8a92962020-08-20 18:02:47 +02006363 eap->argt = argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006364 separate_nextcmd(eap);
6365 if (eap->nextcmd != NULL)
6366 nextcmd = eap->nextcmd;
6367 }
6368 }
6369
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006370 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
6371 {
6372 // expand filename in "syntax include [@group] filename"
6373 has_expr = TRUE;
6374 eap->arg = skipwhite(eap->arg + 7);
6375 if (*eap->arg == '@')
6376 eap->arg = skiptowhite(eap->arg);
6377 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006378
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006379 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006380 {
6381 int count = 0;
6382 char_u *start = skipwhite(line);
6383
6384 // :cmd xxx`=expr1`yyy`=expr2`zzz
6385 // PUSHS ":cmd xxx"
6386 // eval expr1
6387 // PUSHS "yyy"
6388 // eval expr2
6389 // PUSHS "zzz"
6390 // EXECCONCAT 5
6391 for (;;)
6392 {
6393 if (p > start)
6394 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02006395 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006396 ++count;
6397 }
6398 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006399 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006400 return NULL;
6401 may_generate_2STRING(-1, cctx);
6402 ++count;
6403 p = skipwhite(p);
6404 if (*p != '`')
6405 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006406 emsg(_(e_missing_backtick));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006407 return NULL;
6408 }
6409 start = p + 1;
6410
6411 p = (char_u *)strstr((char *)start, "`=");
6412 if (p == NULL)
6413 {
6414 if (*skipwhite(start) != NUL)
6415 {
6416 generate_PUSHS(cctx, vim_strsave(start));
6417 ++count;
6418 }
6419 break;
6420 }
6421 }
6422 generate_EXECCONCAT(cctx, count);
6423 }
6424 else
6425 generate_EXEC(cctx, line);
6426
6427theend:
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006428 if (*nextcmd != NUL)
6429 {
6430 // the parser expects a pointer to the bar, put it back
6431 --nextcmd;
6432 *nextcmd = '|';
6433 }
6434
6435 return nextcmd;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006436}
6437
6438/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02006439 * Add a function to the list of :def functions.
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02006440 * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
Bram Moolenaar09689a02020-05-09 22:50:08 +02006441 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02006442 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02006443add_def_function(ufunc_T *ufunc)
6444{
6445 dfunc_T *dfunc;
6446
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02006447 if (def_functions.ga_len == 0)
6448 {
6449 // The first position is not used, so that a zero uf_dfunc_idx means it
6450 // wasn't set.
6451 if (ga_grow(&def_functions, 1) == FAIL)
6452 return FAIL;
6453 ++def_functions.ga_len;
6454 }
6455
Bram Moolenaar09689a02020-05-09 22:50:08 +02006456 // Add the function to "def_functions".
6457 if (ga_grow(&def_functions, 1) == FAIL)
6458 return FAIL;
6459 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
6460 CLEAR_POINTER(dfunc);
6461 dfunc->df_idx = def_functions.ga_len;
6462 ufunc->uf_dfunc_idx = dfunc->df_idx;
6463 dfunc->df_ufunc = ufunc;
6464 ++def_functions.ga_len;
6465 return OK;
6466}
6467
6468/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006469 * After ex_function() has collected all the function lines: parse and compile
6470 * the lines into instructions.
6471 * Adds the function to "def_functions".
6472 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
6473 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006474 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006475 * This can be used recursively through compile_lambda(), which may reallocate
6476 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02006477 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006478 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02006479 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006480compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006481{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006482 char_u *line = NULL;
6483 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006484 char *errormsg = NULL; // error message
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006485 cctx_T cctx;
6486 garray_T *instr;
6487 int called_emsg_before = called_emsg;
6488 int ret = FAIL;
6489 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006490 int do_estack_push;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006491 int emsg_before = called_emsg;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02006492 int new_def_function = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006493
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006494 // When using a function that was compiled before: Free old instructions.
6495 // Otherwise add a new entry in "def_functions".
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02006496 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006497 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02006498 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6499 + ufunc->uf_dfunc_idx;
Bram Moolenaar09689a02020-05-09 22:50:08 +02006500 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006501 }
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02006502 else
6503 {
6504 if (add_def_function(ufunc) == FAIL)
6505 return FAIL;
6506 new_def_function = TRUE;
6507 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006508
Bram Moolenaar985116a2020-07-12 17:31:09 +02006509 ufunc->uf_def_status = UF_COMPILING;
6510
Bram Moolenaara80faa82020-04-12 19:37:17 +02006511 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006512 cctx.ctx_ufunc = ufunc;
6513 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006514 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006515 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
6516 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
6517 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
6518 cctx.ctx_type_list = &ufunc->uf_type_list;
6519 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
6520 instr = &cctx.ctx_instr;
6521
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006522 // Set the context to the function, it may be compiled when called from
6523 // another script. Set the script version to the most modern one.
6524 // The line number will be set in next_line_from_context().
6525 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006526 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
6527
Bram Moolenaar25e0f582020-05-25 22:36:50 +02006528 // Make sure error messages are OK.
6529 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
6530 if (do_estack_push)
6531 estack_push_ufunc(ufunc, 1);
6532
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006533 if (ufunc->uf_def_args.ga_len > 0)
6534 {
6535 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006536 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006537 int i;
6538 char_u *arg;
6539 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
Bram Moolenaarb8070e32020-07-23 20:56:04 +02006540 int did_set_arg_type = FALSE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006541
6542 // Produce instructions for the default values of optional arguments.
6543 // Store the instruction index in uf_def_arg_idx[] so that we know
6544 // where to start when the function is called, depending on the number
6545 // of arguments.
6546 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
6547 if (ufunc->uf_def_arg_idx == NULL)
6548 goto erret;
6549 for (i = 0; i < count; ++i)
6550 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006551 garray_T *stack = &cctx.ctx_type_stack;
6552 type_T *val_type;
6553 int arg_idx = first_def_arg + i;
6554
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006555 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6556 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02006557 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006558 goto erret;
6559
6560 // If no type specified use the type of the default value.
6561 // Otherwise check that the default value type matches the
6562 // specified type.
6563 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6564 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02006565 {
6566 did_set_arg_type = TRUE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006567 ufunc->uf_arg_types[arg_idx] = val_type;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02006568 }
Bram Moolenaar8b565c22020-08-30 23:24:20 +02006569 else if (check_type(ufunc->uf_arg_types[arg_idx], val_type,
6570 TRUE, arg_idx + 1) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006571 goto erret;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006572
6573 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006574 goto erret;
6575 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006576 ufunc->uf_def_arg_idx[count] = instr->ga_len;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02006577
6578 if (did_set_arg_type)
6579 set_function_type(ufunc);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006580 }
6581
6582 /*
6583 * Loop over all the lines of the function and generate instructions.
6584 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006585 for (;;)
6586 {
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02006587 exarg_T ea;
6588 cmdmod_T save_cmdmod;
6589 int starts_with_colon = FALSE;
6590 char_u *cmd;
6591 int save_msg_scroll = msg_scroll;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006592
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006593 // Bail out on the first error to avoid a flood of errors and report
6594 // the right line number when inside try/catch.
6595 if (emsg_before != called_emsg)
6596 goto erret;
6597
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006598 if (line != NULL && *line == '|')
6599 // the line continues after a '|'
6600 ++line;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02006601 else if (line != NULL && *skipwhite(line) != NUL
Bram Moolenaar7a092242020-04-16 22:10:49 +02006602 && !(*line == '#' && (line == cctx.ctx_line_start
6603 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006604 {
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02006605 semsg(_(e_trailing_arg), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006606 goto erret;
6607 }
6608 else
6609 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02006610 line = next_line_from_context(&cctx, FALSE);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006611 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006612 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006613 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006614 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006615 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006616
Bram Moolenaara80faa82020-04-12 19:37:17 +02006617 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006618 ea.cmdlinep = &line;
6619 ea.cmd = skipwhite(line);
6620
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006621 // Some things can be recognized by the first character.
6622 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006623 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006624 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006625 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006626 if (ea.cmd[1] != '{')
6627 {
6628 line = (char_u *)"";
6629 continue;
6630 }
6631 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006632
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006633 case '}':
6634 {
6635 // "}" ends a block scope
6636 scopetype_T stype = cctx.ctx_scope == NULL
6637 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006638
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006639 if (stype == BLOCK_SCOPE)
6640 {
6641 compile_endblock(&cctx);
6642 line = ea.cmd;
6643 }
6644 else
6645 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006646 emsg(_(e_using_rcurly_outside_if_block_scope));
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006647 goto erret;
6648 }
6649 if (line != NULL)
6650 line = skipwhite(ea.cmd + 1);
6651 continue;
6652 }
6653
6654 case '{':
6655 // "{" starts a block scope
6656 // "{'a': 1}->func() is something else
6657 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6658 {
6659 line = compile_block(ea.cmd, &cctx);
6660 continue;
6661 }
6662 break;
6663
6664 case ':':
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006665 starts_with_colon = TRUE;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006666 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006667 }
6668
6669 /*
6670 * COMMAND MODIFIERS
6671 */
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02006672 save_cmdmod = cmdmod;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006673 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6674 {
6675 if (errormsg != NULL)
6676 goto erret;
6677 // empty line or comment
6678 line = (char_u *)"";
6679 continue;
6680 }
Bram Moolenaar47e7d702020-07-05 18:18:42 +02006681 // TODO: use modifiers in the command
6682 undo_cmdmod(&ea, save_msg_scroll);
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02006683 cmdmod = save_cmdmod;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006684
6685 // Skip ":call" to get to the function name.
Bram Moolenaar575f24b2020-08-12 14:21:11 +02006686 p = ea.cmd;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006687 if (checkforcmd(&ea.cmd, "call", 3))
Bram Moolenaar575f24b2020-08-12 14:21:11 +02006688 {
6689 if (*ea.cmd == '(')
6690 // not for "call()"
6691 ea.cmd = p;
6692 else
6693 ea.cmd = skipwhite(ea.cmd);
6694 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006695
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006696 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006697 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006698 char_u *pskip;
6699
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006700 // Assuming the command starts with a variable or function name,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006701 // find what follows.
6702 // Skip over "var.member", "var[idx]" and the like.
6703 // Also "&opt = val", "$ENV = val" and "@r = val".
6704 pskip = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006705 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006706 p = to_name_end(pskip, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006707 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006708 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006709 char_u *var_end;
6710 int oplen;
6711 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006712
Bram Moolenaar65821722020-08-02 18:58:54 +02006713 if (ea.cmd[0] == '@')
6714 var_end = ea.cmd + 2;
6715 else
6716 var_end = find_name_end(pskip, NULL, NULL,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006717 FNE_CHECK_START | FNE_INCL_BR);
6718 oplen = assignment_len(skipwhite(var_end), &heredoc);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006719 if (oplen > 0)
6720 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006721 size_t len = p - ea.cmd;
6722
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006723 // Recognize an assignment if we recognize the variable
6724 // name:
6725 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006726 // "local = expr" where "local" is a local var.
6727 // "script = expr" where "script" is a script-local var.
6728 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006729 // "&opt = expr"
6730 // "$ENV = expr"
6731 // "@r = expr"
6732 if (*ea.cmd == '&'
6733 || *ea.cmd == '$'
6734 || *ea.cmd == '@'
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006735 || ((len) > 2 && ea.cmd[1] == ':')
6736 || lookup_local(ea.cmd, len, &cctx) != NULL
6737 || lookup_arg(ea.cmd, len, NULL, NULL,
6738 NULL, &cctx) == OK
Bram Moolenaar53900992020-08-22 19:02:02 +02006739 || lookup_script(ea.cmd, len, FALSE) == OK
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006740 || find_imported(ea.cmd, len, &cctx) != NULL)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006741 {
6742 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006743 if (line == NULL || line == ea.cmd)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006744 goto erret;
6745 continue;
6746 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006747 }
6748 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006749
6750 if (*ea.cmd == '[')
6751 {
6752 // [var, var] = expr
6753 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6754 if (line == NULL)
6755 goto erret;
6756 if (line != ea.cmd)
6757 continue;
6758 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006759 }
6760
6761 /*
6762 * COMMAND after range
Bram Moolenaar3d48e252020-07-15 14:15:52 +02006763 * 'text'->func() should not be confused with 'a mark
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006764 */
Bram Moolenaardf069ee2020-06-22 23:02:51 +02006765 cmd = ea.cmd;
Bram Moolenaar7c5ad342020-08-12 15:48:55 +02006766 if (*cmd != '\'' || starts_with_colon)
Bram Moolenaardf069ee2020-06-22 23:02:51 +02006767 {
Bram Moolenaar3d48e252020-07-15 14:15:52 +02006768 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02006769 if (ea.cmd > cmd)
Bram Moolenaar3d48e252020-07-15 14:15:52 +02006770 {
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02006771 if (!starts_with_colon)
6772 {
6773 emsg(_(e_colon_required_before_a_range));
6774 goto erret;
6775 }
6776 if (ends_excmd2(line, ea.cmd))
6777 {
6778 // A range without a command: jump to the line.
6779 // TODO: compile to a more efficient command, possibly
6780 // calling parse_cmd_address().
6781 ea.cmdidx = CMD_SIZE;
6782 line = compile_exec(line, &ea, &cctx);
6783 goto nextline;
6784 }
Bram Moolenaar3d48e252020-07-15 14:15:52 +02006785 }
Bram Moolenaardf069ee2020-06-22 23:02:51 +02006786 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006787 p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006788 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006789 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006790
6791 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6792 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006793 if (cctx.ctx_skip == SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006794 {
6795 line += STRLEN(line);
6796 continue;
6797 }
6798
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006799 // Expression or function call.
Bram Moolenaar007f9d62020-07-06 23:04:49 +02006800 if (ea.cmdidx != CMD_eval)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006801 {
Bram Moolenaar007f9d62020-07-06 23:04:49 +02006802 // CMD_let cannot happen, compile_assignment() above is used
6803 iemsg("Command from find_ex_command() not handled");
6804 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006805 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006806 }
6807
6808 p = skipwhite(p);
6809
Bram Moolenaar3988f642020-08-27 22:43:03 +02006810 if (cctx.ctx_had_return
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006811 && ea.cmdidx != CMD_elseif
6812 && ea.cmdidx != CMD_else
Bram Moolenaarefd88552020-06-18 20:50:10 +02006813 && ea.cmdidx != CMD_endif
6814 && ea.cmdidx != CMD_endfor
6815 && ea.cmdidx != CMD_endwhile
6816 && ea.cmdidx != CMD_catch
6817 && ea.cmdidx != CMD_finally
6818 && ea.cmdidx != CMD_endtry)
6819 {
Bram Moolenaar3988f642020-08-27 22:43:03 +02006820 emsg(_(e_unreachable_code_after_return));
6821 goto erret;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006822 }
6823
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006824 switch (ea.cmdidx)
6825 {
6826 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006827 ea.arg = p;
6828 line = compile_nested_function(&ea, &cctx);
6829 break;
6830
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006831 case CMD_function:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006832 // TODO: should we allow this, e.g. to declare a global
6833 // function?
6834 emsg(_(e_cannot_use_function_inside_def));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006835 goto erret;
6836
6837 case CMD_return:
6838 line = compile_return(p, set_return_type, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006839 cctx.ctx_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006840 break;
6841
6842 case CMD_let:
6843 case CMD_const:
6844 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006845 if (line == p)
6846 line = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006847 break;
6848
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006849 case CMD_unlet:
6850 case CMD_unlockvar:
6851 case CMD_lockvar:
6852 line = compile_unletlock(p, &ea, &cctx);
6853 break;
6854
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006855 case CMD_import:
6856 line = compile_import(p, &cctx);
6857 break;
6858
6859 case CMD_if:
6860 line = compile_if(p, &cctx);
6861 break;
6862 case CMD_elseif:
6863 line = compile_elseif(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006864 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006865 break;
6866 case CMD_else:
6867 line = compile_else(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006868 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006869 break;
6870 case CMD_endif:
6871 line = compile_endif(p, &cctx);
6872 break;
6873
6874 case CMD_while:
6875 line = compile_while(p, &cctx);
6876 break;
6877 case CMD_endwhile:
6878 line = compile_endwhile(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006879 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006880 break;
6881
6882 case CMD_for:
6883 line = compile_for(p, &cctx);
6884 break;
6885 case CMD_endfor:
6886 line = compile_endfor(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006887 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006888 break;
6889 case CMD_continue:
6890 line = compile_continue(p, &cctx);
6891 break;
6892 case CMD_break:
6893 line = compile_break(p, &cctx);
6894 break;
6895
6896 case CMD_try:
6897 line = compile_try(p, &cctx);
6898 break;
6899 case CMD_catch:
6900 line = compile_catch(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006901 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006902 break;
6903 case CMD_finally:
6904 line = compile_finally(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006905 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006906 break;
6907 case CMD_endtry:
6908 line = compile_endtry(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006909 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006910 break;
6911 case CMD_throw:
6912 line = compile_throw(p, &cctx);
6913 break;
6914
Bram Moolenaar007f9d62020-07-06 23:04:49 +02006915 case CMD_eval:
6916 if (compile_expr0(&p, &cctx) == FAIL)
6917 goto erret;
6918
Bram Moolenaar3988f642020-08-27 22:43:03 +02006919 // drop the result
Bram Moolenaar007f9d62020-07-06 23:04:49 +02006920 generate_instr_drop(&cctx, ISN_DROP, 1);
6921
6922 line = skipwhite(p);
6923 break;
6924
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006925 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006926 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006927 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006928 case CMD_echomsg:
6929 case CMD_echoerr:
6930 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006931 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006932
Bram Moolenaarc3516f72020-09-08 22:45:35 +02006933 case CMD_put:
6934 ea.cmd = cmd;
6935 line = compile_put(p, &ea, &cctx);
6936 break;
6937
Bram Moolenaar3988f642020-08-27 22:43:03 +02006938 // TODO: any other commands with an expression argument?
Bram Moolenaardf069ee2020-06-22 23:02:51 +02006939
Bram Moolenaarae616492020-07-28 20:07:27 +02006940 case CMD_append:
6941 case CMD_change:
6942 case CMD_insert:
Bram Moolenaarf5a48012020-08-01 17:00:03 +02006943 case CMD_t:
Bram Moolenaarae616492020-07-28 20:07:27 +02006944 case CMD_xit:
6945 not_in_vim9(&ea);
6946 goto erret;
6947
Bram Moolenaar002262f2020-07-08 17:47:57 +02006948 case CMD_SIZE:
Bram Moolenaar3988f642020-08-27 22:43:03 +02006949 if (cctx.ctx_skip != SKIP_YES)
6950 {
6951 semsg(_(e_invalid_command_str), ea.cmd);
6952 goto erret;
6953 }
6954 // We don't check for a next command here.
6955 line = (char_u *)"";
6956 break;
Bram Moolenaar002262f2020-07-08 17:47:57 +02006957
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006958 default:
Bram Moolenaar5163fcc2020-08-27 23:37:09 +02006959 if (cctx.ctx_skip == SKIP_YES)
6960 {
6961 // We don't check for a next command here.
6962 line = (char_u *)"";
6963 }
6964 else
6965 {
6966 // Not recognized, execute with do_cmdline_cmd().
6967 ea.arg = p;
6968 line = compile_exec(line, &ea, &cctx);
6969 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006970 break;
6971 }
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02006972nextline:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006973 if (line == NULL)
6974 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006975 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006976
6977 if (cctx.ctx_type_stack.ga_len < 0)
6978 {
6979 iemsg("Type stack underflow");
6980 goto erret;
6981 }
6982 }
6983
6984 if (cctx.ctx_scope != NULL)
6985 {
6986 if (cctx.ctx_scope->se_type == IF_SCOPE)
6987 emsg(_(e_endif));
6988 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6989 emsg(_(e_endwhile));
6990 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6991 emsg(_(e_endfor));
6992 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006993 emsg(_(e_missing_rcurly));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006994 goto erret;
6995 }
6996
Bram Moolenaarefd88552020-06-18 20:50:10 +02006997 if (!cctx.ctx_had_return)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006998 {
6999 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
7000 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02007001 emsg(_(e_missing_return_statement));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007002 goto erret;
7003 }
7004
7005 // Return zero if there is no return at the end.
7006 generate_PUSHNR(&cctx, 0);
7007 generate_instr(&cctx, ISN_RETURN);
7008 }
7009
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007010 {
7011 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7012 + ufunc->uf_dfunc_idx;
7013 dfunc->df_deleted = FALSE;
7014 dfunc->df_instr = instr->ga_data;
7015 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007016 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02007017 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007018 if (cctx.ctx_outer_used)
7019 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007020 ufunc->uf_def_status = UF_COMPILED;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007021 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007022
7023 ret = OK;
7024
7025erret:
7026 if (ret == FAIL)
7027 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01007028 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007029 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7030 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007031
7032 for (idx = 0; idx < instr->ga_len; ++idx)
7033 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007034 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01007035
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007036 // If using the last entry in the table and it was added above, we
7037 // might as well remove it.
7038 if (!dfunc->df_deleted && new_def_function
Bram Moolenaar45a15082020-05-25 00:28:33 +02007039 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007040 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01007041 --def_functions.ga_len;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007042 ufunc->uf_dfunc_idx = 0;
7043 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007044 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007045
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007046 while (cctx.ctx_scope != NULL)
7047 drop_scope(&cctx);
7048
Bram Moolenaar20431c92020-03-20 18:39:46 +01007049 // Don't execute this function body.
7050 ga_clear_strings(&ufunc->uf_lines);
7051
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007052 if (errormsg != NULL)
7053 emsg(errormsg);
7054 else if (called_emsg == called_emsg_before)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02007055 emsg(_(e_compile_def_function_failed));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007056 }
7057
7058 current_sctx = save_current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007059 if (do_estack_push)
7060 estack_pop();
7061
Bram Moolenaar20431c92020-03-20 18:39:46 +01007062 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007063 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007064 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02007065 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007066}
7067
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02007068 void
7069set_function_type(ufunc_T *ufunc)
7070{
7071 int varargs = ufunc->uf_va_name != NULL;
7072 int argcount = ufunc->uf_args.ga_len;
7073
7074 // Create a type for the function, with the return type and any
7075 // argument types.
7076 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
7077 // The type is included in "tt_args".
7078 if (argcount > 0 || varargs)
7079 {
7080 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
7081 argcount, &ufunc->uf_type_list);
7082 // Add argument types to the function type.
7083 if (func_type_add_arg_types(ufunc->uf_func_type,
7084 argcount + varargs,
7085 &ufunc->uf_type_list) == FAIL)
7086 return;
7087 ufunc->uf_func_type->tt_argcount = argcount + varargs;
7088 ufunc->uf_func_type->tt_min_argcount =
7089 argcount - ufunc->uf_def_args.ga_len;
7090 if (ufunc->uf_arg_types == NULL)
7091 {
7092 int i;
7093
7094 // lambda does not have argument types.
7095 for (i = 0; i < argcount; ++i)
7096 ufunc->uf_func_type->tt_args[i] = &t_any;
7097 }
7098 else
7099 mch_memmove(ufunc->uf_func_type->tt_args,
7100 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
7101 if (varargs)
7102 {
7103 ufunc->uf_func_type->tt_args[argcount] =
7104 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
7105 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
7106 }
7107 }
7108 else
7109 // No arguments, can use a predefined type.
7110 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
7111 argcount, &ufunc->uf_type_list);
7112}
7113
7114
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007115/*
7116 * Delete an instruction, free what it contains.
7117 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01007118 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007119delete_instr(isn_T *isn)
7120{
7121 switch (isn->isn_type)
7122 {
7123 case ISN_EXEC:
7124 case ISN_LOADENV:
7125 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02007126 case ISN_LOADB:
7127 case ISN_LOADW:
7128 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007129 case ISN_LOADOPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007130 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007131 case ISN_PUSHEXC:
7132 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007133 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007134 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02007135 case ISN_STOREB:
7136 case ISN_STOREW:
7137 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007138 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007139 vim_free(isn->isn_arg.string);
7140 break;
7141
7142 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007143 case ISN_STORES:
7144 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007145 break;
7146
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007147 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02007148 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007149 vim_free(isn->isn_arg.unlet.ul_name);
7150 break;
7151
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007152 case ISN_STOREOPT:
7153 vim_free(isn->isn_arg.storeopt.so_name);
7154 break;
7155
7156 case ISN_PUSHBLOB: // push blob isn_arg.blob
7157 blob_unref(isn->isn_arg.blob);
7158 break;
7159
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007160 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007161#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007162 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007163#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007164 break;
7165
7166 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007167#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007168 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007169#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007170 break;
7171
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007172 case ISN_UCALL:
7173 vim_free(isn->isn_arg.ufunc.cuf_name);
7174 break;
7175
Bram Moolenaar221fcc72020-05-05 19:46:20 +02007176 case ISN_FUNCREF:
7177 {
7178 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7179 + isn->isn_arg.funcref.fr_func;
7180 func_ptr_unref(dfunc->df_ufunc);
7181 }
7182 break;
7183
Bram Moolenaar38ddf332020-07-31 22:05:04 +02007184 case ISN_NEWFUNC:
Bram Moolenaarce658352020-07-31 23:47:12 +02007185 {
7186 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
7187 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
7188
7189 if (ufunc != NULL)
7190 {
7191 // Clear uf_dfunc_idx so that the function is deleted.
7192 clear_def_function(ufunc);
7193 ufunc->uf_dfunc_idx = 0;
7194 func_ptr_unref(ufunc);
7195 }
7196
7197 vim_free(lambda);
7198 vim_free(isn->isn_arg.newfunc.nf_global);
7199 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02007200 break;
7201
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007202 case ISN_2BOOL:
7203 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02007204 case ISN_2STRING_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007205 case ISN_ADDBLOB:
7206 case ISN_ADDLIST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007207 case ISN_ANYINDEX:
7208 case ISN_ANYSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007209 case ISN_BCALL:
7210 case ISN_CATCH:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007211 case ISN_CHECKLEN:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007212 case ISN_CHECKNR:
7213 case ISN_CHECKTYPE:
7214 case ISN_COMPAREANY:
7215 case ISN_COMPAREBLOB:
7216 case ISN_COMPAREBOOL:
7217 case ISN_COMPAREDICT:
7218 case ISN_COMPAREFLOAT:
7219 case ISN_COMPAREFUNC:
7220 case ISN_COMPARELIST:
7221 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007222 case ISN_COMPARESPECIAL:
7223 case ISN_COMPARESTRING:
7224 case ISN_CONCAT:
7225 case ISN_DCALL:
7226 case ISN_DROP:
7227 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007228 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007229 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007230 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007231 case ISN_EXECCONCAT:
7232 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007233 case ISN_FOR:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007234 case ISN_GETITEM:
7235 case ISN_JUMP:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02007236 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02007237 case ISN_LISTSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007238 case ISN_LOAD:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007239 case ISN_LOADBDICT:
7240 case ISN_LOADGDICT:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007241 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007242 case ISN_LOADREG:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007243 case ISN_LOADSCRIPT:
7244 case ISN_LOADTDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007245 case ISN_LOADV:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007246 case ISN_LOADWDICT:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007247 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007248 case ISN_NEGATENR:
7249 case ISN_NEWDICT:
7250 case ISN_NEWLIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007251 case ISN_OPANY:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007252 case ISN_OPFLOAT:
7253 case ISN_OPNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007254 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02007255 case ISN_PCALL_END:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007256 case ISN_PUSHBOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007257 case ISN_PUSHF:
7258 case ISN_PUSHNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007259 case ISN_PUSHSPEC:
Bram Moolenaarc3516f72020-09-08 22:45:35 +02007260 case ISN_PUT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007261 case ISN_RETURN:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007262 case ISN_SHUFFLE:
7263 case ISN_SLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007264 case ISN_STORE:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007265 case ISN_STOREDICT:
7266 case ISN_STORELIST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02007267 case ISN_STORENR:
7268 case ISN_STOREOUTER:
7269 case ISN_STOREREG:
7270 case ISN_STORESCRIPT:
7271 case ISN_STOREV:
7272 case ISN_STRINDEX:
7273 case ISN_STRSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007274 case ISN_THROW:
7275 case ISN_TRY:
7276 // nothing allocated
7277 break;
7278 }
7279}
7280
7281/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01007282 * Free all instructions for "dfunc".
7283 */
7284 static void
7285delete_def_function_contents(dfunc_T *dfunc)
7286{
7287 int idx;
7288
7289 ga_clear(&dfunc->df_def_args_isn);
7290
7291 if (dfunc->df_instr != NULL)
7292 {
7293 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
7294 delete_instr(dfunc->df_instr + idx);
7295 VIM_CLEAR(dfunc->df_instr);
7296 }
7297
7298 dfunc->df_deleted = TRUE;
7299}
7300
7301/*
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007302 * When a user function is deleted, clear the contents of any associated def
7303 * function. The position in def_functions can be re-used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007304 */
7305 void
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007306clear_def_function(ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007307{
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007308 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007309 {
7310 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7311 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007312
Bram Moolenaar20431c92020-03-20 18:39:46 +01007313 delete_def_function_contents(dfunc);
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007314 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007315 }
7316}
7317
7318#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01007319/*
7320 * Free all functions defined with ":def".
7321 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007322 void
7323free_def_functions(void)
7324{
Bram Moolenaar20431c92020-03-20 18:39:46 +01007325 int idx;
7326
7327 for (idx = 0; idx < def_functions.ga_len; ++idx)
7328 {
7329 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
7330
7331 delete_def_function_contents(dfunc);
7332 }
7333
7334 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007335}
7336#endif
7337
7338
7339#endif // FEAT_EVAL