blob: c8054e52d0055c819d2fb30a6417919cba86a03e [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/*
Kota Kato948a3892022-08-16 16:09:59 +010011 * vim9expr.c: Dealing with compiled function expressions
Bram Moolenaardc7c3662021-12-20 15:04:29 +000012 */
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 Moolenaar4913d422022-10-17 13:13:32 +010096 if ((typep->type_curr->tt_type == VAR_ANY
97 || typep->type_curr->tt_type == VAR_UNKNOWN)
Bram Moolenaar078a4612022-01-04 15:17:03 +000098 && idxtype == &t_string)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000099 vartype = VAR_DICT;
100 if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB)
101 {
102 if (need_type(idxtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
103 return FAIL;
104 if (is_slice)
105 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000106 idxtype = get_type_on_stack(cctx, 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000107 if (need_type(idxtype, &t_number, -2, 0, cctx,
108 FALSE, FALSE) == FAIL)
109 return FAIL;
110 }
111 }
112
113 if (vartype == VAR_DICT)
114 {
115 if (is_slice)
116 {
117 emsg(_(e_cannot_slice_dictionary));
118 return FAIL;
119 }
Bram Moolenaar078a4612022-01-04 15:17:03 +0000120 if (typep->type_curr->tt_type == VAR_DICT)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000121 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000122 typep->type_curr = typep->type_curr->tt_member;
123 if (typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000124 // empty dict was used
Bram Moolenaar078a4612022-01-04 15:17:03 +0000125 typep->type_curr = &t_any;
126 if (typep->type_decl->tt_type == VAR_DICT)
127 {
128 typep->type_decl = typep->type_decl->tt_member;
129 if (typep->type_decl == &t_unknown)
130 // empty dict was used
131 typep->type_decl = &t_any;
132 }
133 else
134 typep->type_decl = typep->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000135 }
136 else
137 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000138 if (need_type(typep->type_curr, &t_dict_any, -2, 0, cctx,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000139 FALSE, FALSE) == FAIL)
140 return FAIL;
Bram Moolenaar078a4612022-01-04 15:17:03 +0000141 typep->type_curr = &t_any;
142 typep->type_decl = &t_any;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000143 }
Bram Moolenaard0132f42022-05-12 11:05:40 +0100144 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL
145 || generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000146 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 Moolenaar4913d422022-10-17 13:13:32 +0100176 else if (vartype == VAR_LIST || typep->type_curr->tt_type == VAR_ANY
177 || typep->type_curr->tt_type == VAR_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 Moolenaaradbc08f2022-11-06 18:27:17 +0000188
189 // a copy is made, the composite is no longer "const"
190 if (typep->type_curr->tt_flags & TTFLAG_CONST)
191 {
192 type_T *type = copy_type(typep->type_curr, cctx->ctx_type_list);
193
194 if (type != typep->type_curr) // did get a copy
195 {
196 type->tt_flags &= ~(TTFLAG_CONST | TTFLAG_STATIC);
197 typep->type_curr = type;
198 }
199 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000200 }
201 else
202 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000203 if (typep->type_curr->tt_type == VAR_LIST)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000204 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000205 typep->type_curr = typep->type_curr->tt_member;
206 if (typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000207 // empty list was used
Bram Moolenaar078a4612022-01-04 15:17:03 +0000208 typep->type_curr = &t_any;
209 if (typep->type_decl->tt_type == VAR_LIST)
210 {
211 typep->type_decl = typep->type_decl->tt_member;
212 if (typep->type_decl == &t_unknown)
213 // empty list was used
214 typep->type_decl = &t_any;
215 }
216 else
217 typep->type_decl = typep->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000218 }
219 if (generate_instr_drop(cctx,
220 vartype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1)
221 == FAIL)
222 return FAIL;
223 }
224 }
225 else
226 {
227 switch (vartype)
228 {
229 case VAR_FUNC:
230 case VAR_PARTIAL:
231 emsg(_(e_cannot_index_a_funcref));
232 break;
233 case VAR_BOOL:
234 case VAR_SPECIAL:
235 case VAR_JOB:
236 case VAR_CHANNEL:
237 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000238 case VAR_CLASS:
239 case VAR_OBJECT:
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000240 case VAR_UNKNOWN:
241 case VAR_ANY:
242 case VAR_VOID:
243 emsg(_(e_cannot_index_special_variable));
244 break;
245 default:
246 emsg(_(e_string_list_dict_or_blob_required));
247 }
248 return FAIL;
249 }
250 return OK;
251}
252
253/*
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000254 * Compile ".member" coming after an object or class.
255 */
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000256 static int
257compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type)
258{
259 if (VIM_ISWHITE((*arg)[1]))
260 {
261 semsg(_(e_no_white_space_allowed_after_str_str), ".", *arg);
262 return FAIL;
263 }
264
265 ++*arg;
266 char_u *name = *arg;
267 char_u *name_end = find_name_end(name, NULL, NULL, FNE_CHECK_START);
268 if (name_end == name)
269 return FAIL;
270 size_t len = name_end - name;
271
272 class_T *cl = (class_T *)type->tt_member;
273 if (*name_end == '(')
274 {
275 // TODO
276 }
277 else if (type->tt_type == VAR_OBJECT)
278 {
279 for (int i = 0; i < cl->class_obj_member_count; ++i)
280 {
281 objmember_T *m = &cl->class_obj_members[i];
282 if (STRNCMP(name, m->om_name, len) == 0 && m->om_name[len] == NUL)
283 {
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000284 generate_GET_OBJ_MEMBER(cctx, i, m->om_type);
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000285
286 *arg = name_end;
287 return OK;
288 }
289 }
290
291 semsg(_(e_member_not_found_on_object_str_str), cl->class_name, name);
292 }
293 else
294 {
295 // TODO: class member
296 emsg("compile_class_object_index(): not handled");
297 }
298
299 return FAIL;
300}
301
302/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000303 * Generate an instruction to load script-local variable "name", without the
304 * leading "s:".
305 * Also finds imported variables.
306 */
307 int
308compile_load_scriptvar(
309 cctx_T *cctx,
310 char_u *name, // variable NUL terminated
311 char_u *start, // start of variable
Bram Moolenaard0132f42022-05-12 11:05:40 +0100312 char_u **end) // end of variable, may be NULL
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000313{
314 scriptitem_T *si;
315 int idx;
316 imported_T *import;
317
318 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
319 return FAIL;
320 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaarb6a138e2022-02-08 21:17:22 +0000321 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx, NULL);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000322 if (idx >= 0)
323 {
324 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
325
326 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
327 current_sctx.sc_sid, idx, sv->sv_type);
328 return OK;
329 }
330
Bram Moolenaar4b1d9632022-02-13 21:51:08 +0000331 import = end == NULL ? NULL : find_imported(name, 0, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000332 if (import != NULL)
333 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000334 char_u *p = skipwhite(*end);
335 char_u *exp_name;
336 int cc;
Bram Moolenaarffe6e642022-04-01 13:23:47 +0100337 ufunc_T *ufunc = NULL;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000338 type_T *type;
Bram Moolenaard041f422022-01-12 19:54:00 +0000339 int done = FALSE;
340 int res = OK;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000341
342 // Need to lookup the member.
343 if (*p != '.')
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000344 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000345 semsg(_(e_expected_dot_after_name_str), start);
346 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000347 }
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000348 ++p;
349 if (VIM_ISWHITE(*p))
350 {
351 emsg(_(e_no_white_space_allowed_after_dot));
352 return FAIL;
353 }
354
355 // isolate one name
356 exp_name = p;
357 while (eval_isnamec(*p))
358 ++p;
359 cc = *p;
360 *p = NUL;
361
Bram Moolenaard041f422022-01-12 19:54:00 +0000362 si = SCRIPT_ITEM(import->imp_sid);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100363 if (si->sn_import_autoload && si->sn_state == SN_STATE_NOT_LOADED)
364 // "import autoload './dir/script.vim'" or
365 // "import autoload './autoload/script.vim'" - load script first
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100366 res = generate_SOURCE(cctx, import->imp_sid);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100367
368 if (res == OK)
369 {
370 if (si->sn_autoload_prefix != NULL
371 && si->sn_state == SN_STATE_NOT_LOADED)
372 {
373 char_u *auto_name =
374 concat_str(si->sn_autoload_prefix, exp_name);
375
376 // autoload script must be loaded later, access by the autoload
377 // name. If a '(' follows it must be a function. Otherwise we
378 // don't know, it can be "script.Func".
379 if (cc == '(' || paren_follows_after_expr)
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100380 res = generate_PUSHFUNC(cctx, auto_name, &t_func_any, TRUE);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100381 else
382 res = generate_AUTOLOAD(cctx, auto_name, &t_any);
383 vim_free(auto_name);
384 done = TRUE;
385 }
386 else if (si->sn_import_autoload
387 && si->sn_state == SN_STATE_NOT_LOADED)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100388 {
389 // If a '(' follows it must be a function. Otherwise we don't
390 // know, it can be "script.Func".
391 if (cc == '(' || paren_follows_after_expr)
392 {
393 char_u sid_name[MAX_FUNC_NAME_LEN];
394
395 func_name_with_sid(exp_name, import->imp_sid, sid_name);
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100396 res = generate_PUSHFUNC(cctx, sid_name, &t_func_any, TRUE);
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100397 }
398 else
399 res = generate_OLDSCRIPT(cctx, ISN_LOADEXPORT, exp_name,
400 import->imp_sid, &t_any);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100401 done = TRUE;
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100402 }
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100403 else
404 {
405 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
406 cctx, NULL, TRUE);
407 }
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100408 }
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100409
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000410 *p = cc;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000411 *end = p;
Bram Moolenaard041f422022-01-12 19:54:00 +0000412 if (done)
413 return res;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000414
415 if (idx < 0)
416 {
417 if (ufunc != NULL)
418 {
419 // function call or function reference
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100420 generate_PUSHFUNC(cctx, ufunc->uf_name, NULL, TRUE);
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000421 return OK;
422 }
423 return FAIL;
424 }
425
426 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
427 import->imp_sid,
428 idx,
429 type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000430 return OK;
431 }
432
Bram Moolenaard0132f42022-05-12 11:05:40 +0100433 // Can only get here if we know "name" is a script variable and not in a
434 // Vim9 script (variable is not in sn_var_vals): old style script.
435 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
Bram Moolenaar62aec932022-01-29 21:45:34 +0000436 &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000437}
438
439 static int
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000440generate_funcref(cctx_T *cctx, char_u *name, int has_g_prefix)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000441{
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000442 ufunc_T *ufunc = find_func(name, FALSE);
Bram Moolenaar139575d2022-03-15 19:29:30 +0000443 compiletype_T compile_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000444
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000445 // Reject a global non-autoload function found without the "g:" prefix.
446 if (ufunc == NULL || (!has_g_prefix && func_requires_g_prefix(ufunc)))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000447 return FAIL;
448
449 // Need to compile any default values to get the argument types.
Bram Moolenaar139575d2022-03-15 19:29:30 +0000450 compile_type = get_compile_type(ufunc);
451 if (func_needs_compiling(ufunc, compile_type)
Bram Moolenaar21dc8f12022-03-16 17:54:17 +0000452 && compile_def_function(ufunc, TRUE, compile_type, NULL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000453 return FAIL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100454 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000455}
456
457/*
458 * Compile a variable name into a load instruction.
459 * "end" points to just after the name.
460 * "is_expr" is TRUE when evaluating an expression, might be a funcref.
461 * When "error" is FALSE do not give an error when not found.
462 */
463 int
464compile_load(
465 char_u **arg,
466 char_u *end_arg,
467 cctx_T *cctx,
468 int is_expr,
469 int error)
470{
471 type_T *type;
472 char_u *name = NULL;
473 char_u *end = end_arg;
474 int res = FAIL;
475 int prev_called_emsg = called_emsg;
476
477 if (*(*arg + 1) == ':')
478 {
479 if (end <= *arg + 2)
480 {
481 isntype_T isn_type;
482
483 // load dictionary of namespace
484 switch (**arg)
485 {
486 case 'g': isn_type = ISN_LOADGDICT; break;
487 case 'w': isn_type = ISN_LOADWDICT; break;
488 case 't': isn_type = ISN_LOADTDICT; break;
489 case 'b': isn_type = ISN_LOADBDICT; break;
490 default:
491 semsg(_(e_namespace_not_supported_str), *arg);
492 goto theend;
493 }
494 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
495 goto theend;
496 res = OK;
497 }
498 else
499 {
500 isntype_T isn_type = ISN_DROP;
501
502 // load namespaced variable
503 name = vim_strnsave(*arg + 2, end - (*arg + 2));
504 if (name == NULL)
505 return FAIL;
506
507 switch (**arg)
508 {
Bram Moolenaarc3caa7f2022-05-25 19:15:10 +0100509 case 'v': res = generate_LOADV(cctx, name);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000510 break;
Bram Moolenaarafa048f2022-02-22 20:43:36 +0000511 case 's': if (current_script_is_vim9())
512 {
513 semsg(_(e_cannot_use_s_colon_in_vim9_script_str),
514 *arg);
515 vim_free(name);
516 return FAIL;
517 }
Kota Kato948a3892022-08-16 16:09:59 +0100518 if (is_expr && find_func(name, FALSE) != NULL)
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000519 res = generate_funcref(cctx, name, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000520 else
521 res = compile_load_scriptvar(cctx, name,
Bram Moolenaard0132f42022-05-12 11:05:40 +0100522 NULL, &end);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000523 break;
524 case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
525 {
526 if (is_expr && ASCII_ISUPPER(*name)
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000527 && find_func(name, FALSE) != NULL)
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000528 res = generate_funcref(cctx, name, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000529 else
530 isn_type = ISN_LOADG;
531 }
532 else
533 {
534 isn_type = ISN_LOADAUTO;
535 vim_free(name);
536 name = vim_strnsave(*arg, end - *arg);
537 if (name == NULL)
538 return FAIL;
539 }
540 break;
541 case 'w': isn_type = ISN_LOADW; break;
542 case 't': isn_type = ISN_LOADT; break;
543 case 'b': isn_type = ISN_LOADB; break;
544 default: // cannot happen, just in case
545 semsg(_(e_namespace_not_supported_str), *arg);
546 goto theend;
547 }
548 if (isn_type != ISN_DROP)
549 {
550 // Global, Buffer-local, Window-local and Tabpage-local
551 // variables can be defined later, thus we don't check if it
552 // exists, give an error at runtime.
Bram Moolenaarfa46ead2021-12-22 13:18:39 +0000553 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000554 }
555 }
556 }
557 else
558 {
559 size_t len = end - *arg;
560 int idx;
561 int gen_load = FALSE;
562 int gen_load_outer = 0;
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +0100563 int outer_loop_depth = -1;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +0100564 int outer_loop_idx = -1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000565
566 name = vim_strnsave(*arg, end - *arg);
567 if (name == NULL)
568 return FAIL;
569
570 if (vim_strchr(name, AUTOLOAD_CHAR) != NULL)
571 {
572 script_autoload(name, FALSE);
573 res = generate_LOAD(cctx, ISN_LOADAUTO, 0, name, &t_any);
574 }
575 else if (arg_exists(*arg, len, &idx, &type, &gen_load_outer, cctx)
576 == OK)
577 {
578 if (gen_load_outer == 0)
579 gen_load = TRUE;
580 }
581 else
582 {
583 lvar_T lvar;
584
585 if (lookup_local(*arg, len, &lvar, cctx) == OK)
586 {
587 type = lvar.lv_type;
588 idx = lvar.lv_idx;
589 if (lvar.lv_from_outer != 0)
Bram Moolenaarf8addf12022-09-23 12:44:25 +0100590 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000591 gen_load_outer = lvar.lv_from_outer;
Bram Moolenaarf8addf12022-09-23 12:44:25 +0100592 outer_loop_depth = lvar.lv_loop_depth;
593 outer_loop_idx = lvar.lv_loop_idx;
594 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000595 else
596 gen_load = TRUE;
597 }
598 else
599 {
600 // "var" can be script-local even without using "s:" if it
601 // already exists in a Vim9 script or when it's imported.
Bram Moolenaardce24412022-02-08 20:35:30 +0000602 if (script_var_exists(*arg, len, cctx, NULL) == OK
Bram Moolenaar4b1d9632022-02-13 21:51:08 +0000603 || find_imported(name, 0, FALSE) != NULL)
Bram Moolenaard0132f42022-05-12 11:05:40 +0100604 res = compile_load_scriptvar(cctx, name, *arg, &end);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000605
606 // When evaluating an expression and the name starts with an
607 // uppercase letter it can be a user defined function.
608 // generate_funcref() will fail if the function can't be found.
609 if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000610 res = generate_funcref(cctx, name, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000611 }
612 }
613 if (gen_load)
614 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
615 if (gen_load_outer > 0)
616 {
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +0100617 res = generate_LOADOUTER(cctx, idx, gen_load_outer,
618 outer_loop_depth, outer_loop_idx, type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000619 cctx->ctx_outer_used = TRUE;
620 }
621 }
622
623 *arg = end;
624
625theend:
626 if (res == FAIL && error && called_emsg == prev_called_emsg)
627 semsg(_(e_variable_not_found_str), name);
628 vim_free(name);
629 return res;
630}
631
632/*
633 * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR.
LemonBoyf3b48952022-05-05 13:53:03 +0100634 * "str_offset" is the number of leading bytes to skip from the string.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000635 * Returns FAIL if compilation fails.
636 */
637 static int
LemonBoyf3b48952022-05-05 13:53:03 +0100638compile_string(isn_T *isn, cctx_T *cctx, int str_offset)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000639{
LemonBoyf3b48952022-05-05 13:53:03 +0100640 char_u *s = isn->isn_arg.string + str_offset;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000641 garray_T save_ga = cctx->ctx_instr;
642 int expr_res;
643 int trailing_error;
644 int instr_count;
645 isn_T *instr = NULL;
646
647 // Remove the string type from the stack.
648 --cctx->ctx_type_stack.ga_len;
649
650 // Temporarily reset the list of instructions so that the jump labels are
651 // correct.
652 cctx->ctx_instr.ga_len = 0;
653 cctx->ctx_instr.ga_maxlen = 0;
654 cctx->ctx_instr.ga_data = NULL;
655 expr_res = compile_expr0(&s, cctx);
656 s = skipwhite(s);
657 trailing_error = *s != NUL;
658
659 if (expr_res == FAIL || trailing_error
660 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
661 {
662 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +0000663 semsg(_(e_trailing_characters_str), s);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000664 clear_instr_ga(&cctx->ctx_instr);
665 cctx->ctx_instr = save_ga;
666 ++cctx->ctx_type_stack.ga_len;
667 return FAIL;
668 }
669
670 // Move the generated instructions into the ISN_INSTR instruction, then
671 // restore the list of instructions.
672 instr_count = cctx->ctx_instr.ga_len;
673 instr = cctx->ctx_instr.ga_data;
674 instr[instr_count].isn_type = ISN_FINISH;
675
676 cctx->ctx_instr = save_ga;
677 vim_free(isn->isn_arg.string);
678 isn->isn_type = ISN_INSTR;
679 isn->isn_arg.instr = instr;
680 return OK;
681}
682
683/*
684 * Compile the argument expressions.
685 * "arg" points to just after the "(" and is advanced to after the ")"
686 */
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100687 int
LemonBoyf3b48952022-05-05 13:53:03 +0100688compile_arguments(
689 char_u **arg,
690 cctx_T *cctx,
691 int *argcount,
692 ca_special_T special_fn)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000693{
694 char_u *p = *arg;
695 char_u *whitep = *arg;
696 int must_end = FALSE;
697 int instr_count;
698
699 for (;;)
700 {
701 if (may_get_next_line(whitep, &p, cctx) == FAIL)
702 goto failret;
703 if (*p == ')')
704 {
705 *arg = p + 1;
706 return OK;
707 }
708 if (must_end)
709 {
710 semsg(_(e_missing_comma_before_argument_str), p);
711 return FAIL;
712 }
713
714 instr_count = cctx->ctx_instr.ga_len;
715 if (compile_expr0(&p, cctx) == FAIL)
716 return FAIL;
717 ++*argcount;
718
LemonBoyf3b48952022-05-05 13:53:03 +0100719 if (special_fn == CA_SEARCHPAIR && *argcount == 5
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000720 && cctx->ctx_instr.ga_len == instr_count + 1)
721 {
722 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
723
724 // {skip} argument of searchpair() can be compiled if not empty
725 if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL)
LemonBoyf3b48952022-05-05 13:53:03 +0100726 compile_string(isn, cctx, 0);
727 }
728 else if (special_fn == CA_SUBSTITUTE && *argcount == 3
729 && cctx->ctx_instr.ga_len == instr_count + 1)
730 {
731 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
732
733 // {sub} argument of substitute() can be compiled if it starts
734 // with \=
735 if (isn->isn_type == ISN_PUSHS && isn->isn_arg.string[0] == '\\'
Bram Moolenaar4913d422022-10-17 13:13:32 +0100736 && isn->isn_arg.string[1] == '=')
LemonBoyf3b48952022-05-05 13:53:03 +0100737 compile_string(isn, cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000738 }
739
740 if (*p != ',' && *skipwhite(p) == ',')
741 {
742 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
743 p = skipwhite(p);
744 }
745 if (*p == ',')
746 {
747 ++p;
748 if (*p != NUL && !VIM_ISWHITE(*p))
749 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
750 }
751 else
752 must_end = TRUE;
753 whitep = p;
754 p = skipwhite(p);
755 }
756failret:
757 emsg(_(e_missing_closing_paren));
758 return FAIL;
759}
760
761/*
762 * Compile a function call: name(arg1, arg2)
763 * "arg" points to "name", "arg + varlen" to the "(".
764 * "argcount_init" is 1 for "value->method()"
765 * Instructions:
766 * EVAL arg1
767 * EVAL arg2
768 * BCALL / DCALL / UCALL
769 */
770 static int
771compile_call(
772 char_u **arg,
773 size_t varlen,
774 cctx_T *cctx,
775 ppconst_T *ppconst,
776 int argcount_init)
777{
778 char_u *name = *arg;
779 char_u *p;
780 int argcount = argcount_init;
Bram Moolenaara6c18d32022-03-31 20:02:56 +0100781 char_u namebuf[MAX_FUNC_NAME_LEN];
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000782 char_u fname_buf[FLEN_FIXED + 1];
783 char_u *tofree = NULL;
784 int error = FCERR_NONE;
785 ufunc_T *ufunc = NULL;
786 int res = FAIL;
787 int is_autoload;
Bram Moolenaar62aec932022-01-29 21:45:34 +0000788 int has_g_namespace;
LemonBoyf3b48952022-05-05 13:53:03 +0100789 ca_special_T special_fn;
Bram Moolenaarf67c7172022-01-19 17:23:05 +0000790 imported_T *import;
791
792 if (varlen >= sizeof(namebuf))
793 {
794 semsg(_(e_name_too_long_str), name);
795 return FAIL;
796 }
797 vim_strncpy(namebuf, *arg, varlen);
798
Bram Moolenaar4b1d9632022-02-13 21:51:08 +0000799 import = find_imported(name, varlen, FALSE);
Bram Moolenaarf67c7172022-01-19 17:23:05 +0000800 if (import != NULL)
801 {
802 semsg(_(e_cannot_use_str_itself_it_is_imported), namebuf);
803 return FAIL;
804 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000805
806 // We can evaluate "has('name')" at compile time.
LemonBoy58f331a2022-04-02 21:59:06 +0100807 // We can evaluate "len('string')" at compile time.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000808 // We always evaluate "exists_compiled()" at compile time.
LemonBoy58f331a2022-04-02 21:59:06 +0100809 if ((varlen == 3
810 && (STRNCMP(*arg, "has", 3) == 0 || STRNCMP(*arg, "len", 3) == 0))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000811 || (varlen == 15 && STRNCMP(*arg, "exists_compiled", 6) == 0))
812 {
813 char_u *s = skipwhite(*arg + varlen + 1);
814 typval_T argvars[2];
815 int is_has = **arg == 'h';
LemonBoy58f331a2022-04-02 21:59:06 +0100816 int is_len = **arg == 'l';
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000817
818 argvars[0].v_type = VAR_UNKNOWN;
819 if (*s == '"')
Bram Moolenaar0abc2872022-05-10 13:24:30 +0100820 (void)eval_string(&s, &argvars[0], TRUE, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000821 else if (*s == '\'')
Bram Moolenaar0abc2872022-05-10 13:24:30 +0100822 (void)eval_lit_string(&s, &argvars[0], TRUE, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000823 s = skipwhite(s);
824 if (*s == ')' && argvars[0].v_type == VAR_STRING
825 && ((is_has && !dynamic_feature(argvars[0].vval.v_string))
826 || !is_has))
827 {
828 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
829
830 *arg = s + 1;
831 argvars[1].v_type = VAR_UNKNOWN;
832 tv->v_type = VAR_NUMBER;
833 tv->vval.v_number = 0;
834 if (is_has)
835 f_has(argvars, tv);
LemonBoy58f331a2022-04-02 21:59:06 +0100836 else if (is_len)
837 f_len(argvars, tv);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000838 else
839 f_exists(argvars, tv);
840 clear_tv(&argvars[0]);
841 ++ppconst->pp_used;
842 return OK;
843 }
844 clear_tv(&argvars[0]);
LemonBoy58f331a2022-04-02 21:59:06 +0100845 if (!is_has && !is_len)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000846 {
847 emsg(_(e_argument_of_exists_compiled_must_be_literal_string));
848 return FAIL;
849 }
850 }
851
852 if (generate_ppconst(cctx, ppconst) == FAIL)
853 return FAIL;
854
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000855 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
856
857 // We handle the "skip" argument of searchpair() and searchpairpos()
858 // differently.
LemonBoyf3b48952022-05-05 13:53:03 +0100859 if ((varlen == 6 && STRNCMP(*arg, "search", 6) == 0)
860 || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0)
861 || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0)
862 || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0))
863 special_fn = CA_SEARCHPAIR;
864 else if (varlen == 10 && STRNCMP(*arg, "substitute", 10) == 0)
865 special_fn = CA_SUBSTITUTE;
866 else
867 special_fn = CA_NOT_SPECIAL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000868
869 *arg = skipwhite(*arg + varlen + 1);
LemonBoyf3b48952022-05-05 13:53:03 +0100870 if (compile_arguments(arg, cctx, &argcount, special_fn) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000871 goto theend;
872
873 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
874 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
875 {
876 int idx;
877
878 // builtin function
879 idx = find_internal_func(name);
880 if (idx >= 0)
881 {
882 if (STRCMP(name, "flatten") == 0)
883 {
884 emsg(_(e_cannot_use_flatten_in_vim9_script));
885 goto theend;
886 }
887
888 if (STRCMP(name, "add") == 0 && argcount == 2)
889 {
Bram Moolenaareb4a9ba2022-02-01 12:47:07 +0000890 type_T *type = get_decl_type_on_stack(cctx, 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000891
892 // add() can be compiled to instructions if we know the type
893 if (type->tt_type == VAR_LIST)
894 {
895 // inline "add(list, item)" so that the type can be checked
896 res = generate_LISTAPPEND(cctx);
897 idx = -1;
898 }
899 else if (type->tt_type == VAR_BLOB)
900 {
901 // inline "add(blob, nr)" so that the type can be checked
902 res = generate_BLOBAPPEND(cctx);
903 idx = -1;
904 }
905 }
906
Bram Moolenaarf5fec052022-09-11 11:49:22 +0100907 if ((STRCMP(name, "writefile") == 0 && argcount > 2)
908 || (STRCMP(name, "mkdir") == 0 && argcount > 1))
Bram Moolenaar806a2732022-09-04 15:40:36 +0100909 {
Bram Moolenaarf5fec052022-09-11 11:49:22 +0100910 // May have the "D" or "R" flag, reserve a variable for a
911 // deferred function call.
Bram Moolenaar806a2732022-09-04 15:40:36 +0100912 if (get_defer_var_idx(cctx) == 0)
913 idx = -1;
914 }
915
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000916 if (idx >= 0)
917 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
918 }
919 else
Bram Moolenaara6c18d32022-03-31 20:02:56 +0100920 emsg_funcname(e_unknown_function_str, namebuf);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000921 goto theend;
922 }
923
Bram Moolenaar62aec932022-01-29 21:45:34 +0000924 has_g_namespace = STRNCMP(namebuf, "g:", 2) == 0;
925
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000926 // An argument or local variable can be a function reference, this
927 // overrules a function name.
928 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL
929 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK)
930 {
931 // If we can find the function by name generate the right call.
932 // Skip global functions here, a local funcref takes precedence.
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000933 ufunc = find_func(name, FALSE);
Bram Moolenaar62aec932022-01-29 21:45:34 +0000934 if (ufunc != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000935 {
Bram Moolenaar62aec932022-01-29 21:45:34 +0000936 if (!func_is_global(ufunc))
937 {
938 res = generate_CALL(cctx, ufunc, argcount);
939 goto theend;
940 }
941 if (!has_g_namespace
942 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL)
943 {
944 // A function name without g: prefix must be found locally.
Bram Moolenaara6c18d32022-03-31 20:02:56 +0100945 emsg_funcname(e_unknown_function_str, namebuf);
Bram Moolenaar62aec932022-01-29 21:45:34 +0000946 goto theend;
947 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000948 }
949 }
950
951 // If the name is a variable, load it and use PCALL.
952 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000953 // Not for some#Func(), it will be loaded later.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000954 p = namebuf;
Bram Moolenaar62aec932022-01-29 21:45:34 +0000955 if (!has_g_namespace && !is_autoload
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000956 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
957 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000958 type_T *type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000959
960 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
961 goto theend;
962 }
963
964 // If we can find a global function by name generate the right call.
965 if (ufunc != NULL)
966 {
967 res = generate_CALL(cctx, ufunc, argcount);
968 goto theend;
969 }
970
971 // A global function may be defined only later. Need to figure out at
972 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar62aec932022-01-29 21:45:34 +0000973 if (has_g_namespace || is_autoload)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000974 res = generate_UCALL(cctx, name, argcount);
975 else
Bram Moolenaara6c18d32022-03-31 20:02:56 +0100976 emsg_funcname(e_unknown_function_str, namebuf);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000977
978theend:
979 vim_free(tofree);
980 return res;
981}
982
983// like NAMESPACE_CHAR but with 'a' and 'l'.
984#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
985
986/*
987 * Find the end of a variable or function name. Unlike find_name_end() this
988 * does not recognize magic braces.
989 * When "use_namespace" is TRUE recognize "b:", "s:", etc.
990 * Return a pointer to just after the name. Equal to "arg" if there is no
991 * valid name.
992 */
993 char_u *
994to_name_end(char_u *arg, int use_namespace)
995{
996 char_u *p;
997
998 // Quick check for valid starting character.
999 if (!eval_isnamec1(*arg))
1000 return arg;
1001
1002 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
1003 // Include a namespace such as "s:var" and "v:var". But "n:" is not
1004 // and can be used in slice "[n:]".
1005 if (*p == ':' && (p != arg + 1
1006 || !use_namespace
1007 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
1008 break;
1009 return p;
1010}
1011
1012/*
1013 * Like to_name_end() but also skip over a list or dict constant.
1014 * Also accept "<SNR>123_Func".
1015 * This intentionally does not handle line continuation.
1016 */
1017 char_u *
1018to_name_const_end(char_u *arg)
1019{
1020 char_u *p = arg;
1021 typval_T rettv;
1022
1023 if (STRNCMP(p, "<SNR>", 5) == 0)
1024 p = skipdigits(p + 5);
1025 p = to_name_end(p, TRUE);
1026 if (p == arg && *arg == '[')
1027 {
1028
1029 // Can be "[1, 2, 3]->Func()".
1030 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
1031 p = arg;
1032 }
1033 return p;
1034}
1035
1036/*
1037 * parse a list: [expr, expr]
1038 * "*arg" points to the '['.
1039 * ppconst->pp_is_const is set if all items are a constant.
1040 */
1041 static int
1042compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1043{
1044 char_u *p = skipwhite(*arg + 1);
1045 char_u *whitep = *arg + 1;
1046 int count = 0;
1047 int is_const;
1048 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar2984ed32022-08-20 14:51:17 +01001049 int must_end = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001050
1051 for (;;)
1052 {
1053 if (may_get_next_line(whitep, &p, cctx) == FAIL)
1054 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00001055 semsg(_(e_missing_end_of_list_rsb_str), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001056 return FAIL;
1057 }
1058 if (*p == ',')
1059 {
1060 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
1061 return FAIL;
1062 }
1063 if (*p == ']')
1064 {
1065 ++p;
1066 break;
1067 }
Bram Moolenaar2984ed32022-08-20 14:51:17 +01001068 if (must_end)
1069 {
1070 semsg(_(e_missing_comma_in_list_str), p);
1071 return FAIL;
1072 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001073 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL)
1074 return FAIL;
1075 if (!is_const)
1076 is_all_const = FALSE;
1077 ++count;
1078 if (*p == ',')
1079 {
1080 ++p;
1081 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
1082 {
1083 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
1084 return FAIL;
1085 }
1086 }
Bram Moolenaar2984ed32022-08-20 14:51:17 +01001087 else
1088 must_end = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001089 whitep = p;
1090 p = skipwhite(p);
1091 }
1092 *arg = p;
1093
1094 ppconst->pp_is_const = is_all_const;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001095 return generate_NEWLIST(cctx, count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001096}
1097
1098/*
1099 * Parse a lambda: "(arg, arg) => expr"
1100 * "*arg" points to the '('.
1101 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
1102 */
1103 static int
1104compile_lambda(char_u **arg, cctx_T *cctx)
1105{
1106 int r;
1107 typval_T rettv;
1108 ufunc_T *ufunc;
1109 evalarg_T evalarg;
1110
1111 init_evalarg(&evalarg);
1112 evalarg.eval_flags = EVAL_EVALUATE;
1113 evalarg.eval_cctx = cctx;
1114
1115 // Get the funcref in "rettv".
1116 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
1117 if (r != OK)
1118 {
1119 clear_evalarg(&evalarg, NULL);
1120 return r;
1121 }
1122
1123 // "rettv" will now be a partial referencing the function.
1124 ufunc = rettv.vval.v_partial->pt_func;
1125 ++ufunc->uf_refcount;
1126 clear_tv(&rettv);
1127
1128 // Compile it here to get the return type. The return type is optional,
1129 // when it's missing use t_unknown. This is recognized in
1130 // compile_return().
1131 if (ufunc->uf_ret_type->tt_type == VAR_VOID)
1132 ufunc->uf_ret_type = &t_unknown;
1133 compile_def_function(ufunc, FALSE, cctx->ctx_compile_type, cctx);
1134
1135 // When the outer function is compiled for profiling or debugging, the
1136 // lambda may be called without profiling or debugging. Compile it here in
1137 // the right context.
1138 if (cctx->ctx_compile_type == CT_DEBUG
1139#ifdef FEAT_PROFILE
1140 || cctx->ctx_compile_type == CT_PROFILE
1141#endif
1142 )
1143 compile_def_function(ufunc, FALSE, CT_NONE, cctx);
1144
Bram Moolenaar139575d2022-03-15 19:29:30 +00001145 // if the outer function is not compiled for debugging or profiling, this
1146 // one might be
1147 if (cctx->ctx_compile_type == CT_NONE)
Bram Moolenaar96923b72022-03-15 15:57:04 +00001148 {
Bram Moolenaar139575d2022-03-15 19:29:30 +00001149 compiletype_T compile_type = get_compile_type(ufunc);
1150
1151 if (compile_type != CT_NONE)
1152 compile_def_function(ufunc, FALSE, compile_type, cctx);
Bram Moolenaar96923b72022-03-15 15:57:04 +00001153 }
1154
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001155 // The last entry in evalarg.eval_tofree_ga is a copy of the last line and
1156 // "*arg" may point into it. Point into the original line to avoid a
1157 // dangling pointer.
1158 if (evalarg.eval_using_cmdline)
1159 {
1160 garray_T *gap = &evalarg.eval_tofree_ga;
1161 size_t off = *arg - ((char_u **)gap->ga_data)[gap->ga_len - 1];
1162
1163 *arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
1164 + off;
Bram Moolenaarf8addf12022-09-23 12:44:25 +01001165 evalarg.eval_using_cmdline = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001166 }
1167
1168 clear_evalarg(&evalarg, NULL);
1169
1170 if (ufunc->uf_def_status == UF_COMPILED)
1171 {
1172 // The return type will now be known.
1173 set_function_type(ufunc);
1174
1175 // The function reference count will be 1. When the ISN_FUNCREF
1176 // instruction is deleted the reference count is decremented and the
1177 // function is freed.
Bram Moolenaara915fa02022-03-23 11:29:15 +00001178 return generate_FUNCREF(cctx, ufunc, NULL);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001179 }
1180
1181 func_ptr_unref(ufunc);
1182 return FAIL;
1183}
1184
1185/*
1186 * Get a lambda and compile it. Uses Vim9 syntax.
1187 */
1188 int
1189get_lambda_tv_and_compile(
1190 char_u **arg,
1191 typval_T *rettv,
1192 int types_optional,
1193 evalarg_T *evalarg)
1194{
1195 int r;
1196 ufunc_T *ufunc;
1197 int save_sc_version = current_sctx.sc_version;
1198
1199 // Get the funcref in "rettv".
1200 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
1201 r = get_lambda_tv(arg, rettv, types_optional, evalarg);
1202 current_sctx.sc_version = save_sc_version;
1203 if (r != OK)
Bram Moolenaar7f8a3b12022-05-12 22:03:01 +01001204 return r; // currently unreachable
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001205
1206 // "rettv" will now be a partial referencing the function.
1207 ufunc = rettv->vval.v_partial->pt_func;
1208
1209 // Compile it here to get the return type. The return type is optional,
1210 // when it's missing use t_unknown. This is recognized in
1211 // compile_return().
1212 if (ufunc->uf_ret_type == NULL || ufunc->uf_ret_type->tt_type == VAR_VOID)
1213 ufunc->uf_ret_type = &t_unknown;
1214 compile_def_function(ufunc, FALSE, CT_NONE, NULL);
1215
1216 if (ufunc->uf_def_status == UF_COMPILED)
1217 {
1218 // The return type will now be known.
1219 set_function_type(ufunc);
1220 return OK;
1221 }
1222 clear_tv(rettv);
1223 return FAIL;
1224}
1225
1226/*
1227 * parse a dict: {key: val, [key]: val}
1228 * "*arg" points to the '{'.
1229 * ppconst->pp_is_const is set if all item values are a constant.
1230 */
1231 static int
1232compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1233{
1234 garray_T *instr = &cctx->ctx_instr;
1235 int count = 0;
1236 dict_T *d = dict_alloc();
1237 dictitem_T *item;
1238 char_u *whitep = *arg + 1;
1239 char_u *p;
1240 int is_const;
1241 int is_all_const = TRUE; // reset when non-const encountered
1242
1243 if (d == NULL)
1244 return FAIL;
1245 if (generate_ppconst(cctx, ppconst) == FAIL)
1246 return FAIL;
1247 for (;;)
1248 {
1249 char_u *key = NULL;
1250
1251 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1252 {
1253 *arg = NULL;
1254 goto failret;
1255 }
1256
1257 if (**arg == '}')
1258 break;
1259
1260 if (**arg == '[')
1261 {
1262 isn_T *isn;
1263
1264 // {[expr]: value} uses an evaluated key.
1265 *arg = skipwhite(*arg + 1);
1266 if (compile_expr0(arg, cctx) == FAIL)
1267 return FAIL;
1268 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
1269 if (isn->isn_type == ISN_PUSHNR)
1270 {
1271 char buf[NUMBUFLEN];
1272
1273 // Convert to string at compile time.
1274 vim_snprintf(buf, NUMBUFLEN, "%lld", isn->isn_arg.number);
1275 isn->isn_type = ISN_PUSHS;
1276 isn->isn_arg.string = vim_strsave((char_u *)buf);
1277 }
1278 if (isn->isn_type == ISN_PUSHS)
1279 key = isn->isn_arg.string;
1280 else if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1281 return FAIL;
1282 *arg = skipwhite(*arg);
1283 if (**arg != ']')
1284 {
1285 emsg(_(e_missing_matching_bracket_after_dict_key));
1286 return FAIL;
1287 }
1288 ++*arg;
1289 }
1290 else
1291 {
1292 // {"name": value},
1293 // {'name': value},
1294 // {name: value} use "name" as a literal key
1295 key = get_literal_key(arg);
1296 if (key == NULL)
1297 return FAIL;
1298 if (generate_PUSHS(cctx, &key) == FAIL)
1299 return FAIL;
1300 }
1301
1302 // Check for duplicate keys, if using string keys.
1303 if (key != NULL)
1304 {
1305 item = dict_find(d, key, -1);
1306 if (item != NULL)
1307 {
dundargocc57b5bc2022-11-02 13:30:51 +00001308 semsg(_(e_duplicate_key_in_dictionary), key);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001309 goto failret;
1310 }
1311 item = dictitem_alloc(key);
1312 if (item != NULL)
1313 {
1314 item->di_tv.v_type = VAR_UNKNOWN;
1315 item->di_tv.v_lock = 0;
1316 if (dict_add(d, item) == FAIL)
1317 dictitem_free(item);
1318 }
1319 }
1320
1321 if (**arg != ':')
1322 {
1323 if (*skipwhite(*arg) == ':')
1324 semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg);
1325 else
Bram Moolenaar74409f62022-01-01 15:58:22 +00001326 semsg(_(e_missing_colon_in_dictionary), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001327 return FAIL;
1328 }
1329 whitep = *arg + 1;
1330 if (!IS_WHITE_OR_NUL(*whitep))
1331 {
1332 semsg(_(e_white_space_required_after_str_str), ":", *arg);
1333 return FAIL;
1334 }
1335
1336 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1337 {
1338 *arg = NULL;
1339 goto failret;
1340 }
1341
1342 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL)
1343 return FAIL;
1344 if (!is_const)
1345 is_all_const = FALSE;
1346 ++count;
1347
1348 whitep = *arg;
1349 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1350 {
1351 *arg = NULL;
1352 goto failret;
1353 }
1354 if (**arg == '}')
1355 break;
1356 if (**arg != ',')
1357 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001358 semsg(_(e_missing_comma_in_dictionary), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001359 goto failret;
1360 }
1361 if (IS_WHITE_OR_NUL(*whitep))
1362 {
1363 semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep);
1364 return FAIL;
1365 }
1366 whitep = *arg + 1;
1367 if (!IS_WHITE_OR_NUL(*whitep))
1368 {
1369 semsg(_(e_white_space_required_after_str_str), ",", *arg);
1370 return FAIL;
1371 }
1372 *arg = skipwhite(whitep);
1373 }
1374
1375 *arg = *arg + 1;
1376
1377 // Allow for following comment, after at least one space.
1378 p = skipwhite(*arg);
1379 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
1380 *arg += STRLEN(*arg);
1381
1382 dict_unref(d);
1383 ppconst->pp_is_const = is_all_const;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001384 return generate_NEWDICT(cctx, count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001385
1386failret:
1387 if (*arg == NULL)
1388 {
1389 semsg(_(e_missing_dict_end), _("[end of lines]"));
1390 *arg = (char_u *)"";
1391 }
1392 dict_unref(d);
1393 return FAIL;
1394}
1395
1396/*
1397 * Compile "&option".
1398 */
1399 static int
1400compile_get_option(char_u **arg, cctx_T *cctx)
1401{
1402 typval_T rettv;
1403 char_u *start = *arg;
1404 int ret;
1405
1406 // parse the option and get the current value to get the type.
1407 rettv.v_type = VAR_UNKNOWN;
1408 ret = eval_option(arg, &rettv, TRUE);
1409 if (ret == OK)
1410 {
1411 // include the '&' in the name, eval_option() expects it.
1412 char_u *name = vim_strnsave(start, *arg - start);
1413 type_T *type = rettv.v_type == VAR_BOOL ? &t_bool
1414 : rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
1415
1416 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
1417 vim_free(name);
1418 }
1419 clear_tv(&rettv);
1420
1421 return ret;
1422}
1423
1424/*
1425 * Compile "$VAR".
1426 */
1427 static int
1428compile_get_env(char_u **arg, cctx_T *cctx)
1429{
1430 char_u *start = *arg;
1431 int len;
1432 int ret;
1433 char_u *name;
1434
1435 ++*arg;
1436 len = get_env_len(arg);
1437 if (len == 0)
1438 {
Bram Moolenaar5f25c382022-01-09 13:36:28 +00001439 semsg(_(e_syntax_error_at_str), start);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001440 return FAIL;
1441 }
1442
1443 // include the '$' in the name, eval_env_var() expects it.
1444 name = vim_strnsave(start, len + 1);
1445 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
1446 vim_free(name);
1447 return ret;
1448}
1449
1450/*
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001451 * Compile $"string" or $'string'.
LemonBoy2eaef102022-05-06 13:14:50 +01001452 */
1453 static int
1454compile_interp_string(char_u **arg, cctx_T *cctx)
1455{
1456 typval_T tv;
1457 int ret;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001458 int quote;
LemonBoy2eaef102022-05-06 13:14:50 +01001459 int evaluate = cctx->ctx_skip != SKIP_YES;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001460 int count = 0;
1461 char_u *p;
LemonBoy2eaef102022-05-06 13:14:50 +01001462
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001463 // *arg is on the '$' character, move it to the first string character.
1464 ++*arg;
1465 quote = **arg;
1466 ++*arg;
LemonBoy2eaef102022-05-06 13:14:50 +01001467
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001468 for (;;)
1469 {
1470 // Get the string up to the matching quote or to a single '{'.
1471 // "arg" is advanced to either the quote or the '{'.
1472 if (quote == '"')
1473 ret = eval_string(arg, &tv, evaluate, TRUE);
1474 else
1475 ret = eval_lit_string(arg, &tv, evaluate, TRUE);
1476 if (ret == FAIL)
1477 break;
1478 if (evaluate)
1479 {
1480 if ((tv.vval.v_string != NULL && *tv.vval.v_string != NUL)
1481 || (**arg != '{' && count == 0))
1482 {
1483 // generate non-empty string or empty string if it's the only
1484 // one
1485 if (generate_PUSHS(cctx, &tv.vval.v_string) == FAIL)
1486 return FAIL;
1487 tv.vval.v_string = NULL; // don't free it now
1488 ++count;
1489 }
1490 clear_tv(&tv);
1491 }
1492
1493 if (**arg != '{')
1494 {
1495 // found terminating quote
1496 ++*arg;
1497 break;
1498 }
1499
1500 p = compile_one_expr_in_str(*arg, cctx);
1501 if (p == NULL)
1502 {
1503 ret = FAIL;
1504 break;
1505 }
1506 ++count;
1507 *arg = p;
1508 }
LemonBoy2eaef102022-05-06 13:14:50 +01001509
1510 if (ret == FAIL || !evaluate)
1511 return ret;
1512
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001513 // Small optimization, if there's only a single piece skip the ISN_CONCAT.
1514 if (count > 1)
1515 return generate_CONCAT(cctx, count);
LemonBoy2eaef102022-05-06 13:14:50 +01001516
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001517 return OK;
LemonBoy2eaef102022-05-06 13:14:50 +01001518}
1519
1520/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001521 * Compile "@r".
1522 */
1523 static int
1524compile_get_register(char_u **arg, cctx_T *cctx)
1525{
1526 int ret;
1527
1528 ++*arg;
1529 if (**arg == NUL)
1530 {
1531 semsg(_(e_syntax_error_at_str), *arg - 1);
1532 return FAIL;
1533 }
1534 if (!valid_yank_reg(**arg, FALSE))
1535 {
1536 emsg_invreg(**arg);
1537 return FAIL;
1538 }
1539 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
1540 ++*arg;
1541 return ret;
1542}
1543
1544/*
1545 * Apply leading '!', '-' and '+' to constant "rettv".
1546 * When "numeric_only" is TRUE do not apply '!'.
1547 */
1548 static int
1549apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
1550{
1551 char_u *p = *end;
1552
1553 // this works from end to start
1554 while (p > start)
1555 {
1556 --p;
1557 if (*p == '-' || *p == '+')
1558 {
1559 // only '-' has an effect, for '+' we only check the type
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001560 if (rettv->v_type == VAR_FLOAT)
1561 {
1562 if (*p == '-')
1563 rettv->vval.v_float = -rettv->vval.v_float;
1564 }
1565 else
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001566 {
1567 varnumber_T val;
1568 int error = FALSE;
1569
1570 // tv_get_number_chk() accepts a string, but we don't want that
1571 // here
1572 if (check_not_string(rettv) == FAIL)
1573 return FAIL;
1574 val = tv_get_number_chk(rettv, &error);
1575 clear_tv(rettv);
1576 if (error)
1577 return FAIL;
1578 if (*p == '-')
1579 val = -val;
1580 rettv->v_type = VAR_NUMBER;
1581 rettv->vval.v_number = val;
1582 }
1583 }
1584 else if (numeric_only)
1585 {
1586 ++p;
1587 break;
1588 }
1589 else if (*p == '!')
1590 {
1591 int v = tv2bool(rettv);
1592
1593 // '!' is permissive in the type.
1594 clear_tv(rettv);
1595 rettv->v_type = VAR_BOOL;
1596 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
1597 }
1598 }
1599 *end = p;
1600 return OK;
1601}
1602
1603/*
1604 * Recognize v: variables that are constants and set "rettv".
1605 */
1606 static void
1607get_vim_constant(char_u **arg, typval_T *rettv)
1608{
1609 if (STRNCMP(*arg, "v:true", 6) == 0)
1610 {
1611 rettv->v_type = VAR_BOOL;
1612 rettv->vval.v_number = VVAL_TRUE;
1613 *arg += 6;
1614 }
1615 else if (STRNCMP(*arg, "v:false", 7) == 0)
1616 {
1617 rettv->v_type = VAR_BOOL;
1618 rettv->vval.v_number = VVAL_FALSE;
1619 *arg += 7;
1620 }
1621 else if (STRNCMP(*arg, "v:null", 6) == 0)
1622 {
1623 rettv->v_type = VAR_SPECIAL;
1624 rettv->vval.v_number = VVAL_NULL;
1625 *arg += 6;
1626 }
1627 else if (STRNCMP(*arg, "v:none", 6) == 0)
1628 {
1629 rettv->v_type = VAR_SPECIAL;
1630 rettv->vval.v_number = VVAL_NONE;
1631 *arg += 6;
1632 }
1633}
1634
1635 exprtype_T
1636get_compare_type(char_u *p, int *len, int *type_is)
1637{
1638 exprtype_T type = EXPR_UNKNOWN;
1639 int i;
1640
1641 switch (p[0])
1642 {
1643 case '=': if (p[1] == '=')
1644 type = EXPR_EQUAL;
1645 else if (p[1] == '~')
1646 type = EXPR_MATCH;
1647 break;
1648 case '!': if (p[1] == '=')
1649 type = EXPR_NEQUAL;
1650 else if (p[1] == '~')
1651 type = EXPR_NOMATCH;
1652 break;
1653 case '>': if (p[1] != '=')
1654 {
1655 type = EXPR_GREATER;
1656 *len = 1;
1657 }
1658 else
1659 type = EXPR_GEQUAL;
1660 break;
1661 case '<': if (p[1] != '=')
1662 {
1663 type = EXPR_SMALLER;
1664 *len = 1;
1665 }
1666 else
1667 type = EXPR_SEQUAL;
1668 break;
1669 case 'i': if (p[1] == 's')
1670 {
1671 // "is" and "isnot"; but not a prefix of a name
1672 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
1673 *len = 5;
1674 i = p[*len];
1675 if (!isalnum(i) && i != '_')
1676 {
1677 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
1678 *type_is = TRUE;
1679 }
1680 }
1681 break;
1682 }
1683 return type;
1684}
1685
1686/*
1687 * Skip over an expression, ignoring most errors.
1688 */
1689 void
1690skip_expr_cctx(char_u **arg, cctx_T *cctx)
1691{
1692 evalarg_T evalarg;
1693
1694 init_evalarg(&evalarg);
1695 evalarg.eval_cctx = cctx;
1696 skip_expr(arg, &evalarg);
1697 clear_evalarg(&evalarg, NULL);
1698}
1699
1700/*
1701 * Check that the top of the type stack has a type that can be used as a
1702 * condition. Give an error and return FAIL if not.
1703 */
1704 int
1705bool_on_stack(cctx_T *cctx)
1706{
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001707 type_T *type;
1708
Bram Moolenaar078a4612022-01-04 15:17:03 +00001709 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001710 if (type == &t_bool)
1711 return OK;
1712
Bram Moolenaar4913d422022-10-17 13:13:32 +01001713 if (type->tt_type == VAR_ANY
1714 || type->tt_type == VAR_UNKNOWN
1715 || type->tt_type == VAR_NUMBER
1716 || type == &t_number_bool
1717 || type == &t_const_number_bool)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001718 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
1719 // This requires a runtime type check.
1720 return generate_COND2BOOL(cctx);
1721
1722 return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE);
1723}
1724
1725/*
1726 * Give the "white on both sides" error, taking the operator from "p[len]".
1727 */
1728 void
1729error_white_both(char_u *op, int len)
1730{
1731 char_u buf[10];
1732
1733 vim_strncpy(buf, op, len);
1734 semsg(_(e_white_space_required_before_and_after_str_at_str), buf, op);
1735}
1736
1737/*
1738 * Compile code to apply '-', '+' and '!'.
1739 * When "numeric_only" is TRUE do not apply '!'.
1740 */
1741 static int
1742compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
1743{
1744 char_u *p = *end;
1745
1746 // this works from end to start
1747 while (p > start)
1748 {
1749 --p;
1750 while (VIM_ISWHITE(*p))
1751 --p;
1752 if (*p == '-' || *p == '+')
1753 {
1754 int negate = *p == '-';
1755 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001756 type_T *type;
1757
Bram Moolenaar078a4612022-01-04 15:17:03 +00001758 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001759 if (type != &t_float && need_type(type, &t_number,
1760 -1, 0, cctx, FALSE, FALSE) == FAIL)
1761 return FAIL;
1762
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001763 // only '-' has an effect, for '+' we only check the type
1764 if (negate)
1765 {
1766 isn = generate_instr(cctx, ISN_NEGATENR);
1767 if (isn == NULL)
1768 return FAIL;
1769 }
1770 }
1771 else if (numeric_only)
1772 {
1773 ++p;
1774 break;
1775 }
1776 else
1777 {
1778 int invert = *p == '!';
1779
1780 while (p > start && (p[-1] == '!' || VIM_ISWHITE(p[-1])))
1781 {
1782 if (p[-1] == '!')
1783 invert = !invert;
1784 --p;
1785 }
1786 if (generate_2BOOL(cctx, invert, -1) == FAIL)
1787 return FAIL;
1788 }
1789 }
1790 *end = p;
1791 return OK;
1792}
1793
1794/*
1795 * Compile "(expression)": recursive!
1796 * Return FAIL/OK.
1797 */
1798 static int
1799compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1800{
1801 int ret;
1802 char_u *p = *arg + 1;
1803
1804 if (may_get_next_line_error(p, arg, cctx) == FAIL)
1805 return FAIL;
1806 if (ppconst->pp_used <= PPSIZE - 10)
1807 {
1808 ret = compile_expr1(arg, cctx, ppconst);
1809 }
1810 else
1811 {
1812 // Not enough space in ppconst, flush constants.
1813 if (generate_ppconst(cctx, ppconst) == FAIL)
1814 return FAIL;
1815 ret = compile_expr0(arg, cctx);
1816 }
1817 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
1818 return FAIL;
1819 if (**arg == ')')
1820 ++*arg;
1821 else if (ret == OK)
1822 {
1823 emsg(_(e_missing_closing_paren));
1824 ret = FAIL;
1825 }
1826 return ret;
1827}
1828
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01001829static int compile_expr9(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
Bram Moolenaarc7349932022-01-16 20:59:39 +00001830
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001831/*
1832 * Compile whatever comes after "name" or "name()".
1833 * Advances "*arg" only when something was recognized.
1834 */
1835 static int
1836compile_subscript(
1837 char_u **arg,
1838 cctx_T *cctx,
1839 char_u *start_leader,
1840 char_u **end_leader,
1841 ppconst_T *ppconst)
1842{
1843 char_u *name_start = *end_leader;
1844 int keeping_dict = FALSE;
1845
1846 for (;;)
1847 {
1848 char_u *p = skipwhite(*arg);
Bram Moolenaarffdaca92022-12-09 21:41:48 +00001849 type_T *type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001850
1851 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
1852 {
1853 char_u *next = peek_next_line_from_context(cctx);
1854
Bram Moolenaard0fbb412022-10-19 18:04:49 +01001855 // If a following line starts with "->{", "->(" or "->X" advance to
1856 // that line, so that a line break before "->" is allowed.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001857 // Also if a following line starts with ".x".
1858 if (next != NULL &&
1859 ((next[0] == '-' && next[1] == '>'
1860 && (next[2] == '{'
Bram Moolenaard0fbb412022-10-19 18:04:49 +01001861 || next[2] == '('
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001862 || ASCII_ISALPHA(*skipwhite(next + 2))))
1863 || (next[0] == '.' && eval_isdictc(next[1]))))
1864 {
1865 next = next_line_from_context(cctx, TRUE);
1866 if (next == NULL)
1867 return FAIL;
1868 *arg = next;
1869 p = skipwhite(*arg);
1870 }
1871 }
1872
1873 // Do not skip over white space to find the "(", "execute 'x' (expr)"
1874 // is not a function call.
1875 if (**arg == '(')
1876 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001877 int argcount = 0;
1878
1879 if (generate_ppconst(cctx, ppconst) == FAIL)
1880 return FAIL;
1881 ppconst->pp_is_const = FALSE;
1882
1883 // funcref(arg)
Bram Moolenaar078a4612022-01-04 15:17:03 +00001884 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001885
1886 *arg = skipwhite(p + 1);
LemonBoyf3b48952022-05-05 13:53:03 +01001887 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001888 return FAIL;
1889 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
1890 return FAIL;
1891 if (keeping_dict)
1892 {
1893 keeping_dict = FALSE;
1894 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
1895 return FAIL;
1896 }
1897 }
1898 else if (*p == '-' && p[1] == '>')
1899 {
Bram Moolenaarc7349932022-01-16 20:59:39 +00001900 char_u *pstart = p;
1901 int alt;
1902 char_u *paren;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001903
Bram Moolenaarc7349932022-01-16 20:59:39 +00001904 // something->method()
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001905 if (generate_ppconst(cctx, ppconst) == FAIL)
1906 return FAIL;
1907 ppconst->pp_is_const = FALSE;
1908
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001909 // Apply the '!', '-' and '+' first:
1910 // -1.0->func() works like (-1.0)->func()
1911 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
1912 return FAIL;
1913
1914 p += 2;
1915 *arg = skipwhite(p);
1916 // No line break supported right after "->".
Bram Moolenaarc7349932022-01-16 20:59:39 +00001917
1918 // Three alternatives handled here:
1919 // 1. "base->name(" only a name, use compile_call()
1920 // 2. "base->(expr)(" evaluate "expr", then use PCALL
1921 // 3. "base->expr(" Same, find the end of "expr" by "("
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001922 if (**arg == '(')
Bram Moolenaarc7349932022-01-16 20:59:39 +00001923 alt = 2;
1924 else
1925 {
1926 // alternative 1 or 3
1927 p = *arg;
1928 if (!eval_isnamec1(*p))
1929 {
1930 semsg(_(e_trailing_characters_str), pstart);
1931 return FAIL;
1932 }
1933 if (ASCII_ISALPHA(*p) && p[1] == ':')
1934 p += 2;
1935 for ( ; eval_isnamec(*p); ++p)
1936 ;
1937 if (*p == '(')
1938 {
1939 // alternative 1
1940 alt = 1;
1941 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
1942 return FAIL;
1943 }
1944 else
1945 {
1946 // Must be alternative 3, find the "(". Only works within
1947 // one line.
1948 alt = 3;
1949 paren = vim_strchr(p, '(');
1950 if (paren == NULL)
1951 {
1952 semsg(_(e_missing_parenthesis_str), *arg);
1953 return FAIL;
1954 }
1955 }
1956 }
1957
1958 if (alt != 1)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001959 {
1960 int argcount = 1;
1961 garray_T *stack = &cctx->ctx_type_stack;
1962 int type_idx_start = stack->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001963 int expr_isn_start = cctx->ctx_instr.ga_len;
1964 int expr_isn_end;
1965 int arg_isn_count;
1966
Bram Moolenaarc7349932022-01-16 20:59:39 +00001967 if (alt == 2)
1968 {
1969 // Funcref call: list->(Refs[2])(arg)
1970 // or lambda: list->((arg) => expr)(arg)
1971 //
1972 // Fist compile the function expression.
1973 if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
1974 return FAIL;
1975 }
1976 else
1977 {
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001978 int fail;
1979 int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
Bram Moolenaar31ad32a2022-05-13 16:23:37 +01001980 int prev_did_emsg = did_emsg;
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001981
Bram Moolenaarc7349932022-01-16 20:59:39 +00001982 *paren = NUL;
Bram Moolenaard02dce22022-01-18 17:43:04 +00001983
1984 // instead of using LOADG for "import.Func" use PUSHFUNC
1985 ++paren_follows_after_expr;
1986
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001987 // do not look in the next line
1988 cctx->ctx_ufunc->uf_lines.ga_len = 1;
Bram Moolenaard02dce22022-01-18 17:43:04 +00001989
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01001990 fail = compile_expr9(arg, cctx, ppconst) == FAIL
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001991 || *skipwhite(*arg) != NUL;
1992 *paren = '(';
Bram Moolenaard02dce22022-01-18 17:43:04 +00001993 --paren_follows_after_expr;
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001994 cctx->ctx_ufunc->uf_lines.ga_len = save_len;
Bram Moolenaard02dce22022-01-18 17:43:04 +00001995
Bram Moolenaar6389baa2022-01-17 20:50:40 +00001996 if (fail)
Bram Moolenaarc7349932022-01-16 20:59:39 +00001997 {
Bram Moolenaar31ad32a2022-05-13 16:23:37 +01001998 if (did_emsg == prev_did_emsg)
1999 semsg(_(e_invalid_expression_str), pstart);
Bram Moolenaarc7349932022-01-16 20:59:39 +00002000 return FAIL;
2001 }
Bram Moolenaarc7349932022-01-16 20:59:39 +00002002 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002003
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002004 // Compile the arguments.
2005 if (**arg != '(')
2006 {
2007 if (*skipwhite(*arg) == '(')
Bram Moolenaar3a846e62022-01-01 16:21:00 +00002008 emsg(_(e_no_white_space_allowed_before_parenthesis));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002009 else
2010 semsg(_(e_missing_parenthesis_str), *arg);
2011 return FAIL;
2012 }
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002013
2014 // Remember the next instruction index, where the instructions
2015 // for arguments are being written.
2016 expr_isn_end = cctx->ctx_instr.ga_len;
2017
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002018 *arg = skipwhite(*arg + 1);
LemonBoyf3b48952022-05-05 13:53:03 +01002019 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL)
2020 == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002021 return FAIL;
2022
2023 // Move the instructions for the arguments to before the
2024 // instructions of the expression and move the type of the
2025 // expression after the argument types. This is what ISN_PCALL
2026 // expects.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002027 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
2028 if (arg_isn_count > 0)
2029 {
2030 int expr_isn_count = expr_isn_end - expr_isn_start;
2031 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count);
Bram Moolenaar078a4612022-01-04 15:17:03 +00002032 type_T *decl_type;
2033 type2_T *typep;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002034
2035 if (isn == NULL)
2036 return FAIL;
2037 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
2038 + expr_isn_start,
2039 sizeof(isn_T) * expr_isn_count);
2040 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
2041 + expr_isn_start,
2042 ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end,
2043 sizeof(isn_T) * arg_isn_count);
2044 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
2045 + expr_isn_start + arg_isn_count,
2046 isn, sizeof(isn_T) * expr_isn_count);
2047 vim_free(isn);
2048
Bram Moolenaar078a4612022-01-04 15:17:03 +00002049 typep = ((type2_T *)stack->ga_data) + type_idx_start;
2050 type = typep->type_curr;
2051 decl_type = typep->type_decl;
2052 mch_memmove(((type2_T *)stack->ga_data) + type_idx_start,
2053 ((type2_T *)stack->ga_data) + type_idx_start + 1,
2054 sizeof(type2_T)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002055 * (stack->ga_len - type_idx_start - 1));
Bram Moolenaar078a4612022-01-04 15:17:03 +00002056 typep = ((type2_T *)stack->ga_data) + stack->ga_len - 1;
2057 typep->type_curr = type;
2058 typep->type_decl = decl_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002059 }
2060
Bram Moolenaar078a4612022-01-04 15:17:03 +00002061 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002062 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
2063 return FAIL;
2064 }
Bram Moolenaarc7349932022-01-16 20:59:39 +00002065
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002066 if (keeping_dict)
2067 {
2068 keeping_dict = FALSE;
2069 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
2070 return FAIL;
2071 }
2072 }
2073 else if (**arg == '[')
2074 {
2075 int is_slice = FALSE;
2076
2077 // list index: list[123]
2078 // dict member: dict[key]
2079 // string index: text[123]
2080 // blob index: blob[123]
2081 if (generate_ppconst(cctx, ppconst) == FAIL)
2082 return FAIL;
2083 ppconst->pp_is_const = FALSE;
2084
2085 ++p;
2086 if (may_get_next_line_error(p, arg, cctx) == FAIL)
2087 return FAIL;
2088 if (**arg == ':')
2089 {
2090 // missing first index is equal to zero
2091 generate_PUSHNR(cctx, 0);
2092 }
2093 else
2094 {
2095 if (compile_expr0(arg, cctx) == FAIL)
2096 return FAIL;
2097 if (**arg == ':')
2098 {
2099 semsg(_(e_white_space_required_before_and_after_str_at_str),
2100 ":", *arg);
2101 return FAIL;
2102 }
2103 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2104 return FAIL;
2105 *arg = skipwhite(*arg);
2106 }
2107 if (**arg == ':')
2108 {
2109 is_slice = TRUE;
2110 ++*arg;
2111 if (!IS_WHITE_OR_NUL(**arg) && **arg != ']')
2112 {
2113 semsg(_(e_white_space_required_before_and_after_str_at_str),
2114 ":", *arg);
2115 return FAIL;
2116 }
2117 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2118 return FAIL;
2119 if (**arg == ']')
2120 // missing second index is equal to end of string
2121 generate_PUSHNR(cctx, -1);
2122 else
2123 {
2124 if (compile_expr0(arg, cctx) == FAIL)
2125 return FAIL;
2126 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2127 return FAIL;
2128 *arg = skipwhite(*arg);
2129 }
2130 }
2131
2132 if (**arg != ']')
2133 {
2134 emsg(_(e_missing_closing_square_brace));
2135 return FAIL;
2136 }
2137 *arg = *arg + 1;
2138
2139 if (keeping_dict)
2140 {
2141 keeping_dict = FALSE;
2142 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
2143 return FAIL;
2144 }
2145 if (compile_member(is_slice, &keeping_dict, cctx) == FAIL)
2146 return FAIL;
2147 }
Bram Moolenaarffdaca92022-12-09 21:41:48 +00002148 else if (*p == '.'
2149 && (type = get_type_on_stack(cctx, 0)) != &t_unknown
2150 && (type->tt_type == VAR_CLASS || type->tt_type == VAR_OBJECT))
2151 {
2152 // class member: SomeClass.varname
2153 // class method: SomeClass.SomeMethod()
2154 // class constructor: SomeClass.new()
2155 // object member: someObject.varname, this.varname
2156 // object method: someObject.SomeMethod(), this.SomeMethod()
2157 if (compile_class_object_index(cctx, arg, type) == FAIL)
2158 return FAIL;
2159 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002160 else if (*p == '.' && p[1] != '.')
2161 {
2162 // dictionary member: dict.name
2163 if (generate_ppconst(cctx, ppconst) == FAIL)
2164 return FAIL;
2165 ppconst->pp_is_const = FALSE;
2166
2167 *arg = p + 1;
2168 if (IS_WHITE_OR_NUL(**arg))
2169 {
2170 emsg(_(e_missing_name_after_dot));
2171 return FAIL;
2172 }
2173 p = *arg;
2174 if (eval_isdictc(*p))
2175 while (eval_isnamec(*p))
2176 MB_PTR_ADV(p);
2177 if (p == *arg)
2178 {
2179 semsg(_(e_syntax_error_at_str), *arg);
2180 return FAIL;
2181 }
2182 if (keeping_dict && generate_instr(cctx, ISN_CLEARDICT) == NULL)
2183 return FAIL;
2184 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
2185 return FAIL;
2186 keeping_dict = TRUE;
2187 *arg = p;
2188 }
2189 else
2190 break;
2191 }
2192
2193 // Turn "dict.Func" into a partial for "Func" bound to "dict".
2194 // This needs to be done at runtime to be able to check the type.
Bram Moolenaar1ff9c442022-05-17 15:03:33 +01002195 if (keeping_dict && cctx->ctx_skip != SKIP_YES
2196 && generate_instr(cctx, ISN_USEDICT) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002197 return FAIL;
2198
2199 return OK;
2200}
2201
2202/*
2203 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
2204 * "arg" is advanced until after the expression, skipping white space.
2205 *
2206 * If the value is a constant "ppconst->pp_used" will be non-zero.
2207 * Before instructions are generated, any values in "ppconst" will generated.
2208 *
2209 * This is the compiling equivalent of eval1(), eval2(), etc.
2210 */
2211
2212/*
2213 * number number constant
2214 * 0zFFFFFFFF Blob constant
2215 * "string" string constant
2216 * 'string' literal string constant
2217 * &option-name option value
2218 * @r register contents
2219 * identifier variable value
2220 * function() function call
2221 * $VAR environment variable
2222 * (expression) nested expression
2223 * [expr, expr] List
2224 * {key: val, [key]: val} Dictionary
2225 *
2226 * Also handle:
2227 * ! in front logical NOT
2228 * - in front unary minus
2229 * + in front unary plus (ignored)
2230 * trailing (arg) funcref/partial call
2231 * trailing [] subscript in String or List
2232 * trailing .name entry in Dictionary
2233 * trailing ->name() method call
2234 */
2235 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002236compile_expr9(
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002237 char_u **arg,
2238 cctx_T *cctx,
2239 ppconst_T *ppconst)
2240{
2241 char_u *start_leader, *end_leader;
2242 int ret = OK;
2243 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
2244 int used_before = ppconst->pp_used;
2245
2246 ppconst->pp_is_const = FALSE;
2247
2248 /*
2249 * Skip '!', '-' and '+' characters. They are handled later.
2250 */
2251 start_leader = *arg;
2252 if (eval_leader(arg, TRUE) == FAIL)
2253 return FAIL;
2254 end_leader = *arg;
2255
2256 rettv->v_type = VAR_UNKNOWN;
2257 switch (**arg)
2258 {
2259 /*
2260 * Number constant.
2261 */
2262 case '0': // also for blob starting with 0z
2263 case '1':
2264 case '2':
2265 case '3':
2266 case '4':
2267 case '5':
2268 case '6':
2269 case '7':
2270 case '8':
2271 case '9':
2272 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
2273 return FAIL;
2274 // Apply "-" and "+" just before the number now, right to
2275 // left. Matters especially when "->" follows. Stops at
2276 // '!'.
2277 if (apply_leader(rettv, TRUE,
2278 start_leader, &end_leader) == FAIL)
2279 {
2280 clear_tv(rettv);
2281 return FAIL;
2282 }
2283 break;
2284
2285 /*
2286 * String constant: "string".
2287 */
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002288 case '"': if (eval_string(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002289 return FAIL;
2290 break;
2291
2292 /*
2293 * Literal string constant: 'str''ing'.
2294 */
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002295 case '\'': if (eval_lit_string(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002296 return FAIL;
2297 break;
2298
2299 /*
2300 * Constant Vim variable.
2301 */
2302 case 'v': get_vim_constant(arg, rettv);
2303 ret = NOTDONE;
2304 break;
2305
2306 /*
2307 * "true" constant
2308 */
2309 case 't': if (STRNCMP(*arg, "true", 4) == 0
2310 && !eval_isnamec((*arg)[4]))
2311 {
2312 *arg += 4;
2313 rettv->v_type = VAR_BOOL;
2314 rettv->vval.v_number = VVAL_TRUE;
2315 }
2316 else
2317 ret = NOTDONE;
2318 break;
2319
2320 /*
2321 * "false" constant
2322 */
2323 case 'f': if (STRNCMP(*arg, "false", 5) == 0
2324 && !eval_isnamec((*arg)[5]))
2325 {
2326 *arg += 5;
2327 rettv->v_type = VAR_BOOL;
2328 rettv->vval.v_number = VVAL_FALSE;
2329 }
2330 else
2331 ret = NOTDONE;
2332 break;
2333
2334 /*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00002335 * "null" or "null_*" constant
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002336 */
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00002337 case 'n': if (STRNCMP(*arg, "null", 4) == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002338 {
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00002339 char_u *p = *arg + 4;
2340 int len;
2341
2342 for (len = 0; eval_isnamec(p[len]); ++len)
2343 ;
2344 ret = handle_predefined(*arg, len + 4, rettv);
2345 if (ret == FAIL)
2346 ret = NOTDONE;
2347 else
2348 *arg += len + 4;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002349 }
2350 else
2351 ret = NOTDONE;
2352 break;
2353
2354 /*
2355 * List: [expr, expr]
2356 */
2357 case '[': if (generate_ppconst(cctx, ppconst) == FAIL)
2358 return FAIL;
2359 ret = compile_list(arg, cctx, ppconst);
2360 break;
2361
2362 /*
2363 * Dictionary: {'key': val, 'key': val}
2364 */
2365 case '{': if (generate_ppconst(cctx, ppconst) == FAIL)
2366 return FAIL;
2367 ret = compile_dict(arg, cctx, ppconst);
2368 break;
2369
2370 /*
2371 * Option value: &name
2372 */
2373 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
2374 return FAIL;
2375 ret = compile_get_option(arg, cctx);
2376 break;
2377
2378 /*
2379 * Environment variable: $VAR.
LemonBoy2eaef102022-05-06 13:14:50 +01002380 * Interpolated string: $"string" or $'string'.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002381 */
2382 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
2383 return FAIL;
LemonBoy2eaef102022-05-06 13:14:50 +01002384 if ((*arg)[1] == '"' || (*arg)[1] == '\'')
2385 ret = compile_interp_string(arg, cctx);
2386 else
2387 ret = compile_get_env(arg, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002388 break;
2389
2390 /*
2391 * Register contents: @r.
2392 */
2393 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
2394 return FAIL;
2395 ret = compile_get_register(arg, cctx);
2396 break;
2397 /*
2398 * nested expression: (expression).
2399 * lambda: (arg, arg) => expr
2400 * funcref: (arg, arg) => { statement }
2401 */
2402 case '(': // if compile_lambda returns NOTDONE then it must be (expr)
2403 ret = compile_lambda(arg, cctx);
2404 if (ret == NOTDONE)
2405 ret = compile_parenthesis(arg, cctx, ppconst);
2406 break;
2407
2408 default: ret = NOTDONE;
2409 break;
2410 }
2411 if (ret == FAIL)
2412 return FAIL;
2413
2414 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
2415 {
2416 if (cctx->ctx_skip == SKIP_YES)
2417 clear_tv(rettv);
2418 else
2419 // A constant expression can possibly be handled compile time,
2420 // return the value instead of generating code.
2421 ++ppconst->pp_used;
2422 }
2423 else if (ret == NOTDONE)
2424 {
2425 char_u *p;
2426 int r;
2427
2428 if (!eval_isnamec1(**arg))
2429 {
2430 if (!vim9_bad_comment(*arg))
2431 {
2432 if (ends_excmd(*skipwhite(*arg)))
2433 semsg(_(e_empty_expression_str), *arg);
2434 else
2435 semsg(_(e_name_expected_str), *arg);
2436 }
2437 return FAIL;
2438 }
2439
2440 // "name" or "name()"
2441 p = to_name_end(*arg, TRUE);
2442 if (p - *arg == (size_t)1 && **arg == '_')
2443 {
2444 emsg(_(e_cannot_use_underscore_here));
2445 return FAIL;
2446 }
2447
2448 if (*p == '(')
2449 {
2450 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
2451 }
2452 else
2453 {
2454 if (cctx->ctx_skip != SKIP_YES
2455 && generate_ppconst(cctx, ppconst) == FAIL)
2456 return FAIL;
2457 r = compile_load(arg, p, cctx, TRUE, TRUE);
2458 }
2459 if (r == FAIL)
2460 return FAIL;
2461 }
2462
2463 // Handle following "[]", ".member", etc.
2464 // Then deal with prefixed '-', '+' and '!', if not done already.
2465 if (compile_subscript(arg, cctx, start_leader, &end_leader,
2466 ppconst) == FAIL)
2467 return FAIL;
2468 if (ppconst->pp_used > 0)
2469 {
2470 // apply the '!', '-' and '+' before the constant
2471 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
2472 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
2473 return FAIL;
2474 return OK;
2475 }
2476 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
2477 return FAIL;
2478 return OK;
2479}
2480
2481/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002482 * <type>expr9: runtime type check / conversion
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002483 */
2484 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002485compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002486{
2487 type_T *want_type = NULL;
2488
2489 // Recognize <type>
2490 if (**arg == '<' && eval_isnamec1((*arg)[1]))
2491 {
2492 ++*arg;
2493 want_type = parse_type(arg, cctx->ctx_type_list, TRUE);
2494 if (want_type == NULL)
2495 return FAIL;
2496
2497 if (**arg != '>')
2498 {
2499 if (*skipwhite(*arg) == '>')
2500 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
2501 else
2502 emsg(_(e_missing_gt));
2503 return FAIL;
2504 }
2505 ++*arg;
2506 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2507 return FAIL;
2508 }
2509
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002510 if (compile_expr9(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002511 return FAIL;
2512
2513 if (want_type != NULL)
2514 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002515 type_T *actual;
2516 where_T where = WHERE_INIT;
2517
2518 generate_ppconst(cctx, ppconst);
Bram Moolenaar078a4612022-01-04 15:17:03 +00002519 actual = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +00002520 if (check_type_maybe(want_type, actual, FALSE, where) != OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002521 {
Bram Moolenaar59618fe2021-12-21 12:32:17 +00002522 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE)
2523 == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002524 return FAIL;
2525 }
2526 }
2527
2528 return OK;
2529}
2530
2531/*
2532 * * number multiplication
2533 * / number division
2534 * % number modulo
2535 */
2536 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002537compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002538{
2539 char_u *op;
2540 char_u *next;
2541 int ppconst_used = ppconst->pp_used;
2542
2543 // get the first expression
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002544 if (compile_expr8(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002545 return FAIL;
2546
2547 /*
2548 * Repeat computing, until no "*", "/" or "%" is following.
2549 */
2550 for (;;)
2551 {
2552 op = may_peek_next_line(cctx, *arg, &next);
2553 if (*op != '*' && *op != '/' && *op != '%')
2554 break;
2555 if (next != NULL)
2556 {
2557 *arg = next_line_from_context(cctx, TRUE);
2558 op = skipwhite(*arg);
2559 }
2560
2561 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
2562 {
2563 error_white_both(op, 1);
2564 return FAIL;
2565 }
2566 if (may_get_next_line_error(op + 1, arg, cctx) == FAIL)
2567 return FAIL;
2568
2569 // get the second expression
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002570 if (compile_expr8(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002571 return FAIL;
2572
2573 if (ppconst->pp_used == ppconst_used + 2
2574 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
2575 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
2576 {
2577 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
2578 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
2579 varnumber_T res = 0;
2580 int failed = FALSE;
2581
2582 // both are numbers: compute the result
2583 switch (*op)
2584 {
2585 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
2586 break;
2587 case '/': res = num_divide(tv1->vval.v_number,
2588 tv2->vval.v_number, &failed);
2589 break;
2590 case '%': res = num_modulus(tv1->vval.v_number,
2591 tv2->vval.v_number, &failed);
2592 break;
2593 }
2594 if (failed)
2595 return FAIL;
2596 tv1->vval.v_number = res;
2597 --ppconst->pp_used;
2598 }
2599 else
2600 {
2601 generate_ppconst(cctx, ppconst);
2602 generate_two_op(cctx, op);
2603 }
2604 }
2605
2606 return OK;
2607}
2608
2609/*
2610 * + number addition or list/blobl concatenation
2611 * - number subtraction
2612 * .. string concatenation
2613 */
2614 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002615compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002616{
2617 char_u *op;
2618 char_u *next;
2619 int oplen;
2620 int ppconst_used = ppconst->pp_used;
2621
2622 // get the first variable
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002623 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002624 return FAIL;
2625
2626 /*
2627 * Repeat computing, until no "+", "-" or ".." is following.
2628 */
2629 for (;;)
2630 {
2631 op = may_peek_next_line(cctx, *arg, &next);
2632 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
2633 break;
2634 if (op[0] == op[1] && *op != '.' && next)
2635 // Finding "++" or "--" on the next line is a separate command.
2636 // But ".." is concatenation.
2637 break;
2638 oplen = (*op == '.' ? 2 : 1);
2639 if (next != NULL)
2640 {
2641 *arg = next_line_from_context(cctx, TRUE);
2642 op = skipwhite(*arg);
2643 }
2644
2645 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
2646 {
2647 error_white_both(op, oplen);
2648 return FAIL;
2649 }
2650
2651 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL)
2652 return FAIL;
2653
2654 // get the second expression
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002655 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002656 return FAIL;
2657
2658 if (ppconst->pp_used == ppconst_used + 2
2659 && (*op == '.'
2660 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
2661 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
2662 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
2663 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
2664 {
2665 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
2666 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
2667
2668 // concat/subtract/add constant numbers
2669 if (*op == '+')
2670 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
2671 else if (*op == '-')
2672 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
2673 else
2674 {
2675 // concatenate constant strings
2676 char_u *s1 = tv1->vval.v_string;
2677 char_u *s2 = tv2->vval.v_string;
2678 size_t len1 = STRLEN(s1);
2679
2680 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
2681 if (tv1->vval.v_string == NULL)
2682 {
2683 clear_ppconst(ppconst);
2684 return FAIL;
2685 }
2686 mch_memmove(tv1->vval.v_string, s1, len1);
2687 STRCPY(tv1->vval.v_string + len1, s2);
2688 vim_free(s1);
2689 vim_free(s2);
2690 }
2691 --ppconst->pp_used;
2692 }
2693 else
2694 {
2695 generate_ppconst(cctx, ppconst);
2696 ppconst->pp_is_const = FALSE;
2697 if (*op == '.')
2698 {
2699 if (may_generate_2STRING(-2, FALSE, cctx) == FAIL
2700 || may_generate_2STRING(-1, FALSE, cctx) == FAIL)
2701 return FAIL;
LemonBoy372bcce2022-04-25 12:43:20 +01002702 if (generate_CONCAT(cctx, 2) == FAIL)
2703 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002704 }
2705 else
2706 generate_two_op(cctx, op);
2707 }
2708 }
2709
2710 return OK;
2711}
2712
2713/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002714 * expr6a >> expr6b
2715 * expr6a << expr6b
2716 *
2717 * Produces instructions:
2718 * OPNR bitwise left or right shift
2719 */
2720 static int
2721compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2722{
2723 exprtype_T type = EXPR_UNKNOWN;
2724 char_u *p;
2725 char_u *next;
2726 int len = 2;
2727 int ppconst_used = ppconst->pp_used;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002728 isn_T *isn;
2729
2730 // get the first variable
2731 if (compile_expr6(arg, cctx, ppconst) == FAIL)
2732 return FAIL;
2733
2734 /*
2735 * Repeat computing, until no "+", "-" or ".." is following.
2736 */
2737 for (;;)
2738 {
2739 type = EXPR_UNKNOWN;
2740
2741 p = may_peek_next_line(cctx, *arg, &next);
2742 if (p[0] == '<' && p[1] == '<')
2743 type = EXPR_LSHIFT;
2744 else if (p[0] == '>' && p[1] == '>')
2745 type = EXPR_RSHIFT;
2746
2747 if (type == EXPR_UNKNOWN)
2748 return OK;
2749
2750 // Handle a bitwise left or right shift operator
2751 if (ppconst->pp_used == ppconst_used + 1)
2752 {
Bram Moolenaar5b529232022-05-22 21:53:26 +01002753 if (ppconst->pp_tv[ppconst->pp_used - 1].v_type != VAR_NUMBER)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002754 {
2755 // left operand should be a number
2756 emsg(_(e_bitshift_ops_must_be_number));
2757 return FAIL;
2758 }
2759 }
2760 else
2761 {
2762 type_T *t = get_type_on_stack(cctx, 0);
2763
2764 if (need_type(t, &t_number, 0, 0, cctx, FALSE, FALSE) == FAIL)
2765 {
2766 emsg(_(e_bitshift_ops_must_be_number));
2767 return FAIL;
2768 }
2769 }
2770
2771 if (next != NULL)
2772 {
2773 *arg = next_line_from_context(cctx, TRUE);
2774 p = skipwhite(*arg);
2775 }
2776
2777 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
2778 {
2779 error_white_both(p, len);
2780 return FAIL;
2781 }
2782
2783 // get the second variable
2784 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
2785 return FAIL;
2786
2787 if (compile_expr6(arg, cctx, ppconst) == FAIL)
2788 return FAIL;
2789
2790 if (ppconst->pp_used == ppconst_used + 2)
2791 {
Bram Moolenaar5b529232022-05-22 21:53:26 +01002792 typval_T *tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
2793 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
2794
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002795 // Both sides are a constant, compute the result now.
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002796 if (tv2->v_type != VAR_NUMBER || tv2->vval.v_number < 0)
2797 {
2798 // right operand should be a positive number
2799 if (tv2->v_type != VAR_NUMBER)
2800 emsg(_(e_bitshift_ops_must_be_number));
2801 else
dundargocc57b5bc2022-11-02 13:30:51 +00002802 emsg(_(e_bitshift_ops_must_be_positive));
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002803 return FAIL;
2804 }
2805
2806 if (tv2->vval.v_number > MAX_LSHIFT_BITS)
2807 tv1->vval.v_number = 0;
2808 else if (type == EXPR_LSHIFT)
Bram Moolenaar68e64d22022-05-22 22:07:52 +01002809 tv1->vval.v_number =
2810 (uvarnumber_T)tv1->vval.v_number << tv2->vval.v_number;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002811 else
Bram Moolenaar338bf582022-05-22 20:16:32 +01002812 tv1->vval.v_number =
2813 (uvarnumber_T)tv1->vval.v_number >> tv2->vval.v_number;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002814 clear_tv(tv2);
2815 --ppconst->pp_used;
2816 }
2817 else
2818 {
2819 if (need_type(get_type_on_stack(cctx, 0), &t_number, 0, 0, cctx,
2820 FALSE, FALSE) == FAIL)
2821 {
2822 emsg(_(e_bitshift_ops_must_be_number));
2823 return FAIL;
2824 }
2825
2826 generate_ppconst(cctx, ppconst);
2827
2828 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
2829 if (isn == NULL)
2830 return FAIL;
2831
2832 if (isn != NULL)
2833 isn->isn_arg.op.op_type = type;
2834 }
2835 }
2836
2837 return OK;
2838}
2839
2840/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002841 * expr5a == expr5b
2842 * expr5a =~ expr5b
2843 * expr5a != expr5b
2844 * expr5a !~ expr5b
2845 * expr5a > expr5b
2846 * expr5a >= expr5b
2847 * expr5a < expr5b
2848 * expr5a <= expr5b
2849 * expr5a is expr5b
2850 * expr5a isnot expr5b
2851 *
2852 * Produces instructions:
2853 * EVAL expr5a Push result of "expr5a"
2854 * EVAL expr5b Push result of "expr5b"
2855 * COMPARE one of the compare instructions
2856 */
2857 static int
2858compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2859{
2860 exprtype_T type = EXPR_UNKNOWN;
2861 char_u *p;
2862 char_u *next;
2863 int len = 2;
2864 int type_is = FALSE;
2865 int ppconst_used = ppconst->pp_used;
2866
2867 // get the first variable
2868 if (compile_expr5(arg, cctx, ppconst) == FAIL)
2869 return FAIL;
2870
2871 p = may_peek_next_line(cctx, *arg, &next);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002872
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002873 type = get_compare_type(p, &len, &type_is);
2874
2875 /*
2876 * If there is a comparative operator, use it.
2877 */
2878 if (type != EXPR_UNKNOWN)
2879 {
2880 int ic = FALSE; // Default: do not ignore case
2881
2882 if (next != NULL)
2883 {
2884 *arg = next_line_from_context(cctx, TRUE);
2885 p = skipwhite(*arg);
2886 }
2887 if (type_is && (p[len] == '?' || p[len] == '#'))
2888 {
2889 semsg(_(e_invalid_expression_str), *arg);
2890 return FAIL;
2891 }
2892 // extra question mark appended: ignore case
2893 if (p[len] == '?')
2894 {
2895 ic = TRUE;
2896 ++len;
2897 }
2898 // extra '#' appended: match case (ignored)
2899 else if (p[len] == '#')
2900 ++len;
2901 // nothing appended: match case
2902
2903 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
2904 {
2905 error_white_both(p, len);
2906 return FAIL;
2907 }
2908
2909 // get the second variable
2910 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
2911 return FAIL;
2912
2913 if (compile_expr5(arg, cctx, ppconst) == FAIL)
2914 return FAIL;
2915
2916 if (ppconst->pp_used == ppconst_used + 2)
2917 {
Bram Moolenaar5b529232022-05-22 21:53:26 +01002918 typval_T *tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002919 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
2920 int ret;
2921
2922 // Both sides are a constant, compute the result now.
2923 // First check for a valid combination of types, this is more
2924 // strict than typval_compare().
2925 if (check_compare_types(type, tv1, tv2) == FAIL)
2926 ret = FAIL;
2927 else
2928 {
2929 ret = typval_compare(tv1, tv2, type, ic);
2930 tv1->v_type = VAR_BOOL;
2931 tv1->vval.v_number = tv1->vval.v_number
2932 ? VVAL_TRUE : VVAL_FALSE;
2933 clear_tv(tv2);
2934 --ppconst->pp_used;
2935 }
2936 return ret;
2937 }
2938
2939 generate_ppconst(cctx, ppconst);
2940 return generate_COMPARE(cctx, type, ic);
2941 }
2942
2943 return OK;
2944}
2945
2946static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2947
2948/*
2949 * Compile || or &&.
2950 */
2951 static int
2952compile_and_or(
2953 char_u **arg,
2954 cctx_T *cctx,
2955 char *op,
2956 ppconst_T *ppconst,
2957 int ppconst_used UNUSED)
2958{
2959 char_u *next;
2960 char_u *p = may_peek_next_line(cctx, *arg, &next);
2961 int opchar = *op;
2962
2963 if (p[0] == opchar && p[1] == opchar)
2964 {
2965 garray_T *instr = &cctx->ctx_instr;
2966 garray_T end_ga;
2967 int save_skip = cctx->ctx_skip;
2968
2969 /*
2970 * Repeat until there is no following "||" or "&&"
2971 */
2972 ga_init2(&end_ga, sizeof(int), 10);
2973 while (p[0] == opchar && p[1] == opchar)
2974 {
2975 long start_lnum = SOURCING_LNUM;
2976 long save_sourcing_lnum;
2977 int start_ctx_lnum = cctx->ctx_lnum;
2978 int save_lnum;
2979 int const_used;
2980 int status;
2981 jumpwhen_T jump_when = opchar == '|'
2982 ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE;
2983
2984 if (next != NULL)
2985 {
2986 *arg = next_line_from_context(cctx, TRUE);
2987 p = skipwhite(*arg);
2988 }
2989
2990 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
2991 {
2992 semsg(_(e_white_space_required_before_and_after_str_at_str),
2993 op, p);
2994 ga_clear(&end_ga);
2995 return FAIL;
2996 }
2997
2998 save_sourcing_lnum = SOURCING_LNUM;
2999 SOURCING_LNUM = start_lnum;
3000 save_lnum = cctx->ctx_lnum;
3001 cctx->ctx_lnum = start_ctx_lnum;
3002
3003 status = check_ppconst_bool(ppconst);
3004 if (status != FAIL)
3005 {
3006 // Use the last ppconst if possible.
3007 if (ppconst->pp_used > 0)
3008 {
3009 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
3010 int is_true = tv2bool(tv);
3011
3012 if ((is_true && opchar == '|')
3013 || (!is_true && opchar == '&'))
3014 {
3015 // For "false && expr" and "true || expr" the "expr"
3016 // does not need to be evaluated.
3017 cctx->ctx_skip = SKIP_YES;
3018 clear_tv(tv);
3019 tv->v_type = VAR_BOOL;
3020 tv->vval.v_number = is_true ? VVAL_TRUE : VVAL_FALSE;
3021 }
3022 else
3023 {
3024 // For "true && expr" and "false || expr" only "expr"
3025 // needs to be evaluated.
3026 --ppconst->pp_used;
3027 jump_when = JUMP_NEVER;
3028 }
3029 }
3030 else
3031 {
3032 // Every part must evaluate to a bool.
3033 status = bool_on_stack(cctx);
3034 }
3035 }
3036 if (status != FAIL)
3037 status = ga_grow(&end_ga, 1);
3038 cctx->ctx_lnum = save_lnum;
3039 if (status == FAIL)
3040 {
3041 ga_clear(&end_ga);
3042 return FAIL;
3043 }
3044
3045 if (jump_when != JUMP_NEVER)
3046 {
3047 if (cctx->ctx_skip != SKIP_YES)
3048 {
3049 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3050 ++end_ga.ga_len;
3051 }
3052 generate_JUMP(cctx, jump_when, 0);
3053 }
3054
3055 // eval the next expression
3056 SOURCING_LNUM = save_sourcing_lnum;
3057 if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
3058 {
3059 ga_clear(&end_ga);
3060 return FAIL;
3061 }
3062
3063 const_used = ppconst->pp_used;
3064 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
3065 : compile_expr4(arg, cctx, ppconst)) == FAIL)
3066 {
3067 ga_clear(&end_ga);
3068 return FAIL;
3069 }
3070
3071 // "0 || 1" results in true, "1 && 0" results in false.
3072 if (ppconst->pp_used == const_used + 1)
3073 {
3074 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
3075
3076 if (tv->v_type == VAR_NUMBER
3077 && (tv->vval.v_number == 1 || tv->vval.v_number == 0))
3078 {
3079 tv->vval.v_number = tv->vval.v_number == 1
3080 ? VVAL_TRUE : VVAL_FALSE;
3081 tv->v_type = VAR_BOOL;
3082 }
3083 }
3084
3085 p = may_peek_next_line(cctx, *arg, &next);
3086 }
3087
3088 if (check_ppconst_bool(ppconst) == FAIL)
3089 {
3090 ga_clear(&end_ga);
3091 return FAIL;
3092 }
3093
3094 if (cctx->ctx_skip != SKIP_YES && ppconst->pp_used == 0)
3095 // Every part must evaluate to a bool.
3096 if (bool_on_stack(cctx) == FAIL)
3097 {
3098 ga_clear(&end_ga);
3099 return FAIL;
3100 }
3101
3102 if (end_ga.ga_len > 0)
3103 {
3104 // Fill in the end label in all jumps.
3105 generate_ppconst(cctx, ppconst);
3106 while (end_ga.ga_len > 0)
3107 {
3108 isn_T *isn;
3109
3110 --end_ga.ga_len;
3111 isn = ((isn_T *)instr->ga_data)
3112 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3113 isn->isn_arg.jump.jump_where = instr->ga_len;
3114 }
3115 }
3116 ga_clear(&end_ga);
3117
3118 cctx->ctx_skip = save_skip;
3119 }
3120
3121 return OK;
3122}
3123
3124/*
3125 * expr4a && expr4a && expr4a logical AND
3126 *
3127 * Produces instructions:
3128 * EVAL expr4a Push result of "expr4a"
3129 * COND2BOOL convert to bool if needed
3130 * JUMP_IF_COND_FALSE end
3131 * EVAL expr4b Push result of "expr4b"
3132 * JUMP_IF_COND_FALSE end
3133 * EVAL expr4c Push result of "expr4c"
3134 * end:
3135 */
3136 static int
3137compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3138{
3139 int ppconst_used = ppconst->pp_used;
3140
3141 // get the first variable
3142 if (compile_expr4(arg, cctx, ppconst) == FAIL)
3143 return FAIL;
3144
3145 // || and && work almost the same
3146 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
3147}
3148
3149/*
3150 * expr3a || expr3b || expr3c logical OR
3151 *
3152 * Produces instructions:
3153 * EVAL expr3a Push result of "expr3a"
3154 * COND2BOOL convert to bool if needed
3155 * JUMP_IF_COND_TRUE end
3156 * EVAL expr3b Push result of "expr3b"
3157 * JUMP_IF_COND_TRUE end
3158 * EVAL expr3c Push result of "expr3c"
3159 * end:
3160 */
3161 static int
3162compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3163{
3164 int ppconst_used = ppconst->pp_used;
3165
3166 // eval the first expression
3167 if (compile_expr3(arg, cctx, ppconst) == FAIL)
3168 return FAIL;
3169
3170 // || and && work almost the same
3171 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
3172}
3173
3174/*
3175 * Toplevel expression: expr2 ? expr1a : expr1b
3176 * Produces instructions:
3177 * EVAL expr2 Push result of "expr2"
3178 * JUMP_IF_FALSE alt jump if false
3179 * EVAL expr1a
3180 * JUMP_ALWAYS end
3181 * alt: EVAL expr1b
3182 * end:
3183 *
3184 * Toplevel expression: expr2 ?? expr1
3185 * Produces instructions:
3186 * EVAL expr2 Push result of "expr2"
3187 * JUMP_AND_KEEP_IF_TRUE end jump if true
3188 * EVAL expr1
3189 * end:
3190 */
3191 int
3192compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3193{
3194 char_u *p;
3195 int ppconst_used = ppconst->pp_used;
3196 char_u *next;
3197
3198 // Ignore all kinds of errors when not producing code.
3199 if (cctx->ctx_skip == SKIP_YES)
3200 {
Bram Moolenaar83d0cec2022-02-04 21:17:58 +00003201 int prev_did_emsg = did_emsg;
3202
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003203 skip_expr_cctx(arg, cctx);
Bram Moolenaar83d0cec2022-02-04 21:17:58 +00003204 return did_emsg == prev_did_emsg ? OK : FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003205 }
3206
3207 // Evaluate the first expression.
3208 if (compile_expr2(arg, cctx, ppconst) == FAIL)
3209 return FAIL;
3210
3211 p = may_peek_next_line(cctx, *arg, &next);
3212 if (*p == '?')
3213 {
3214 int op_falsy = p[1] == '?';
3215 garray_T *instr = &cctx->ctx_instr;
3216 garray_T *stack = &cctx->ctx_type_stack;
3217 int alt_idx = instr->ga_len;
3218 int end_idx = 0;
3219 isn_T *isn;
3220 type_T *type1 = NULL;
3221 int has_const_expr = FALSE;
3222 int const_value = FALSE;
3223 int save_skip = cctx->ctx_skip;
3224
3225 if (next != NULL)
3226 {
3227 *arg = next_line_from_context(cctx, TRUE);
3228 p = skipwhite(*arg);
3229 }
3230
3231 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
3232 {
3233 semsg(_(e_white_space_required_before_and_after_str_at_str),
3234 op_falsy ? "??" : "?", p);
3235 return FAIL;
3236 }
3237
3238 if (ppconst->pp_used == ppconst_used + 1)
3239 {
3240 // the condition is a constant, we know whether the ? or the :
3241 // expression is to be evaluated.
3242 has_const_expr = TRUE;
3243 if (op_falsy)
3244 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
3245 else
3246 {
3247 int error = FALSE;
3248
3249 const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
3250 &error);
3251 if (error)
3252 return FAIL;
3253 }
3254 cctx->ctx_skip = save_skip == SKIP_YES ||
3255 (op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
3256
3257 if (op_falsy && cctx->ctx_skip == SKIP_YES)
3258 // "left ?? right" and "left" is truthy: produce "left"
3259 generate_ppconst(cctx, ppconst);
3260 else
3261 {
3262 clear_tv(&ppconst->pp_tv[ppconst_used]);
3263 --ppconst->pp_used;
3264 }
3265 }
3266 else
3267 {
3268 generate_ppconst(cctx, ppconst);
3269 if (op_falsy)
3270 end_idx = instr->ga_len;
3271 generate_JUMP(cctx, op_falsy
3272 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
3273 if (op_falsy)
Bram Moolenaar078a4612022-01-04 15:17:03 +00003274 type1 = get_type_on_stack(cctx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003275 }
3276
3277 // evaluate the second expression; any type is accepted
3278 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
3279 return FAIL;
3280 if (compile_expr1(arg, cctx, ppconst) == FAIL)
3281 return FAIL;
3282
3283 if (!has_const_expr)
3284 {
3285 generate_ppconst(cctx, ppconst);
3286
3287 if (!op_falsy)
3288 {
3289 // remember the type and drop it
Bram Moolenaar078a4612022-01-04 15:17:03 +00003290 type1 = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003291 --stack->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003292
3293 end_idx = instr->ga_len;
3294 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3295
3296 // jump here from JUMP_IF_FALSE
3297 isn = ((isn_T *)instr->ga_data) + alt_idx;
3298 isn->isn_arg.jump.jump_where = instr->ga_len;
3299 }
3300 }
3301
3302 if (!op_falsy)
3303 {
3304 // Check for the ":".
3305 p = may_peek_next_line(cctx, *arg, &next);
3306 if (*p != ':')
3307 {
3308 emsg(_(e_missing_colon_after_questionmark));
3309 return FAIL;
3310 }
3311 if (next != NULL)
3312 {
3313 *arg = next_line_from_context(cctx, TRUE);
3314 p = skipwhite(*arg);
3315 }
3316
3317 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3318 {
3319 semsg(_(e_white_space_required_before_and_after_str_at_str),
3320 ":", p);
3321 return FAIL;
3322 }
3323
3324 // evaluate the third expression
3325 if (has_const_expr)
3326 cctx->ctx_skip = save_skip == SKIP_YES || const_value
3327 ? SKIP_YES : SKIP_NOT;
3328 if (may_get_next_line_error(p + 1, arg, cctx) == FAIL)
3329 return FAIL;
3330 if (compile_expr1(arg, cctx, ppconst) == FAIL)
3331 return FAIL;
3332 }
3333
3334 if (!has_const_expr)
3335 {
3336 type_T **typep;
3337
3338 generate_ppconst(cctx, ppconst);
Bram Moolenaarfa46ead2021-12-22 13:18:39 +00003339 ppconst->pp_is_const = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003340
3341 // If the types differ, the result has a more generic type.
Bram Moolenaar078a4612022-01-04 15:17:03 +00003342 typep = &((((type2_T *)stack->ga_data)
3343 + stack->ga_len - 1)->type_curr);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003344 common_type(type1, *typep, typep, cctx->ctx_type_list);
3345
3346 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
3347 isn = ((isn_T *)instr->ga_data) + end_idx;
3348 isn->isn_arg.jump.jump_where = instr->ga_len;
3349 }
3350
3351 cctx->ctx_skip = save_skip;
3352 }
3353 return OK;
3354}
3355
3356/*
3357 * Toplevel expression.
3358 * Sets "is_const" (if not NULL) to indicate the value is a constant.
3359 * Returns OK or FAIL.
3360 */
3361 int
3362compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const)
3363{
3364 ppconst_T ppconst;
3365
3366 CLEAR_FIELD(ppconst);
3367 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
3368 {
3369 clear_ppconst(&ppconst);
3370 return FAIL;
3371 }
3372 if (is_const != NULL)
3373 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const;
3374 if (generate_ppconst(cctx, &ppconst) == FAIL)
3375 return FAIL;
3376 return OK;
3377}
3378
3379/*
3380 * Toplevel expression.
3381 */
3382 int
3383compile_expr0(char_u **arg, cctx_T *cctx)
3384{
3385 return compile_expr0_ext(arg, cctx, NULL);
3386}
3387
3388
3389#endif // defined(FEAT_EVAL)