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