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