blob: 2727c5c70bb5c566bf4553c2b614e14bab9e9e2f [file] [log] [blame]
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001/* 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 * vim9cmds.c: Dealing with compiled function expressions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19// When not generating protos this is included in proto.h
20#ifdef PROTO
21# include "vim9.h"
22#endif
23
Bram Moolenaard02dce22022-01-18 17:43:04 +000024// flag passed from compile_subscript() to compile_load_scriptvar()
25static int paren_follows_after_expr = 0;
26
Bram Moolenaardc7c3662021-12-20 15:04:29 +000027/*
28 * Generate code for any ppconst entries.
29 */
30 int
31generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
32{
33 int i;
34 int ret = OK;
35 int save_skip = cctx->ctx_skip;
36
37 cctx->ctx_skip = SKIP_NOT;
38 for (i = 0; i < ppconst->pp_used; ++i)
39 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
40 ret = FAIL;
41 ppconst->pp_used = 0;
42 cctx->ctx_skip = save_skip;
43 return ret;
44}
45
46/*
47 * Check that the last item of "ppconst" is a bool, if there is an item.
48 */
49 static int
50check_ppconst_bool(ppconst_T *ppconst)
51{
52 if (ppconst->pp_used > 0)
53 {
54 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
55 where_T where = WHERE_INIT;
56
57 return check_typval_type(&t_bool, tv, where);
58 }
59 return OK;
60}
61
62/*
63 * Clear ppconst constants. Used when failing.
64 */
65 void
66clear_ppconst(ppconst_T *ppconst)
67{
68 int i;
69
70 for (i = 0; i < ppconst->pp_used; ++i)
71 clear_tv(&ppconst->pp_tv[i]);
72 ppconst->pp_used = 0;
73}
74
75/*
76 * Compile getting a member from a list/dict/string/blob. Stack has the
77 * indexable value and the index or the two indexes of a slice.
78 * "keeping_dict" is used for dict[func](arg) to pass dict to func.
79 */
80 int
81compile_member(int is_slice, int *keeping_dict, cctx_T *cctx)
82{
Bram Moolenaar078a4612022-01-04 15:17:03 +000083 type2_T *typep;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000084 garray_T *stack = &cctx->ctx_type_stack;
85 vartype_T vartype;
86 type_T *idxtype;
87
88 // We can index a list, dict and blob. If we don't know the type
89 // we can use the index value type. If we still don't know use an "ANY"
90 // instruction.
Bram Moolenaar078a4612022-01-04 15:17:03 +000091 // TODO: what about the decl type?
92 typep = (((type2_T *)stack->ga_data) + stack->ga_len - (is_slice ? 3 : 2));
93 vartype = typep->type_curr->tt_type;
94 idxtype = (((type2_T *)stack->ga_data) + stack->ga_len - 1)->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000095 // If the index is a string, the variable must be a Dict.
Bram Moolenaar078a4612022-01-04 15:17:03 +000096 if ((typep->type_curr == &t_any || typep->type_curr == &t_unknown)
97 && idxtype == &t_string)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000098 vartype = VAR_DICT;
99 if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB)
100 {
101 if (need_type(idxtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
102 return FAIL;
103 if (is_slice)
104 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000105 idxtype = get_type_on_stack(cctx, 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000106 if (need_type(idxtype, &t_number, -2, 0, cctx,
107 FALSE, FALSE) == FAIL)
108 return FAIL;
109 }
110 }
111
112 if (vartype == VAR_DICT)
113 {
114 if (is_slice)
115 {
116 emsg(_(e_cannot_slice_dictionary));
117 return FAIL;
118 }
Bram Moolenaar078a4612022-01-04 15:17:03 +0000119 if (typep->type_curr->tt_type == VAR_DICT)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000120 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000121 typep->type_curr = typep->type_curr->tt_member;
122 if (typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000123 // empty dict was used
Bram Moolenaar078a4612022-01-04 15:17:03 +0000124 typep->type_curr = &t_any;
125 if (typep->type_decl->tt_type == VAR_DICT)
126 {
127 typep->type_decl = typep->type_decl->tt_member;
128 if (typep->type_decl == &t_unknown)
129 // empty dict was used
130 typep->type_decl = &t_any;
131 }
132 else
133 typep->type_decl = typep->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000134 }
135 else
136 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000137 if (need_type(typep->type_curr, &t_dict_any, -2, 0, cctx,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000138 FALSE, FALSE) == FAIL)
139 return FAIL;
Bram Moolenaar078a4612022-01-04 15:17:03 +0000140 typep->type_curr = &t_any;
141 typep->type_decl = &t_any;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000142 }
143 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
144 return FAIL;
145 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
146 return FAIL;
147 if (keeping_dict != NULL)
148 *keeping_dict = TRUE;
149 }
150 else if (vartype == VAR_STRING)
151 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000152 typep->type_curr = &t_string;
153 typep->type_decl = &t_string;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000154 if ((is_slice
155 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
156 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
157 return FAIL;
158 }
159 else if (vartype == VAR_BLOB)
160 {
161 if (is_slice)
162 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000163 typep->type_curr = &t_blob;
164 typep->type_decl = &t_blob;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000165 if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL)
166 return FAIL;
167 }
168 else
169 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000170 typep->type_curr = &t_number;
171 typep->type_decl = &t_number;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000172 if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL)
173 return FAIL;
174 }
175 }
Bram Moolenaar078a4612022-01-04 15:17:03 +0000176 else if (vartype == VAR_LIST || typep->type_curr == &t_any
177 || typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000178 {
179 if (is_slice)
180 {
181 if (generate_instr_drop(cctx,
182 vartype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
183 2) == FAIL)
184 return FAIL;
185 }
186 else
187 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000188 if (typep->type_curr->tt_type == VAR_LIST)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000189 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000190 typep->type_curr = typep->type_curr->tt_member;
191 if (typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000192 // empty list was used
Bram Moolenaar078a4612022-01-04 15:17:03 +0000193 typep->type_curr = &t_any;
194 if (typep->type_decl->tt_type == VAR_LIST)
195 {
196 typep->type_decl = typep->type_decl->tt_member;
197 if (typep->type_decl == &t_unknown)
198 // empty list was used
199 typep->type_decl = &t_any;
200 }
201 else
202 typep->type_decl = typep->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000203 }
204 if (generate_instr_drop(cctx,
205 vartype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1)
206 == FAIL)
207 return FAIL;
208 }
209 }
210 else
211 {
212 switch (vartype)
213 {
214 case VAR_FUNC:
215 case VAR_PARTIAL:
216 emsg(_(e_cannot_index_a_funcref));
217 break;
218 case VAR_BOOL:
219 case VAR_SPECIAL:
220 case VAR_JOB:
221 case VAR_CHANNEL:
222 case VAR_INSTR:
223 case VAR_UNKNOWN:
224 case VAR_ANY:
225 case VAR_VOID:
226 emsg(_(e_cannot_index_special_variable));
227 break;
228 default:
229 emsg(_(e_string_list_dict_or_blob_required));
230 }
231 return FAIL;
232 }
233 return OK;
234}
235
236/*
237 * Generate an instruction to load script-local variable "name", without the
238 * leading "s:".
239 * Also finds imported variables.
240 */
241 int
242compile_load_scriptvar(
243 cctx_T *cctx,
244 char_u *name, // variable NUL terminated
245 char_u *start, // start of variable
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000246 char_u **end, // end of variable, may be NULL
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000247 int error) // when TRUE may give error
248{
249 scriptitem_T *si;
250 int idx;
251 imported_T *import;
252
253 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
254 return FAIL;
255 si = SCRIPT_ITEM(current_sctx.sc_sid);
256 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000257 if (idx >= 0)
258 {
259 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
260
261 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
262 current_sctx.sc_sid, idx, sv->sv_type);
263 return OK;
264 }
265
Bram Moolenaardc4451d2022-01-09 21:36:37 +0000266 import = end == NULL ? NULL : find_imported(name, 0, FALSE, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000267 if (import != NULL)
268 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000269 char_u *p = skipwhite(*end);
270 char_u *exp_name;
271 int cc;
272 ufunc_T *ufunc;
273 type_T *type;
Bram Moolenaard041f422022-01-12 19:54:00 +0000274 int done = FALSE;
275 int res = OK;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000276
277 // Need to lookup the member.
278 if (*p != '.')
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000279 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000280 semsg(_(e_expected_dot_after_name_str), start);
281 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000282 }
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000283 ++p;
284 if (VIM_ISWHITE(*p))
285 {
286 emsg(_(e_no_white_space_allowed_after_dot));
287 return FAIL;
288 }
289
290 // isolate one name
291 exp_name = p;
292 while (eval_isnamec(*p))
293 ++p;
294 cc = *p;
295 *p = NUL;
296
Bram Moolenaard041f422022-01-12 19:54:00 +0000297 si = SCRIPT_ITEM(import->imp_sid);
298 if (si->sn_autoload_prefix != NULL
299 && si->sn_state == SN_STATE_NOT_LOADED)
300 {
301 char_u *auto_name = concat_str(si->sn_autoload_prefix, exp_name);
302
303 // autoload script must be loaded later, access by the autoload
Bram Moolenaar06b77222022-01-25 15:51:56 +0000304 // name. If a '(' follows it must be a function. Otherwise we
305 // don't know, it can be "script.Func".
Bram Moolenaard02dce22022-01-18 17:43:04 +0000306 if (cc == '(' || paren_follows_after_expr)
Bram Moolenaard041f422022-01-12 19:54:00 +0000307 res = generate_PUSHFUNC(cctx, auto_name, &t_func_any);
308 else
Bram Moolenaar06b77222022-01-25 15:51:56 +0000309 res = generate_AUTOLOAD(cctx, auto_name, &t_any);
Bram Moolenaard041f422022-01-12 19:54:00 +0000310 vim_free(auto_name);
311 done = TRUE;
312 }
313 else
314 {
315 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000316 cctx, TRUE);
Bram Moolenaard041f422022-01-12 19:54:00 +0000317 }
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000318 *p = cc;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000319 *end = p;
Bram Moolenaard041f422022-01-12 19:54:00 +0000320 if (done)
321 return res;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000322
323 if (idx < 0)
324 {
325 if (ufunc != NULL)
326 {
327 // function call or function reference
328 generate_PUSHFUNC(cctx, ufunc->uf_name, NULL);
329 return OK;
330 }
331 return FAIL;
332 }
333
334 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
335 import->imp_sid,
336 idx,
337 type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000338 return OK;
339 }
340
Bram Moolenaar62aec932022-01-29 21:45:34 +0000341 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
342 // variable is not in sn_var_vals: old style script.
343 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
344 &t_any);
345
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000346 if (error)
347 semsg(_(e_item_not_found_str), name);
348 return FAIL;
349}
350
351 static int
352generate_funcref(cctx_T *cctx, char_u *name)
353{
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000354 ufunc_T *ufunc = find_func(name, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000355
356 if (ufunc == NULL)
357 return FAIL;
358
359 // Need to compile any default values to get the argument types.
360 if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
361 && compile_def_function(ufunc, TRUE, COMPILE_TYPE(ufunc), NULL)
362 == FAIL)
363 return FAIL;
364 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
365}
366
367/*
368 * Compile a variable name into a load instruction.
369 * "end" points to just after the name.
370 * "is_expr" is TRUE when evaluating an expression, might be a funcref.
371 * When "error" is FALSE do not give an error when not found.
372 */
373 int
374compile_load(
375 char_u **arg,
376 char_u *end_arg,
377 cctx_T *cctx,
378 int is_expr,
379 int error)
380{
381 type_T *type;
382 char_u *name = NULL;
383 char_u *end = end_arg;
384 int res = FAIL;
385 int prev_called_emsg = called_emsg;
386
387 if (*(*arg + 1) == ':')
388 {
389 if (end <= *arg + 2)
390 {
391 isntype_T isn_type;
392
393 // load dictionary of namespace
394 switch (**arg)
395 {
396 case 'g': isn_type = ISN_LOADGDICT; break;
397 case 'w': isn_type = ISN_LOADWDICT; break;
398 case 't': isn_type = ISN_LOADTDICT; break;
399 case 'b': isn_type = ISN_LOADBDICT; break;
400 default:
401 semsg(_(e_namespace_not_supported_str), *arg);
402 goto theend;
403 }
404 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
405 goto theend;
406 res = OK;
407 }
408 else
409 {
410 isntype_T isn_type = ISN_DROP;
411
412 // load namespaced variable
413 name = vim_strnsave(*arg + 2, end - (*arg + 2));
414 if (name == NULL)
415 return FAIL;
416
417 switch (**arg)
418 {
419 case 'v': res = generate_LOADV(cctx, name, error);
420 break;
421 case 's': if (is_expr && ASCII_ISUPPER(*name)
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000422 && find_func(name, FALSE) != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000423 res = generate_funcref(cctx, name);
424 else
425 res = compile_load_scriptvar(cctx, name,
426 NULL, &end, error);
427 break;
428 case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
429 {
430 if (is_expr && ASCII_ISUPPER(*name)
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000431 && find_func(name, FALSE) != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000432 res = generate_funcref(cctx, name);
433 else
434 isn_type = ISN_LOADG;
435 }
436 else
437 {
438 isn_type = ISN_LOADAUTO;
439 vim_free(name);
440 name = vim_strnsave(*arg, end - *arg);
441 if (name == NULL)
442 return FAIL;
443 }
444 break;
445 case 'w': isn_type = ISN_LOADW; break;
446 case 't': isn_type = ISN_LOADT; break;
447 case 'b': isn_type = ISN_LOADB; break;
448 default: // cannot happen, just in case
449 semsg(_(e_namespace_not_supported_str), *arg);
450 goto theend;
451 }
452 if (isn_type != ISN_DROP)
453 {
454 // Global, Buffer-local, Window-local and Tabpage-local
455 // variables can be defined later, thus we don't check if it
456 // exists, give an error at runtime.
Bram Moolenaarfa46ead2021-12-22 13:18:39 +0000457 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000458 }
459 }
460 }
461 else
462 {
463 size_t len = end - *arg;
464 int idx;
465 int gen_load = FALSE;
466 int gen_load_outer = 0;
467
468 name = vim_strnsave(*arg, end - *arg);
469 if (name == NULL)
470 return FAIL;
471
472 if (vim_strchr(name, AUTOLOAD_CHAR) != NULL)
473 {
474 script_autoload(name, FALSE);
475 res = generate_LOAD(cctx, ISN_LOADAUTO, 0, name, &t_any);
476 }
477 else if (arg_exists(*arg, len, &idx, &type, &gen_load_outer, cctx)
478 == OK)
479 {
480 if (gen_load_outer == 0)
481 gen_load = TRUE;
482 }
483 else
484 {
485 lvar_T lvar;
486
487 if (lookup_local(*arg, len, &lvar, cctx) == OK)
488 {
489 type = lvar.lv_type;
490 idx = lvar.lv_idx;
491 if (lvar.lv_from_outer != 0)
492 gen_load_outer = lvar.lv_from_outer;
493 else
494 gen_load = TRUE;
495 }
496 else
497 {
498 // "var" can be script-local even without using "s:" if it
499 // already exists in a Vim9 script or when it's imported.
500 if (script_var_exists(*arg, len, cctx) == OK
Bram Moolenaardc4451d2022-01-09 21:36:37 +0000501 || find_imported(name, 0, FALSE, cctx) != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000502 res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
503
504 // When evaluating an expression and the name starts with an
505 // uppercase letter it can be a user defined function.
506 // generate_funcref() will fail if the function can't be found.
507 if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
508 res = generate_funcref(cctx, name);
509 }
510 }
511 if (gen_load)
512 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
513 if (gen_load_outer > 0)
514 {
515 res = generate_LOADOUTER(cctx, idx, gen_load_outer, type);
516 cctx->ctx_outer_used = TRUE;
517 }
518 }
519
520 *arg = end;
521
522theend:
523 if (res == FAIL && error && called_emsg == prev_called_emsg)
524 semsg(_(e_variable_not_found_str), name);
525 vim_free(name);
526 return res;
527}
528
529/*
530 * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR.
531 * Returns FAIL if compilation fails.
532 */
533 static int
534compile_string(isn_T *isn, cctx_T *cctx)
535{
536 char_u *s = isn->isn_arg.string;
537 garray_T save_ga = cctx->ctx_instr;
538 int expr_res;
539 int trailing_error;
540 int instr_count;
541 isn_T *instr = NULL;
542
543 // Remove the string type from the stack.
544 --cctx->ctx_type_stack.ga_len;
545
546 // Temporarily reset the list of instructions so that the jump labels are
547 // correct.
548 cctx->ctx_instr.ga_len = 0;
549 cctx->ctx_instr.ga_maxlen = 0;
550 cctx->ctx_instr.ga_data = NULL;
551 expr_res = compile_expr0(&s, cctx);
552 s = skipwhite(s);
553 trailing_error = *s != NUL;
554
555 if (expr_res == FAIL || trailing_error
556 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
557 {
558 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +0000559 semsg(_(e_trailing_characters_str), s);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000560 clear_instr_ga(&cctx->ctx_instr);
561 cctx->ctx_instr = save_ga;
562 ++cctx->ctx_type_stack.ga_len;
563 return FAIL;
564 }
565
566 // Move the generated instructions into the ISN_INSTR instruction, then
567 // restore the list of instructions.
568 instr_count = cctx->ctx_instr.ga_len;
569 instr = cctx->ctx_instr.ga_data;
570 instr[instr_count].isn_type = ISN_FINISH;
571
572 cctx->ctx_instr = save_ga;
573 vim_free(isn->isn_arg.string);
574 isn->isn_type = ISN_INSTR;
575 isn->isn_arg.instr = instr;
576 return OK;
577}
578
579/*
580 * Compile the argument expressions.
581 * "arg" points to just after the "(" and is advanced to after the ")"
582 */
583 static int
584compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, int is_searchpair)
585{
586 char_u *p = *arg;
587 char_u *whitep = *arg;
588 int must_end = FALSE;
589 int instr_count;
590
591 for (;;)
592 {
593 if (may_get_next_line(whitep, &p, cctx) == FAIL)
594 goto failret;
595 if (*p == ')')
596 {
597 *arg = p + 1;
598 return OK;
599 }
600 if (must_end)
601 {
602 semsg(_(e_missing_comma_before_argument_str), p);
603 return FAIL;
604 }
605
606 instr_count = cctx->ctx_instr.ga_len;
607 if (compile_expr0(&p, cctx) == FAIL)
608 return FAIL;
609 ++*argcount;
610
611 if (is_searchpair && *argcount == 5
612 && cctx->ctx_instr.ga_len == instr_count + 1)
613 {
614 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
615
616 // {skip} argument of searchpair() can be compiled if not empty
617 if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL)
618 compile_string(isn, cctx);
619 }
620
621 if (*p != ',' && *skipwhite(p) == ',')
622 {
623 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
624 p = skipwhite(p);
625 }
626 if (*p == ',')
627 {
628 ++p;
629 if (*p != NUL && !VIM_ISWHITE(*p))
630 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
631 }
632 else
633 must_end = TRUE;
634 whitep = p;
635 p = skipwhite(p);
636 }
637failret:
638 emsg(_(e_missing_closing_paren));
639 return FAIL;
640}
641
642/*
643 * Compile a function call: name(arg1, arg2)
644 * "arg" points to "name", "arg + varlen" to the "(".
645 * "argcount_init" is 1 for "value->method()"
646 * Instructions:
647 * EVAL arg1
648 * EVAL arg2
649 * BCALL / DCALL / UCALL
650 */
651 static int
652compile_call(
653 char_u **arg,
654 size_t varlen,
655 cctx_T *cctx,
656 ppconst_T *ppconst,
657 int argcount_init)
658{
659 char_u *name = *arg;
660 char_u *p;
661 int argcount = argcount_init;
662 char_u namebuf[100];
663 char_u fname_buf[FLEN_FIXED + 1];
664 char_u *tofree = NULL;
665 int error = FCERR_NONE;
666 ufunc_T *ufunc = NULL;
667 int res = FAIL;
668 int is_autoload;
Bram Moolenaar62aec932022-01-29 21:45:34 +0000669 int has_g_namespace;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000670 int is_searchpair;
Bram Moolenaarf67c7172022-01-19 17:23:05 +0000671 imported_T *import;
672
673 if (varlen >= sizeof(namebuf))
674 {
675 semsg(_(e_name_too_long_str), name);
676 return FAIL;
677 }
678 vim_strncpy(namebuf, *arg, varlen);
679
680 import = find_imported(name, varlen, FALSE, cctx);
681 if (import != NULL)
682 {
683 semsg(_(e_cannot_use_str_itself_it_is_imported), namebuf);
684 return FAIL;
685 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000686
687 // We can evaluate "has('name')" at compile time.
688 // We always evaluate "exists_compiled()" at compile time.
689 if ((varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
690 || (varlen == 15 && STRNCMP(*arg, "exists_compiled", 6) == 0))
691 {
692 char_u *s = skipwhite(*arg + varlen + 1);
693 typval_T argvars[2];
694 int is_has = **arg == 'h';
695
696 argvars[0].v_type = VAR_UNKNOWN;
697 if (*s == '"')
698 (void)eval_string(&s, &argvars[0], TRUE);
699 else if (*s == '\'')
700 (void)eval_lit_string(&s, &argvars[0], TRUE);
701 s = skipwhite(s);
702 if (*s == ')' && argvars[0].v_type == VAR_STRING
703 && ((is_has && !dynamic_feature(argvars[0].vval.v_string))
704 || !is_has))
705 {
706 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
707
708 *arg = s + 1;
709 argvars[1].v_type = VAR_UNKNOWN;
710 tv->v_type = VAR_NUMBER;
711 tv->vval.v_number = 0;
712 if (is_has)
713 f_has(argvars, tv);
714 else
715 f_exists(argvars, tv);
716 clear_tv(&argvars[0]);
717 ++ppconst->pp_used;
718 return OK;
719 }
720 clear_tv(&argvars[0]);
721 if (!is_has)
722 {
723 emsg(_(e_argument_of_exists_compiled_must_be_literal_string));
724 return FAIL;
725 }
726 }
727
728 if (generate_ppconst(cctx, ppconst) == FAIL)
729 return FAIL;
730
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000731 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
732
733 // We handle the "skip" argument of searchpair() and searchpairpos()
734 // differently.
735 is_searchpair = (varlen == 6 && STRNCMP(*arg, "search", 6) == 0)
736 || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0)
737 || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0)
738 || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0);
739
740 *arg = skipwhite(*arg + varlen + 1);
741 if (compile_arguments(arg, cctx, &argcount, is_searchpair) == FAIL)
742 goto theend;
743
744 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
745 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
746 {
747 int idx;
748
749 // builtin function
750 idx = find_internal_func(name);
751 if (idx >= 0)
752 {
753 if (STRCMP(name, "flatten") == 0)
754 {
755 emsg(_(e_cannot_use_flatten_in_vim9_script));
756 goto theend;
757 }
758
759 if (STRCMP(name, "add") == 0 && argcount == 2)
760 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000761 type_T *type = get_type_on_stack(cctx, 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000762
763 // add() can be compiled to instructions if we know the type
764 if (type->tt_type == VAR_LIST)
765 {
766 // inline "add(list, item)" so that the type can be checked
767 res = generate_LISTAPPEND(cctx);
768 idx = -1;
769 }
770 else if (type->tt_type == VAR_BLOB)
771 {
772 // inline "add(blob, nr)" so that the type can be checked
773 res = generate_BLOBAPPEND(cctx);
774 idx = -1;
775 }
776 }
777
778 if (idx >= 0)
779 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
780 }
781 else
782 semsg(_(e_unknown_function_str), namebuf);
783 goto theend;
784 }
785
Bram Moolenaar62aec932022-01-29 21:45:34 +0000786 has_g_namespace = STRNCMP(namebuf, "g:", 2) == 0;
787
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000788 // An argument or local variable can be a function reference, this
789 // overrules a function name.
790 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL
791 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK)
792 {
793 // If we can find the function by name generate the right call.
794 // Skip global functions here, a local funcref takes precedence.
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000795 ufunc = find_func(name, FALSE);
Bram Moolenaar62aec932022-01-29 21:45:34 +0000796 if (ufunc != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000797 {
Bram Moolenaar62aec932022-01-29 21:45:34 +0000798 if (!func_is_global(ufunc))
799 {
800 res = generate_CALL(cctx, ufunc, argcount);
801 goto theend;
802 }
803 if (!has_g_namespace
804 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL)
805 {
806 // A function name without g: prefix must be found locally.
807 semsg(_(e_unknown_function_str), namebuf);
808 goto theend;
809 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000810 }
811 }
812
813 // If the name is a variable, load it and use PCALL.
814 // Not for g:Func(), we don't know if it is a variable or not.
815 // Not for eome#Func(), it will be loaded later.
816 p = namebuf;
Bram Moolenaar62aec932022-01-29 21:45:34 +0000817 if (!has_g_namespace && !is_autoload
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000818 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
819 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000820 type_T *type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000821
822 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
823 goto theend;
824 }
825
826 // If we can find a global function by name generate the right call.
827 if (ufunc != NULL)
828 {
829 res = generate_CALL(cctx, ufunc, argcount);
830 goto theend;
831 }
832
833 // A global function may be defined only later. Need to figure out at
834 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar62aec932022-01-29 21:45:34 +0000835 if (has_g_namespace || is_autoload)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000836 res = generate_UCALL(cctx, name, argcount);
837 else
838 semsg(_(e_unknown_function_str), namebuf);
839
840theend:
841 vim_free(tofree);
842 return res;
843}
844
845// like NAMESPACE_CHAR but with 'a' and 'l'.
846#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
847
848/*
849 * Find the end of a variable or function name. Unlike find_name_end() this
850 * does not recognize magic braces.
851 * When "use_namespace" is TRUE recognize "b:", "s:", etc.
852 * Return a pointer to just after the name. Equal to "arg" if there is no
853 * valid name.
854 */
855 char_u *
856to_name_end(char_u *arg, int use_namespace)
857{
858 char_u *p;
859
860 // Quick check for valid starting character.
861 if (!eval_isnamec1(*arg))
862 return arg;
863
864 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
865 // Include a namespace such as "s:var" and "v:var". But "n:" is not
866 // and can be used in slice "[n:]".
867 if (*p == ':' && (p != arg + 1
868 || !use_namespace
869 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
870 break;
871 return p;
872}
873
874/*
875 * Like to_name_end() but also skip over a list or dict constant.
876 * Also accept "<SNR>123_Func".
877 * This intentionally does not handle line continuation.
878 */
879 char_u *
880to_name_const_end(char_u *arg)
881{
882 char_u *p = arg;
883 typval_T rettv;
884
885 if (STRNCMP(p, "<SNR>", 5) == 0)
886 p = skipdigits(p + 5);
887 p = to_name_end(p, TRUE);
888 if (p == arg && *arg == '[')
889 {
890
891 // Can be "[1, 2, 3]->Func()".
892 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
893 p = arg;
894 }
895 return p;
896}
897
898/*
899 * parse a list: [expr, expr]
900 * "*arg" points to the '['.
901 * ppconst->pp_is_const is set if all items are a constant.
902 */
903 static int
904compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
905{
906 char_u *p = skipwhite(*arg + 1);
907 char_u *whitep = *arg + 1;
908 int count = 0;
909 int is_const;
910 int is_all_const = TRUE; // reset when non-const encountered
911
912 for (;;)
913 {
914 if (may_get_next_line(whitep, &p, cctx) == FAIL)
915 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000916 semsg(_(e_missing_end_of_list_rsb_str), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000917 return FAIL;
918 }
919 if (*p == ',')
920 {
921 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
922 return FAIL;
923 }
924 if (*p == ']')
925 {
926 ++p;
927 break;
928 }
929 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL)
930 return FAIL;
931 if (!is_const)
932 is_all_const = FALSE;
933 ++count;
934 if (*p == ',')
935 {
936 ++p;
937 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
938 {
939 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
940 return FAIL;
941 }
942 }
943 whitep = p;
944 p = skipwhite(p);
945 }
946 *arg = p;
947
948 ppconst->pp_is_const = is_all_const;
949 return generate_NEWLIST(cctx, count);
950}
951
952/*
953 * Parse a lambda: "(arg, arg) => expr"
954 * "*arg" points to the '('.
955 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
956 */
957 static int
958compile_lambda(char_u **arg, cctx_T *cctx)
959{
960 int r;
961 typval_T rettv;
962 ufunc_T *ufunc;
963 evalarg_T evalarg;
964
965 init_evalarg(&evalarg);
966 evalarg.eval_flags = EVAL_EVALUATE;
967 evalarg.eval_cctx = cctx;
968
969 // Get the funcref in "rettv".
970 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
971 if (r != OK)
972 {
973 clear_evalarg(&evalarg, NULL);
974 return r;
975 }
976
977 // "rettv" will now be a partial referencing the function.
978 ufunc = rettv.vval.v_partial->pt_func;
979 ++ufunc->uf_refcount;
980 clear_tv(&rettv);
981
982 // Compile it here to get the return type. The return type is optional,
983 // when it's missing use t_unknown. This is recognized in
984 // compile_return().
985 if (ufunc->uf_ret_type->tt_type == VAR_VOID)
986 ufunc->uf_ret_type = &t_unknown;
987 compile_def_function(ufunc, FALSE, cctx->ctx_compile_type, cctx);
988
989 // When the outer function is compiled for profiling or debugging, the
990 // lambda may be called without profiling or debugging. Compile it here in
991 // the right context.
992 if (cctx->ctx_compile_type == CT_DEBUG
993#ifdef FEAT_PROFILE
994 || cctx->ctx_compile_type == CT_PROFILE
995#endif
996 )
997 compile_def_function(ufunc, FALSE, CT_NONE, cctx);
998
999 // The last entry in evalarg.eval_tofree_ga is a copy of the last line and
1000 // "*arg" may point into it. Point into the original line to avoid a
1001 // dangling pointer.
1002 if (evalarg.eval_using_cmdline)
1003 {
1004 garray_T *gap = &evalarg.eval_tofree_ga;
1005 size_t off = *arg - ((char_u **)gap->ga_data)[gap->ga_len - 1];
1006
1007 *arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
1008 + off;
1009 }
1010
1011 clear_evalarg(&evalarg, NULL);
1012
1013 if (ufunc->uf_def_status == UF_COMPILED)
1014 {
1015 // The return type will now be known.
1016 set_function_type(ufunc);
1017
1018 // The function reference count will be 1. When the ISN_FUNCREF
1019 // instruction is deleted the reference count is decremented and the
1020 // function is freed.
1021 return generate_FUNCREF(cctx, ufunc);
1022 }
1023
1024 func_ptr_unref(ufunc);
1025 return FAIL;
1026}
1027
1028/*
1029 * Get a lambda and compile it. Uses Vim9 syntax.
1030 */
1031 int
1032get_lambda_tv_and_compile(
1033 char_u **arg,
1034 typval_T *rettv,
1035 int types_optional,
1036 evalarg_T *evalarg)
1037{
1038 int r;
1039 ufunc_T *ufunc;
1040 int save_sc_version = current_sctx.sc_version;
1041
1042 // Get the funcref in "rettv".
1043 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
1044 r = get_lambda_tv(arg, rettv, types_optional, evalarg);
1045 current_sctx.sc_version = save_sc_version;
1046 if (r != OK)
1047 return r;
1048
1049 // "rettv" will now be a partial referencing the function.
1050 ufunc = rettv->vval.v_partial->pt_func;
1051
1052 // Compile it here to get the return type. The return type is optional,
1053 // when it's missing use t_unknown. This is recognized in
1054 // compile_return().
1055 if (ufunc->uf_ret_type == NULL || ufunc->uf_ret_type->tt_type == VAR_VOID)
1056 ufunc->uf_ret_type = &t_unknown;
1057 compile_def_function(ufunc, FALSE, CT_NONE, NULL);
1058
1059 if (ufunc->uf_def_status == UF_COMPILED)
1060 {
1061 // The return type will now be known.
1062 set_function_type(ufunc);
1063 return OK;
1064 }
1065 clear_tv(rettv);
1066 return FAIL;
1067}
1068
1069/*
1070 * parse a dict: {key: val, [key]: val}
1071 * "*arg" points to the '{'.
1072 * ppconst->pp_is_const is set if all item values are a constant.
1073 */
1074 static int
1075compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1076{
1077 garray_T *instr = &cctx->ctx_instr;
1078 int count = 0;
1079 dict_T *d = dict_alloc();
1080 dictitem_T *item;
1081 char_u *whitep = *arg + 1;
1082 char_u *p;
1083 int is_const;
1084 int is_all_const = TRUE; // reset when non-const encountered
1085
1086 if (d == NULL)
1087 return FAIL;
1088 if (generate_ppconst(cctx, ppconst) == FAIL)
1089 return FAIL;
1090 for (;;)
1091 {
1092 char_u *key = NULL;
1093
1094 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1095 {
1096 *arg = NULL;
1097 goto failret;
1098 }
1099
1100 if (**arg == '}')
1101 break;
1102
1103 if (**arg == '[')
1104 {
1105 isn_T *isn;
1106
1107 // {[expr]: value} uses an evaluated key.
1108 *arg = skipwhite(*arg + 1);
1109 if (compile_expr0(arg, cctx) == FAIL)
1110 return FAIL;
1111 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
1112 if (isn->isn_type == ISN_PUSHNR)
1113 {
1114 char buf[NUMBUFLEN];
1115
1116 // Convert to string at compile time.
1117 vim_snprintf(buf, NUMBUFLEN, "%lld", isn->isn_arg.number);
1118 isn->isn_type = ISN_PUSHS;
1119 isn->isn_arg.string = vim_strsave((char_u *)buf);
1120 }
1121 if (isn->isn_type == ISN_PUSHS)
1122 key = isn->isn_arg.string;
1123 else if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1124 return FAIL;
1125 *arg = skipwhite(*arg);
1126 if (**arg != ']')
1127 {
1128 emsg(_(e_missing_matching_bracket_after_dict_key));
1129 return FAIL;
1130 }
1131 ++*arg;
1132 }
1133 else
1134 {
1135 // {"name": value},
1136 // {'name': value},
1137 // {name: value} use "name" as a literal key
1138 key = get_literal_key(arg);
1139 if (key == NULL)
1140 return FAIL;
1141 if (generate_PUSHS(cctx, &key) == FAIL)
1142 return FAIL;
1143 }
1144
1145 // Check for duplicate keys, if using string keys.
1146 if (key != NULL)
1147 {
1148 item = dict_find(d, key, -1);
1149 if (item != NULL)
1150 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001151 semsg(_(e_duplicate_key_in_dicitonary), key);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001152 goto failret;
1153 }
1154 item = dictitem_alloc(key);
1155 if (item != NULL)
1156 {
1157 item->di_tv.v_type = VAR_UNKNOWN;
1158 item->di_tv.v_lock = 0;
1159 if (dict_add(d, item) == FAIL)
1160 dictitem_free(item);
1161 }
1162 }
1163
1164 if (**arg != ':')
1165 {
1166 if (*skipwhite(*arg) == ':')
1167 semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg);
1168 else
Bram Moolenaar74409f62022-01-01 15:58:22 +00001169 semsg(_(e_missing_colon_in_dictionary), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001170 return FAIL;
1171 }
1172 whitep = *arg + 1;
1173 if (!IS_WHITE_OR_NUL(*whitep))
1174 {
1175 semsg(_(e_white_space_required_after_str_str), ":", *arg);
1176 return FAIL;
1177 }
1178
1179 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1180 {
1181 *arg = NULL;
1182 goto failret;
1183 }
1184
1185 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL)
1186 return FAIL;
1187 if (!is_const)
1188 is_all_const = FALSE;
1189 ++count;
1190
1191 whitep = *arg;
1192 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1193 {
1194 *arg = NULL;
1195 goto failret;
1196 }
1197 if (**arg == '}')
1198 break;
1199 if (**arg != ',')
1200 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001201 semsg(_(e_missing_comma_in_dictionary), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001202 goto failret;
1203 }
1204 if (IS_WHITE_OR_NUL(*whitep))
1205 {
1206 semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep);
1207 return FAIL;
1208 }
1209 whitep = *arg + 1;
1210 if (!IS_WHITE_OR_NUL(*whitep))
1211 {
1212 semsg(_(e_white_space_required_after_str_str), ",", *arg);
1213 return FAIL;
1214 }
1215 *arg = skipwhite(whitep);
1216 }
1217
1218 *arg = *arg + 1;
1219
1220 // Allow for following comment, after at least one space.
1221 p = skipwhite(*arg);
1222 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
1223 *arg += STRLEN(*arg);
1224
1225 dict_unref(d);
1226 ppconst->pp_is_const = is_all_const;
1227 return generate_NEWDICT(cctx, count);
1228
1229failret:
1230 if (*arg == NULL)
1231 {
1232 semsg(_(e_missing_dict_end), _("[end of lines]"));
1233 *arg = (char_u *)"";
1234 }
1235 dict_unref(d);
1236 return FAIL;
1237}
1238
1239/*
1240 * Compile "&option".
1241 */
1242 static int
1243compile_get_option(char_u **arg, cctx_T *cctx)
1244{
1245 typval_T rettv;
1246 char_u *start = *arg;
1247 int ret;
1248
1249 // parse the option and get the current value to get the type.
1250 rettv.v_type = VAR_UNKNOWN;
1251 ret = eval_option(arg, &rettv, TRUE);
1252 if (ret == OK)
1253 {
1254 // include the '&' in the name, eval_option() expects it.
1255 char_u *name = vim_strnsave(start, *arg - start);
1256 type_T *type = rettv.v_type == VAR_BOOL ? &t_bool
1257 : rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
1258
1259 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
1260 vim_free(name);
1261 }
1262 clear_tv(&rettv);
1263
1264 return ret;
1265}
1266
1267/*
1268 * Compile "$VAR".
1269 */
1270 static int
1271compile_get_env(char_u **arg, cctx_T *cctx)
1272{
1273 char_u *start = *arg;
1274 int len;
1275 int ret;
1276 char_u *name;
1277
1278 ++*arg;
1279 len = get_env_len(arg);
1280 if (len == 0)
1281 {
Bram Moolenaar5f25c382022-01-09 13:36:28 +00001282 semsg(_(e_syntax_error_at_str), start);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001283 return FAIL;
1284 }
1285
1286 // include the '$' in the name, eval_env_var() expects it.
1287 name = vim_strnsave(start, len + 1);
1288 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
1289 vim_free(name);
1290 return ret;
1291}
1292
1293/*
1294 * Compile "@r".
1295 */
1296 static int
1297compile_get_register(char_u **arg, cctx_T *cctx)
1298{
1299 int ret;
1300
1301 ++*arg;
1302 if (**arg == NUL)
1303 {
1304 semsg(_(e_syntax_error_at_str), *arg - 1);
1305 return FAIL;
1306 }
1307 if (!valid_yank_reg(**arg, FALSE))
1308 {
1309 emsg_invreg(**arg);
1310 return FAIL;
1311 }
1312 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
1313 ++*arg;
1314 return ret;
1315}
1316
1317/*
1318 * Apply leading '!', '-' and '+' to constant "rettv".
1319 * When "numeric_only" is TRUE do not apply '!'.
1320 */
1321 static int
1322apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
1323{
1324 char_u *p = *end;
1325
1326 // this works from end to start
1327 while (p > start)
1328 {
1329 --p;
1330 if (*p == '-' || *p == '+')
1331 {
1332 // only '-' has an effect, for '+' we only check the type
1333#ifdef FEAT_FLOAT
1334 if (rettv->v_type == VAR_FLOAT)
1335 {
1336 if (*p == '-')
1337 rettv->vval.v_float = -rettv->vval.v_float;
1338 }
1339 else
1340#endif
1341 {
1342 varnumber_T val;
1343 int error = FALSE;
1344
1345 // tv_get_number_chk() accepts a string, but we don't want that
1346 // here
1347 if (check_not_string(rettv) == FAIL)
1348 return FAIL;
1349 val = tv_get_number_chk(rettv, &error);
1350 clear_tv(rettv);
1351 if (error)
1352 return FAIL;
1353 if (*p == '-')
1354 val = -val;
1355 rettv->v_type = VAR_NUMBER;
1356 rettv->vval.v_number = val;
1357 }
1358 }
1359 else if (numeric_only)
1360 {
1361 ++p;
1362 break;
1363 }
1364 else if (*p == '!')
1365 {
1366 int v = tv2bool(rettv);
1367
1368 // '!' is permissive in the type.
1369 clear_tv(rettv);
1370 rettv->v_type = VAR_BOOL;
1371 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
1372 }
1373 }
1374 *end = p;
1375 return OK;
1376}
1377
1378/*
1379 * Recognize v: variables that are constants and set "rettv".
1380 */
1381 static void
1382get_vim_constant(char_u **arg, typval_T *rettv)
1383{
1384 if (STRNCMP(*arg, "v:true", 6) == 0)
1385 {
1386 rettv->v_type = VAR_BOOL;
1387 rettv->vval.v_number = VVAL_TRUE;
1388 *arg += 6;
1389 }
1390 else if (STRNCMP(*arg, "v:false", 7) == 0)
1391 {
1392 rettv->v_type = VAR_BOOL;
1393 rettv->vval.v_number = VVAL_FALSE;
1394 *arg += 7;
1395 }
1396 else if (STRNCMP(*arg, "v:null", 6) == 0)
1397 {
1398 rettv->v_type = VAR_SPECIAL;
1399 rettv->vval.v_number = VVAL_NULL;
1400 *arg += 6;
1401 }
1402 else if (STRNCMP(*arg, "v:none", 6) == 0)
1403 {
1404 rettv->v_type = VAR_SPECIAL;
1405 rettv->vval.v_number = VVAL_NONE;
1406 *arg += 6;
1407 }
1408}
1409
1410 exprtype_T
1411get_compare_type(char_u *p, int *len, int *type_is)
1412{
1413 exprtype_T type = EXPR_UNKNOWN;
1414 int i;
1415
1416 switch (p[0])
1417 {
1418 case '=': if (p[1] == '=')
1419 type = EXPR_EQUAL;
1420 else if (p[1] == '~')
1421 type = EXPR_MATCH;
1422 break;
1423 case '!': if (p[1] == '=')
1424 type = EXPR_NEQUAL;
1425 else if (p[1] == '~')
1426 type = EXPR_NOMATCH;
1427 break;
1428 case '>': if (p[1] != '=')
1429 {
1430 type = EXPR_GREATER;
1431 *len = 1;
1432 }
1433 else
1434 type = EXPR_GEQUAL;
1435 break;
1436 case '<': if (p[1] != '=')
1437 {
1438 type = EXPR_SMALLER;
1439 *len = 1;
1440 }
1441 else
1442 type = EXPR_SEQUAL;
1443 break;
1444 case 'i': if (p[1] == 's')
1445 {
1446 // "is" and "isnot"; but not a prefix of a name
1447 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
1448 *len = 5;
1449 i = p[*len];
1450 if (!isalnum(i) && i != '_')
1451 {
1452 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
1453 *type_is = TRUE;
1454 }
1455 }
1456 break;
1457 }
1458 return type;
1459}
1460
1461/*
1462 * Skip over an expression, ignoring most errors.
1463 */
1464 void
1465skip_expr_cctx(char_u **arg, cctx_T *cctx)
1466{
1467 evalarg_T evalarg;
1468
1469 init_evalarg(&evalarg);
1470 evalarg.eval_cctx = cctx;
1471 skip_expr(arg, &evalarg);
1472 clear_evalarg(&evalarg, NULL);
1473}
1474
1475/*
1476 * Check that the top of the type stack has a type that can be used as a
1477 * condition. Give an error and return FAIL if not.
1478 */
1479 int
1480bool_on_stack(cctx_T *cctx)
1481{
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001482 type_T *type;
1483
Bram Moolenaar078a4612022-01-04 15:17:03 +00001484 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001485 if (type == &t_bool)
1486 return OK;
1487
Bram Moolenaar59618fe2021-12-21 12:32:17 +00001488 if (type == &t_any
1489 || type == &t_unknown
1490 || type == &t_number
1491 || type == &t_number_bool)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001492 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
1493 // This requires a runtime type check.
1494 return generate_COND2BOOL(cctx);
1495
1496 return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE);
1497}
1498
1499/*
1500 * Give the "white on both sides" error, taking the operator from "p[len]".
1501 */
1502 void
1503error_white_both(char_u *op, int len)
1504{
1505 char_u buf[10];
1506
1507 vim_strncpy(buf, op, len);
1508 semsg(_(e_white_space_required_before_and_after_str_at_str), buf, op);
1509}
1510
1511/*
1512 * Compile code to apply '-', '+' and '!'.
1513 * When "numeric_only" is TRUE do not apply '!'.
1514 */
1515 static int
1516compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
1517{
1518 char_u *p = *end;
1519
1520 // this works from end to start
1521 while (p > start)
1522 {
1523 --p;
1524 while (VIM_ISWHITE(*p))
1525 --p;
1526 if (*p == '-' || *p == '+')
1527 {
1528 int negate = *p == '-';
1529 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001530 type_T *type;
1531
Bram Moolenaar078a4612022-01-04 15:17:03 +00001532 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001533 if (type != &t_float && need_type(type, &t_number,
1534 -1, 0, cctx, FALSE, FALSE) == FAIL)
1535 return FAIL;
1536
1537 while (p > start && (p[-1] == '-' || p[-1] == '+'))
1538 {
1539 --p;
1540 if (*p == '-')
1541 negate = !negate;
1542 }
1543 // only '-' has an effect, for '+' we only check the type
1544 if (negate)
1545 {
1546 isn = generate_instr(cctx, ISN_NEGATENR);
1547 if (isn == NULL)
1548 return FAIL;
1549 }
1550 }
1551 else if (numeric_only)
1552 {
1553 ++p;
1554 break;
1555 }
1556 else
1557 {
1558 int invert = *p == '!';
1559
1560 while (p > start && (p[-1] == '!' || VIM_ISWHITE(p[-1])))
1561 {
1562 if (p[-1] == '!')
1563 invert = !invert;
1564 --p;
1565 }
1566 if (generate_2BOOL(cctx, invert, -1) == FAIL)
1567 return FAIL;
1568 }
1569 }
1570 *end = p;
1571 return OK;
1572}
1573
1574/*
1575 * Compile "(expression)": recursive!
1576 * Return FAIL/OK.
1577 */
1578 static int
1579compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1580{
1581 int ret;
1582 char_u *p = *arg + 1;
1583
1584 if (may_get_next_line_error(p, arg, cctx) == FAIL)
1585 return FAIL;
1586 if (ppconst->pp_used <= PPSIZE - 10)
1587 {
1588 ret = compile_expr1(arg, cctx, ppconst);
1589 }
1590 else
1591 {
1592 // Not enough space in ppconst, flush constants.
1593 if (generate_ppconst(cctx, ppconst) == FAIL)
1594 return FAIL;
1595 ret = compile_expr0(arg, cctx);
1596 }
1597 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
1598 return FAIL;
1599 if (**arg == ')')
1600 ++*arg;
1601 else if (ret == OK)
1602 {
1603 emsg(_(e_missing_closing_paren));
1604 ret = FAIL;
1605 }
1606 return ret;
1607}
1608
Bram Moolenaarc7349932022-01-16 20:59:39 +00001609static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
1610
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001611/*
1612 * Compile whatever comes after "name" or "name()".
1613 * Advances "*arg" only when something was recognized.
1614 */
1615 static int
1616compile_subscript(
1617 char_u **arg,
1618 cctx_T *cctx,
1619 char_u *start_leader,
1620 char_u **end_leader,
1621 ppconst_T *ppconst)
1622{
1623 char_u *name_start = *end_leader;
1624 int keeping_dict = FALSE;
1625
1626 for (;;)
1627 {
1628 char_u *p = skipwhite(*arg);
1629
1630 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
1631 {
1632 char_u *next = peek_next_line_from_context(cctx);
1633
1634 // If a following line starts with "->{" or "->X" advance to that
1635 // line, so that a line break before "->" is allowed.
1636 // Also if a following line starts with ".x".
1637 if (next != NULL &&
1638 ((next[0] == '-' && next[1] == '>'
1639 && (next[2] == '{'
1640 || ASCII_ISALPHA(*skipwhite(next + 2))))
1641 || (next[0] == '.' && eval_isdictc(next[1]))))
1642 {
1643 next = next_line_from_context(cctx, TRUE);
1644 if (next == NULL)
1645 return FAIL;
1646 *arg = next;
1647 p = skipwhite(*arg);
1648 }
1649 }
1650
1651 // Do not skip over white space to find the "(", "execute 'x' (expr)"
1652 // is not a function call.
1653 if (**arg == '(')
1654 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001655 type_T *type;
1656 int argcount = 0;
1657
1658 if (generate_ppconst(cctx, ppconst) == FAIL)
1659 return FAIL;
1660 ppconst->pp_is_const = FALSE;
1661
1662 // funcref(arg)
Bram Moolenaar078a4612022-01-04 15:17:03 +00001663 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001664
1665 *arg = skipwhite(p + 1);
1666 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
1667 return FAIL;
1668 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
1669 return FAIL;
1670 if (keeping_dict)
1671 {
1672 keeping_dict = FALSE;
1673 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
1674 return FAIL;
1675 }
1676 }
1677 else if (*p == '-' && p[1] == '>')
1678 {
Bram Moolenaarc7349932022-01-16 20:59:39 +00001679 char_u *pstart = p;
1680 int alt;
1681 char_u *paren;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001682
Bram Moolenaarc7349932022-01-16 20:59:39 +00001683 // something->method()
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001684 if (generate_ppconst(cctx, ppconst) == FAIL)
1685 return FAIL;
1686 ppconst->pp_is_const = FALSE;
1687
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001688 // Apply the '!', '-' and '+' first:
1689 // -1.0->func() works like (-1.0)->func()
1690 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
1691 return FAIL;
1692
1693 p += 2;
1694 *arg = skipwhite(p);
1695 // No line break supported right after "->".
Bram Moolenaarc7349932022-01-16 20:59:39 +00001696
1697 // Three alternatives handled here:
1698 // 1. "base->name(" only a name, use compile_call()
1699 // 2. "base->(expr)(" evaluate "expr", then use PCALL
1700 // 3. "base->expr(" Same, find the end of "expr" by "("
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001701 if (**arg == '(')
Bram Moolenaarc7349932022-01-16 20:59:39 +00001702 alt = 2;
1703 else
1704 {
1705 // alternative 1 or 3
1706 p = *arg;
1707 if (!eval_isnamec1(*p))
1708 {
1709 semsg(_(e_trailing_characters_str), pstart);
1710 return FAIL;
1711 }
1712 if (ASCII_ISALPHA(*p) && p[1] == ':')
1713 p += 2;
1714 for ( ; eval_isnamec(*p); ++p)
1715 ;
1716 if (*p == '(')
1717 {
1718 // alternative 1
1719 alt = 1;
1720 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
1721 return FAIL;
1722 }
1723 else
1724 {
1725 // Must be alternative 3, find the "(". Only works within
1726 // one line.
1727 alt = 3;
1728 paren = vim_strchr(p, '(');
1729 if (paren == NULL)
1730 {
1731 semsg(_(e_missing_parenthesis_str), *arg);
1732 return FAIL;
1733 }
1734 }
1735 }
1736
1737 if (alt != 1)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001738 {
1739 int argcount = 1;
1740 garray_T *stack = &cctx->ctx_type_stack;
1741 int type_idx_start = stack->ga_len;
1742 type_T *type;
1743 int expr_isn_start = cctx->ctx_instr.ga_len;
1744 int expr_isn_end;
1745 int arg_isn_count;
1746
Bram Moolenaarc7349932022-01-16 20:59:39 +00001747 if (alt == 2)
1748 {
1749 // Funcref call: list->(Refs[2])(arg)
1750 // or lambda: list->((arg) => expr)(arg)
1751 //
1752 // Fist compile the function expression.
1753 if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
1754 return FAIL;
1755 }
1756 else
1757 {
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001758 int fail;
1759 int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
1760
Bram Moolenaarc7349932022-01-16 20:59:39 +00001761 *paren = NUL;
Bram Moolenaard02dce22022-01-18 17:43:04 +00001762
1763 // instead of using LOADG for "import.Func" use PUSHFUNC
1764 ++paren_follows_after_expr;
1765
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001766 // do not look in the next line
1767 cctx->ctx_ufunc->uf_lines.ga_len = 1;
Bram Moolenaard02dce22022-01-18 17:43:04 +00001768
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001769 fail = compile_expr8(arg, cctx, ppconst) == FAIL
1770 || *skipwhite(*arg) != NUL;
1771 *paren = '(';
Bram Moolenaard02dce22022-01-18 17:43:04 +00001772 --paren_follows_after_expr;
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001773 cctx->ctx_ufunc->uf_lines.ga_len = save_len;
Bram Moolenaard02dce22022-01-18 17:43:04 +00001774
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001775 if (fail)
Bram Moolenaarc7349932022-01-16 20:59:39 +00001776 {
Bram Moolenaarc7349932022-01-16 20:59:39 +00001777 semsg(_(e_invalid_expression_str), pstart);
1778 return FAIL;
1779 }
Bram Moolenaarc7349932022-01-16 20:59:39 +00001780 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001781
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001782 // Compile the arguments.
1783 if (**arg != '(')
1784 {
1785 if (*skipwhite(*arg) == '(')
Bram Moolenaar3a846e62022-01-01 16:21:00 +00001786 emsg(_(e_no_white_space_allowed_before_parenthesis));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001787 else
1788 semsg(_(e_missing_parenthesis_str), *arg);
1789 return FAIL;
1790 }
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001791
1792 // Remember the next instruction index, where the instructions
1793 // for arguments are being written.
1794 expr_isn_end = cctx->ctx_instr.ga_len;
1795
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001796 *arg = skipwhite(*arg + 1);
1797 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
1798 return FAIL;
1799
1800 // Move the instructions for the arguments to before the
1801 // instructions of the expression and move the type of the
1802 // expression after the argument types. This is what ISN_PCALL
1803 // expects.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001804 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
1805 if (arg_isn_count > 0)
1806 {
1807 int expr_isn_count = expr_isn_end - expr_isn_start;
1808 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count);
Bram Moolenaar078a4612022-01-04 15:17:03 +00001809 type_T *decl_type;
1810 type2_T *typep;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001811
1812 if (isn == NULL)
1813 return FAIL;
1814 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
1815 + expr_isn_start,
1816 sizeof(isn_T) * expr_isn_count);
1817 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
1818 + expr_isn_start,
1819 ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end,
1820 sizeof(isn_T) * arg_isn_count);
1821 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
1822 + expr_isn_start + arg_isn_count,
1823 isn, sizeof(isn_T) * expr_isn_count);
1824 vim_free(isn);
1825
Bram Moolenaar078a4612022-01-04 15:17:03 +00001826 typep = ((type2_T *)stack->ga_data) + type_idx_start;
1827 type = typep->type_curr;
1828 decl_type = typep->type_decl;
1829 mch_memmove(((type2_T *)stack->ga_data) + type_idx_start,
1830 ((type2_T *)stack->ga_data) + type_idx_start + 1,
1831 sizeof(type2_T)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001832 * (stack->ga_len - type_idx_start - 1));
Bram Moolenaar078a4612022-01-04 15:17:03 +00001833 typep = ((type2_T *)stack->ga_data) + stack->ga_len - 1;
1834 typep->type_curr = type;
1835 typep->type_decl = decl_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001836 }
1837
Bram Moolenaar078a4612022-01-04 15:17:03 +00001838 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001839 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
1840 return FAIL;
1841 }
Bram Moolenaarc7349932022-01-16 20:59:39 +00001842
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001843 if (keeping_dict)
1844 {
1845 keeping_dict = FALSE;
1846 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
1847 return FAIL;
1848 }
1849 }
1850 else if (**arg == '[')
1851 {
1852 int is_slice = FALSE;
1853
1854 // list index: list[123]
1855 // dict member: dict[key]
1856 // string index: text[123]
1857 // blob index: blob[123]
1858 if (generate_ppconst(cctx, ppconst) == FAIL)
1859 return FAIL;
1860 ppconst->pp_is_const = FALSE;
1861
1862 ++p;
1863 if (may_get_next_line_error(p, arg, cctx) == FAIL)
1864 return FAIL;
1865 if (**arg == ':')
1866 {
1867 // missing first index is equal to zero
1868 generate_PUSHNR(cctx, 0);
1869 }
1870 else
1871 {
1872 if (compile_expr0(arg, cctx) == FAIL)
1873 return FAIL;
1874 if (**arg == ':')
1875 {
1876 semsg(_(e_white_space_required_before_and_after_str_at_str),
1877 ":", *arg);
1878 return FAIL;
1879 }
1880 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
1881 return FAIL;
1882 *arg = skipwhite(*arg);
1883 }
1884 if (**arg == ':')
1885 {
1886 is_slice = TRUE;
1887 ++*arg;
1888 if (!IS_WHITE_OR_NUL(**arg) && **arg != ']')
1889 {
1890 semsg(_(e_white_space_required_before_and_after_str_at_str),
1891 ":", *arg);
1892 return FAIL;
1893 }
1894 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
1895 return FAIL;
1896 if (**arg == ']')
1897 // missing second index is equal to end of string
1898 generate_PUSHNR(cctx, -1);
1899 else
1900 {
1901 if (compile_expr0(arg, cctx) == FAIL)
1902 return FAIL;
1903 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
1904 return FAIL;
1905 *arg = skipwhite(*arg);
1906 }
1907 }
1908
1909 if (**arg != ']')
1910 {
1911 emsg(_(e_missing_closing_square_brace));
1912 return FAIL;
1913 }
1914 *arg = *arg + 1;
1915
1916 if (keeping_dict)
1917 {
1918 keeping_dict = FALSE;
1919 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
1920 return FAIL;
1921 }
1922 if (compile_member(is_slice, &keeping_dict, cctx) == FAIL)
1923 return FAIL;
1924 }
1925 else if (*p == '.' && p[1] != '.')
1926 {
1927 // dictionary member: dict.name
1928 if (generate_ppconst(cctx, ppconst) == FAIL)
1929 return FAIL;
1930 ppconst->pp_is_const = FALSE;
1931
1932 *arg = p + 1;
1933 if (IS_WHITE_OR_NUL(**arg))
1934 {
1935 emsg(_(e_missing_name_after_dot));
1936 return FAIL;
1937 }
1938 p = *arg;
1939 if (eval_isdictc(*p))
1940 while (eval_isnamec(*p))
1941 MB_PTR_ADV(p);
1942 if (p == *arg)
1943 {
1944 semsg(_(e_syntax_error_at_str), *arg);
1945 return FAIL;
1946 }
1947 if (keeping_dict && generate_instr(cctx, ISN_CLEARDICT) == NULL)
1948 return FAIL;
1949 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
1950 return FAIL;
1951 keeping_dict = TRUE;
1952 *arg = p;
1953 }
1954 else
1955 break;
1956 }
1957
1958 // Turn "dict.Func" into a partial for "Func" bound to "dict".
1959 // This needs to be done at runtime to be able to check the type.
1960 if (keeping_dict && generate_instr(cctx, ISN_USEDICT) == NULL)
1961 return FAIL;
1962
1963 return OK;
1964}
1965
1966/*
1967 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
1968 * "arg" is advanced until after the expression, skipping white space.
1969 *
1970 * If the value is a constant "ppconst->pp_used" will be non-zero.
1971 * Before instructions are generated, any values in "ppconst" will generated.
1972 *
1973 * This is the compiling equivalent of eval1(), eval2(), etc.
1974 */
1975
1976/*
1977 * number number constant
1978 * 0zFFFFFFFF Blob constant
1979 * "string" string constant
1980 * 'string' literal string constant
1981 * &option-name option value
1982 * @r register contents
1983 * identifier variable value
1984 * function() function call
1985 * $VAR environment variable
1986 * (expression) nested expression
1987 * [expr, expr] List
1988 * {key: val, [key]: val} Dictionary
1989 *
1990 * Also handle:
1991 * ! in front logical NOT
1992 * - in front unary minus
1993 * + in front unary plus (ignored)
1994 * trailing (arg) funcref/partial call
1995 * trailing [] subscript in String or List
1996 * trailing .name entry in Dictionary
1997 * trailing ->name() method call
1998 */
1999 static int
Bram Moolenaar5da36052021-12-27 15:39:57 +00002000compile_expr8(
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002001 char_u **arg,
2002 cctx_T *cctx,
2003 ppconst_T *ppconst)
2004{
2005 char_u *start_leader, *end_leader;
2006 int ret = OK;
2007 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
2008 int used_before = ppconst->pp_used;
2009
2010 ppconst->pp_is_const = FALSE;
2011
2012 /*
2013 * Skip '!', '-' and '+' characters. They are handled later.
2014 */
2015 start_leader = *arg;
2016 if (eval_leader(arg, TRUE) == FAIL)
2017 return FAIL;
2018 end_leader = *arg;
2019
2020 rettv->v_type = VAR_UNKNOWN;
2021 switch (**arg)
2022 {
2023 /*
2024 * Number constant.
2025 */
2026 case '0': // also for blob starting with 0z
2027 case '1':
2028 case '2':
2029 case '3':
2030 case '4':
2031 case '5':
2032 case '6':
2033 case '7':
2034 case '8':
2035 case '9':
2036 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
2037 return FAIL;
2038 // Apply "-" and "+" just before the number now, right to
2039 // left. Matters especially when "->" follows. Stops at
2040 // '!'.
2041 if (apply_leader(rettv, TRUE,
2042 start_leader, &end_leader) == FAIL)
2043 {
2044 clear_tv(rettv);
2045 return FAIL;
2046 }
2047 break;
2048
2049 /*
2050 * String constant: "string".
2051 */
2052 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
2053 return FAIL;
2054 break;
2055
2056 /*
2057 * Literal string constant: 'str''ing'.
2058 */
2059 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
2060 return FAIL;
2061 break;
2062
2063 /*
2064 * Constant Vim variable.
2065 */
2066 case 'v': get_vim_constant(arg, rettv);
2067 ret = NOTDONE;
2068 break;
2069
2070 /*
2071 * "true" constant
2072 */
2073 case 't': if (STRNCMP(*arg, "true", 4) == 0
2074 && !eval_isnamec((*arg)[4]))
2075 {
2076 *arg += 4;
2077 rettv->v_type = VAR_BOOL;
2078 rettv->vval.v_number = VVAL_TRUE;
2079 }
2080 else
2081 ret = NOTDONE;
2082 break;
2083
2084 /*
2085 * "false" constant
2086 */
2087 case 'f': if (STRNCMP(*arg, "false", 5) == 0
2088 && !eval_isnamec((*arg)[5]))
2089 {
2090 *arg += 5;
2091 rettv->v_type = VAR_BOOL;
2092 rettv->vval.v_number = VVAL_FALSE;
2093 }
2094 else
2095 ret = NOTDONE;
2096 break;
2097
2098 /*
2099 * "null" constant
2100 */
2101 case 'n': if (STRNCMP(*arg, "null", 4) == 0
2102 && !eval_isnamec((*arg)[4]))
2103 {
2104 *arg += 4;
2105 rettv->v_type = VAR_SPECIAL;
2106 rettv->vval.v_number = VVAL_NULL;
2107 }
2108 else
2109 ret = NOTDONE;
2110 break;
2111
2112 /*
2113 * List: [expr, expr]
2114 */
2115 case '[': if (generate_ppconst(cctx, ppconst) == FAIL)
2116 return FAIL;
2117 ret = compile_list(arg, cctx, ppconst);
2118 break;
2119
2120 /*
2121 * Dictionary: {'key': val, 'key': val}
2122 */
2123 case '{': if (generate_ppconst(cctx, ppconst) == FAIL)
2124 return FAIL;
2125 ret = compile_dict(arg, cctx, ppconst);
2126 break;
2127
2128 /*
2129 * Option value: &name
2130 */
2131 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
2132 return FAIL;
2133 ret = compile_get_option(arg, cctx);
2134 break;
2135
2136 /*
2137 * Environment variable: $VAR.
2138 */
2139 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
2140 return FAIL;
2141 ret = compile_get_env(arg, cctx);
2142 break;
2143
2144 /*
2145 * Register contents: @r.
2146 */
2147 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
2148 return FAIL;
2149 ret = compile_get_register(arg, cctx);
2150 break;
2151 /*
2152 * nested expression: (expression).
2153 * lambda: (arg, arg) => expr
2154 * funcref: (arg, arg) => { statement }
2155 */
2156 case '(': // if compile_lambda returns NOTDONE then it must be (expr)
2157 ret = compile_lambda(arg, cctx);
2158 if (ret == NOTDONE)
2159 ret = compile_parenthesis(arg, cctx, ppconst);
2160 break;
2161
2162 default: ret = NOTDONE;
2163 break;
2164 }
2165 if (ret == FAIL)
2166 return FAIL;
2167
2168 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
2169 {
2170 if (cctx->ctx_skip == SKIP_YES)
2171 clear_tv(rettv);
2172 else
2173 // A constant expression can possibly be handled compile time,
2174 // return the value instead of generating code.
2175 ++ppconst->pp_used;
2176 }
2177 else if (ret == NOTDONE)
2178 {
2179 char_u *p;
2180 int r;
2181
2182 if (!eval_isnamec1(**arg))
2183 {
2184 if (!vim9_bad_comment(*arg))
2185 {
2186 if (ends_excmd(*skipwhite(*arg)))
2187 semsg(_(e_empty_expression_str), *arg);
2188 else
2189 semsg(_(e_name_expected_str), *arg);
2190 }
2191 return FAIL;
2192 }
2193
2194 // "name" or "name()"
2195 p = to_name_end(*arg, TRUE);
2196 if (p - *arg == (size_t)1 && **arg == '_')
2197 {
2198 emsg(_(e_cannot_use_underscore_here));
2199 return FAIL;
2200 }
2201
2202 if (*p == '(')
2203 {
2204 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
2205 }
2206 else
2207 {
2208 if (cctx->ctx_skip != SKIP_YES
2209 && generate_ppconst(cctx, ppconst) == FAIL)
2210 return FAIL;
2211 r = compile_load(arg, p, cctx, TRUE, TRUE);
2212 }
2213 if (r == FAIL)
2214 return FAIL;
2215 }
2216
2217 // Handle following "[]", ".member", etc.
2218 // Then deal with prefixed '-', '+' and '!', if not done already.
2219 if (compile_subscript(arg, cctx, start_leader, &end_leader,
2220 ppconst) == FAIL)
2221 return FAIL;
2222 if (ppconst->pp_used > 0)
2223 {
2224 // apply the '!', '-' and '+' before the constant
2225 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
2226 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
2227 return FAIL;
2228 return OK;
2229 }
2230 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
2231 return FAIL;
2232 return OK;
2233}
2234
2235/*
Bram Moolenaar5da36052021-12-27 15:39:57 +00002236 * <type>expr8: runtime type check / conversion
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002237 */
2238 static int
Bram Moolenaar5da36052021-12-27 15:39:57 +00002239compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002240{
2241 type_T *want_type = NULL;
2242
2243 // Recognize <type>
2244 if (**arg == '<' && eval_isnamec1((*arg)[1]))
2245 {
2246 ++*arg;
2247 want_type = parse_type(arg, cctx->ctx_type_list, TRUE);
2248 if (want_type == NULL)
2249 return FAIL;
2250
2251 if (**arg != '>')
2252 {
2253 if (*skipwhite(*arg) == '>')
2254 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
2255 else
2256 emsg(_(e_missing_gt));
2257 return FAIL;
2258 }
2259 ++*arg;
2260 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2261 return FAIL;
2262 }
2263
Bram Moolenaar5da36052021-12-27 15:39:57 +00002264 if (compile_expr8(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002265 return FAIL;
2266
2267 if (want_type != NULL)
2268 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002269 type_T *actual;
2270 where_T where = WHERE_INIT;
2271
2272 generate_ppconst(cctx, ppconst);
Bram Moolenaar078a4612022-01-04 15:17:03 +00002273 actual = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +00002274 if (check_type_maybe(want_type, actual, FALSE, where) != OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002275 {
Bram Moolenaar59618fe2021-12-21 12:32:17 +00002276 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE)
2277 == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002278 return FAIL;
2279 }
2280 }
2281
2282 return OK;
2283}
2284
2285/*
2286 * * number multiplication
2287 * / number division
2288 * % number modulo
2289 */
2290 static int
2291compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2292{
2293 char_u *op;
2294 char_u *next;
2295 int ppconst_used = ppconst->pp_used;
2296
2297 // get the first expression
Bram Moolenaar5da36052021-12-27 15:39:57 +00002298 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002299 return FAIL;
2300
2301 /*
2302 * Repeat computing, until no "*", "/" or "%" is following.
2303 */
2304 for (;;)
2305 {
2306 op = may_peek_next_line(cctx, *arg, &next);
2307 if (*op != '*' && *op != '/' && *op != '%')
2308 break;
2309 if (next != NULL)
2310 {
2311 *arg = next_line_from_context(cctx, TRUE);
2312 op = skipwhite(*arg);
2313 }
2314
2315 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
2316 {
2317 error_white_both(op, 1);
2318 return FAIL;
2319 }
2320 if (may_get_next_line_error(op + 1, arg, cctx) == FAIL)
2321 return FAIL;
2322
2323 // get the second expression
Bram Moolenaar5da36052021-12-27 15:39:57 +00002324 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002325 return FAIL;
2326
2327 if (ppconst->pp_used == ppconst_used + 2
2328 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
2329 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
2330 {
2331 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
2332 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
2333 varnumber_T res = 0;
2334 int failed = FALSE;
2335
2336 // both are numbers: compute the result
2337 switch (*op)
2338 {
2339 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
2340 break;
2341 case '/': res = num_divide(tv1->vval.v_number,
2342 tv2->vval.v_number, &failed);
2343 break;
2344 case '%': res = num_modulus(tv1->vval.v_number,
2345 tv2->vval.v_number, &failed);
2346 break;
2347 }
2348 if (failed)
2349 return FAIL;
2350 tv1->vval.v_number = res;
2351 --ppconst->pp_used;
2352 }
2353 else
2354 {
2355 generate_ppconst(cctx, ppconst);
2356 generate_two_op(cctx, op);
2357 }
2358 }
2359
2360 return OK;
2361}
2362
2363/*
2364 * + number addition or list/blobl concatenation
2365 * - number subtraction
2366 * .. string concatenation
2367 */
2368 static int
2369compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2370{
2371 char_u *op;
2372 char_u *next;
2373 int oplen;
2374 int ppconst_used = ppconst->pp_used;
2375
2376 // get the first variable
2377 if (compile_expr6(arg, cctx, ppconst) == FAIL)
2378 return FAIL;
2379
2380 /*
2381 * Repeat computing, until no "+", "-" or ".." is following.
2382 */
2383 for (;;)
2384 {
2385 op = may_peek_next_line(cctx, *arg, &next);
2386 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
2387 break;
2388 if (op[0] == op[1] && *op != '.' && next)
2389 // Finding "++" or "--" on the next line is a separate command.
2390 // But ".." is concatenation.
2391 break;
2392 oplen = (*op == '.' ? 2 : 1);
2393 if (next != NULL)
2394 {
2395 *arg = next_line_from_context(cctx, TRUE);
2396 op = skipwhite(*arg);
2397 }
2398
2399 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
2400 {
2401 error_white_both(op, oplen);
2402 return FAIL;
2403 }
2404
2405 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL)
2406 return FAIL;
2407
2408 // get the second expression
2409 if (compile_expr6(arg, cctx, ppconst) == FAIL)
2410 return FAIL;
2411
2412 if (ppconst->pp_used == ppconst_used + 2
2413 && (*op == '.'
2414 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
2415 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
2416 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
2417 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
2418 {
2419 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
2420 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
2421
2422 // concat/subtract/add constant numbers
2423 if (*op == '+')
2424 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
2425 else if (*op == '-')
2426 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
2427 else
2428 {
2429 // concatenate constant strings
2430 char_u *s1 = tv1->vval.v_string;
2431 char_u *s2 = tv2->vval.v_string;
2432 size_t len1 = STRLEN(s1);
2433
2434 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
2435 if (tv1->vval.v_string == NULL)
2436 {
2437 clear_ppconst(ppconst);
2438 return FAIL;
2439 }
2440 mch_memmove(tv1->vval.v_string, s1, len1);
2441 STRCPY(tv1->vval.v_string + len1, s2);
2442 vim_free(s1);
2443 vim_free(s2);
2444 }
2445 --ppconst->pp_used;
2446 }
2447 else
2448 {
2449 generate_ppconst(cctx, ppconst);
2450 ppconst->pp_is_const = FALSE;
2451 if (*op == '.')
2452 {
2453 if (may_generate_2STRING(-2, FALSE, cctx) == FAIL
2454 || may_generate_2STRING(-1, FALSE, cctx) == FAIL)
2455 return FAIL;
2456 generate_instr_drop(cctx, ISN_CONCAT, 1);
2457 }
2458 else
2459 generate_two_op(cctx, op);
2460 }
2461 }
2462
2463 return OK;
2464}
2465
2466/*
2467 * expr5a == expr5b
2468 * expr5a =~ expr5b
2469 * expr5a != expr5b
2470 * expr5a !~ expr5b
2471 * expr5a > expr5b
2472 * expr5a >= expr5b
2473 * expr5a < expr5b
2474 * expr5a <= expr5b
2475 * expr5a is expr5b
2476 * expr5a isnot expr5b
2477 *
2478 * Produces instructions:
2479 * EVAL expr5a Push result of "expr5a"
2480 * EVAL expr5b Push result of "expr5b"
2481 * COMPARE one of the compare instructions
2482 */
2483 static int
2484compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2485{
2486 exprtype_T type = EXPR_UNKNOWN;
2487 char_u *p;
2488 char_u *next;
2489 int len = 2;
2490 int type_is = FALSE;
2491 int ppconst_used = ppconst->pp_used;
2492
2493 // get the first variable
2494 if (compile_expr5(arg, cctx, ppconst) == FAIL)
2495 return FAIL;
2496
2497 p = may_peek_next_line(cctx, *arg, &next);
2498 type = get_compare_type(p, &len, &type_is);
2499
2500 /*
2501 * If there is a comparative operator, use it.
2502 */
2503 if (type != EXPR_UNKNOWN)
2504 {
2505 int ic = FALSE; // Default: do not ignore case
2506
2507 if (next != NULL)
2508 {
2509 *arg = next_line_from_context(cctx, TRUE);
2510 p = skipwhite(*arg);
2511 }
2512 if (type_is && (p[len] == '?' || p[len] == '#'))
2513 {
2514 semsg(_(e_invalid_expression_str), *arg);
2515 return FAIL;
2516 }
2517 // extra question mark appended: ignore case
2518 if (p[len] == '?')
2519 {
2520 ic = TRUE;
2521 ++len;
2522 }
2523 // extra '#' appended: match case (ignored)
2524 else if (p[len] == '#')
2525 ++len;
2526 // nothing appended: match case
2527
2528 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
2529 {
2530 error_white_both(p, len);
2531 return FAIL;
2532 }
2533
2534 // get the second variable
2535 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
2536 return FAIL;
2537
2538 if (compile_expr5(arg, cctx, ppconst) == FAIL)
2539 return FAIL;
2540
2541 if (ppconst->pp_used == ppconst_used + 2)
2542 {
2543 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
2544 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
2545 int ret;
2546
2547 // Both sides are a constant, compute the result now.
2548 // First check for a valid combination of types, this is more
2549 // strict than typval_compare().
2550 if (check_compare_types(type, tv1, tv2) == FAIL)
2551 ret = FAIL;
2552 else
2553 {
2554 ret = typval_compare(tv1, tv2, type, ic);
2555 tv1->v_type = VAR_BOOL;
2556 tv1->vval.v_number = tv1->vval.v_number
2557 ? VVAL_TRUE : VVAL_FALSE;
2558 clear_tv(tv2);
2559 --ppconst->pp_used;
2560 }
2561 return ret;
2562 }
2563
2564 generate_ppconst(cctx, ppconst);
2565 return generate_COMPARE(cctx, type, ic);
2566 }
2567
2568 return OK;
2569}
2570
2571static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2572
2573/*
2574 * Compile || or &&.
2575 */
2576 static int
2577compile_and_or(
2578 char_u **arg,
2579 cctx_T *cctx,
2580 char *op,
2581 ppconst_T *ppconst,
2582 int ppconst_used UNUSED)
2583{
2584 char_u *next;
2585 char_u *p = may_peek_next_line(cctx, *arg, &next);
2586 int opchar = *op;
2587
2588 if (p[0] == opchar && p[1] == opchar)
2589 {
2590 garray_T *instr = &cctx->ctx_instr;
2591 garray_T end_ga;
2592 int save_skip = cctx->ctx_skip;
2593
2594 /*
2595 * Repeat until there is no following "||" or "&&"
2596 */
2597 ga_init2(&end_ga, sizeof(int), 10);
2598 while (p[0] == opchar && p[1] == opchar)
2599 {
2600 long start_lnum = SOURCING_LNUM;
2601 long save_sourcing_lnum;
2602 int start_ctx_lnum = cctx->ctx_lnum;
2603 int save_lnum;
2604 int const_used;
2605 int status;
2606 jumpwhen_T jump_when = opchar == '|'
2607 ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE;
2608
2609 if (next != NULL)
2610 {
2611 *arg = next_line_from_context(cctx, TRUE);
2612 p = skipwhite(*arg);
2613 }
2614
2615 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
2616 {
2617 semsg(_(e_white_space_required_before_and_after_str_at_str),
2618 op, p);
2619 ga_clear(&end_ga);
2620 return FAIL;
2621 }
2622
2623 save_sourcing_lnum = SOURCING_LNUM;
2624 SOURCING_LNUM = start_lnum;
2625 save_lnum = cctx->ctx_lnum;
2626 cctx->ctx_lnum = start_ctx_lnum;
2627
2628 status = check_ppconst_bool(ppconst);
2629 if (status != FAIL)
2630 {
2631 // Use the last ppconst if possible.
2632 if (ppconst->pp_used > 0)
2633 {
2634 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
2635 int is_true = tv2bool(tv);
2636
2637 if ((is_true && opchar == '|')
2638 || (!is_true && opchar == '&'))
2639 {
2640 // For "false && expr" and "true || expr" the "expr"
2641 // does not need to be evaluated.
2642 cctx->ctx_skip = SKIP_YES;
2643 clear_tv(tv);
2644 tv->v_type = VAR_BOOL;
2645 tv->vval.v_number = is_true ? VVAL_TRUE : VVAL_FALSE;
2646 }
2647 else
2648 {
2649 // For "true && expr" and "false || expr" only "expr"
2650 // needs to be evaluated.
2651 --ppconst->pp_used;
2652 jump_when = JUMP_NEVER;
2653 }
2654 }
2655 else
2656 {
2657 // Every part must evaluate to a bool.
2658 status = bool_on_stack(cctx);
2659 }
2660 }
2661 if (status != FAIL)
2662 status = ga_grow(&end_ga, 1);
2663 cctx->ctx_lnum = save_lnum;
2664 if (status == FAIL)
2665 {
2666 ga_clear(&end_ga);
2667 return FAIL;
2668 }
2669
2670 if (jump_when != JUMP_NEVER)
2671 {
2672 if (cctx->ctx_skip != SKIP_YES)
2673 {
2674 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
2675 ++end_ga.ga_len;
2676 }
2677 generate_JUMP(cctx, jump_when, 0);
2678 }
2679
2680 // eval the next expression
2681 SOURCING_LNUM = save_sourcing_lnum;
2682 if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
2683 {
2684 ga_clear(&end_ga);
2685 return FAIL;
2686 }
2687
2688 const_used = ppconst->pp_used;
2689 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
2690 : compile_expr4(arg, cctx, ppconst)) == FAIL)
2691 {
2692 ga_clear(&end_ga);
2693 return FAIL;
2694 }
2695
2696 // "0 || 1" results in true, "1 && 0" results in false.
2697 if (ppconst->pp_used == const_used + 1)
2698 {
2699 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
2700
2701 if (tv->v_type == VAR_NUMBER
2702 && (tv->vval.v_number == 1 || tv->vval.v_number == 0))
2703 {
2704 tv->vval.v_number = tv->vval.v_number == 1
2705 ? VVAL_TRUE : VVAL_FALSE;
2706 tv->v_type = VAR_BOOL;
2707 }
2708 }
2709
2710 p = may_peek_next_line(cctx, *arg, &next);
2711 }
2712
2713 if (check_ppconst_bool(ppconst) == FAIL)
2714 {
2715 ga_clear(&end_ga);
2716 return FAIL;
2717 }
2718
2719 if (cctx->ctx_skip != SKIP_YES && ppconst->pp_used == 0)
2720 // Every part must evaluate to a bool.
2721 if (bool_on_stack(cctx) == FAIL)
2722 {
2723 ga_clear(&end_ga);
2724 return FAIL;
2725 }
2726
2727 if (end_ga.ga_len > 0)
2728 {
2729 // Fill in the end label in all jumps.
2730 generate_ppconst(cctx, ppconst);
2731 while (end_ga.ga_len > 0)
2732 {
2733 isn_T *isn;
2734
2735 --end_ga.ga_len;
2736 isn = ((isn_T *)instr->ga_data)
2737 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
2738 isn->isn_arg.jump.jump_where = instr->ga_len;
2739 }
2740 }
2741 ga_clear(&end_ga);
2742
2743 cctx->ctx_skip = save_skip;
2744 }
2745
2746 return OK;
2747}
2748
2749/*
2750 * expr4a && expr4a && expr4a logical AND
2751 *
2752 * Produces instructions:
2753 * EVAL expr4a Push result of "expr4a"
2754 * COND2BOOL convert to bool if needed
2755 * JUMP_IF_COND_FALSE end
2756 * EVAL expr4b Push result of "expr4b"
2757 * JUMP_IF_COND_FALSE end
2758 * EVAL expr4c Push result of "expr4c"
2759 * end:
2760 */
2761 static int
2762compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2763{
2764 int ppconst_used = ppconst->pp_used;
2765
2766 // get the first variable
2767 if (compile_expr4(arg, cctx, ppconst) == FAIL)
2768 return FAIL;
2769
2770 // || and && work almost the same
2771 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
2772}
2773
2774/*
2775 * expr3a || expr3b || expr3c logical OR
2776 *
2777 * Produces instructions:
2778 * EVAL expr3a Push result of "expr3a"
2779 * COND2BOOL convert to bool if needed
2780 * JUMP_IF_COND_TRUE end
2781 * EVAL expr3b Push result of "expr3b"
2782 * JUMP_IF_COND_TRUE end
2783 * EVAL expr3c Push result of "expr3c"
2784 * end:
2785 */
2786 static int
2787compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2788{
2789 int ppconst_used = ppconst->pp_used;
2790
2791 // eval the first expression
2792 if (compile_expr3(arg, cctx, ppconst) == FAIL)
2793 return FAIL;
2794
2795 // || and && work almost the same
2796 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
2797}
2798
2799/*
2800 * Toplevel expression: expr2 ? expr1a : expr1b
2801 * Produces instructions:
2802 * EVAL expr2 Push result of "expr2"
2803 * JUMP_IF_FALSE alt jump if false
2804 * EVAL expr1a
2805 * JUMP_ALWAYS end
2806 * alt: EVAL expr1b
2807 * end:
2808 *
2809 * Toplevel expression: expr2 ?? expr1
2810 * Produces instructions:
2811 * EVAL expr2 Push result of "expr2"
2812 * JUMP_AND_KEEP_IF_TRUE end jump if true
2813 * EVAL expr1
2814 * end:
2815 */
2816 int
2817compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2818{
2819 char_u *p;
2820 int ppconst_used = ppconst->pp_used;
2821 char_u *next;
2822
2823 // Ignore all kinds of errors when not producing code.
2824 if (cctx->ctx_skip == SKIP_YES)
2825 {
2826 skip_expr_cctx(arg, cctx);
2827 return OK;
2828 }
2829
2830 // Evaluate the first expression.
2831 if (compile_expr2(arg, cctx, ppconst) == FAIL)
2832 return FAIL;
2833
2834 p = may_peek_next_line(cctx, *arg, &next);
2835 if (*p == '?')
2836 {
2837 int op_falsy = p[1] == '?';
2838 garray_T *instr = &cctx->ctx_instr;
2839 garray_T *stack = &cctx->ctx_type_stack;
2840 int alt_idx = instr->ga_len;
2841 int end_idx = 0;
2842 isn_T *isn;
2843 type_T *type1 = NULL;
2844 int has_const_expr = FALSE;
2845 int const_value = FALSE;
2846 int save_skip = cctx->ctx_skip;
2847
2848 if (next != NULL)
2849 {
2850 *arg = next_line_from_context(cctx, TRUE);
2851 p = skipwhite(*arg);
2852 }
2853
2854 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
2855 {
2856 semsg(_(e_white_space_required_before_and_after_str_at_str),
2857 op_falsy ? "??" : "?", p);
2858 return FAIL;
2859 }
2860
2861 if (ppconst->pp_used == ppconst_used + 1)
2862 {
2863 // the condition is a constant, we know whether the ? or the :
2864 // expression is to be evaluated.
2865 has_const_expr = TRUE;
2866 if (op_falsy)
2867 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
2868 else
2869 {
2870 int error = FALSE;
2871
2872 const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
2873 &error);
2874 if (error)
2875 return FAIL;
2876 }
2877 cctx->ctx_skip = save_skip == SKIP_YES ||
2878 (op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
2879
2880 if (op_falsy && cctx->ctx_skip == SKIP_YES)
2881 // "left ?? right" and "left" is truthy: produce "left"
2882 generate_ppconst(cctx, ppconst);
2883 else
2884 {
2885 clear_tv(&ppconst->pp_tv[ppconst_used]);
2886 --ppconst->pp_used;
2887 }
2888 }
2889 else
2890 {
2891 generate_ppconst(cctx, ppconst);
2892 if (op_falsy)
2893 end_idx = instr->ga_len;
2894 generate_JUMP(cctx, op_falsy
2895 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
2896 if (op_falsy)
Bram Moolenaar078a4612022-01-04 15:17:03 +00002897 type1 = get_type_on_stack(cctx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002898 }
2899
2900 // evaluate the second expression; any type is accepted
2901 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
2902 return FAIL;
2903 if (compile_expr1(arg, cctx, ppconst) == FAIL)
2904 return FAIL;
2905
2906 if (!has_const_expr)
2907 {
2908 generate_ppconst(cctx, ppconst);
2909
2910 if (!op_falsy)
2911 {
2912 // remember the type and drop it
Bram Moolenaar078a4612022-01-04 15:17:03 +00002913 type1 = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002914 --stack->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002915
2916 end_idx = instr->ga_len;
2917 generate_JUMP(cctx, JUMP_ALWAYS, 0);
2918
2919 // jump here from JUMP_IF_FALSE
2920 isn = ((isn_T *)instr->ga_data) + alt_idx;
2921 isn->isn_arg.jump.jump_where = instr->ga_len;
2922 }
2923 }
2924
2925 if (!op_falsy)
2926 {
2927 // Check for the ":".
2928 p = may_peek_next_line(cctx, *arg, &next);
2929 if (*p != ':')
2930 {
2931 emsg(_(e_missing_colon_after_questionmark));
2932 return FAIL;
2933 }
2934 if (next != NULL)
2935 {
2936 *arg = next_line_from_context(cctx, TRUE);
2937 p = skipwhite(*arg);
2938 }
2939
2940 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
2941 {
2942 semsg(_(e_white_space_required_before_and_after_str_at_str),
2943 ":", p);
2944 return FAIL;
2945 }
2946
2947 // evaluate the third expression
2948 if (has_const_expr)
2949 cctx->ctx_skip = save_skip == SKIP_YES || const_value
2950 ? SKIP_YES : SKIP_NOT;
2951 if (may_get_next_line_error(p + 1, arg, cctx) == FAIL)
2952 return FAIL;
2953 if (compile_expr1(arg, cctx, ppconst) == FAIL)
2954 return FAIL;
2955 }
2956
2957 if (!has_const_expr)
2958 {
2959 type_T **typep;
2960
2961 generate_ppconst(cctx, ppconst);
Bram Moolenaarfa46ead2021-12-22 13:18:39 +00002962 ppconst->pp_is_const = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002963
2964 // If the types differ, the result has a more generic type.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002965 typep = &((((type2_T *)stack->ga_data)
2966 + stack->ga_len - 1)->type_curr);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002967 common_type(type1, *typep, typep, cctx->ctx_type_list);
2968
2969 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
2970 isn = ((isn_T *)instr->ga_data) + end_idx;
2971 isn->isn_arg.jump.jump_where = instr->ga_len;
2972 }
2973
2974 cctx->ctx_skip = save_skip;
2975 }
2976 return OK;
2977}
2978
2979/*
2980 * Toplevel expression.
2981 * Sets "is_const" (if not NULL) to indicate the value is a constant.
2982 * Returns OK or FAIL.
2983 */
2984 int
2985compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const)
2986{
2987 ppconst_T ppconst;
2988
2989 CLEAR_FIELD(ppconst);
2990 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
2991 {
2992 clear_ppconst(&ppconst);
2993 return FAIL;
2994 }
2995 if (is_const != NULL)
2996 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const;
2997 if (generate_ppconst(cctx, &ppconst) == FAIL)
2998 return FAIL;
2999 return OK;
3000}
3001
3002/*
3003 * Toplevel expression.
3004 */
3005 int
3006compile_expr0(char_u **arg, cctx_T *cctx)
3007{
3008 return compile_expr0_ext(arg, cctx, NULL);
3009}
3010
3011
3012#endif // defined(FEAT_EVAL)