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