blob: 1034f64b070deab058bd2d5ff59673c4787316b3 [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 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +0000102 if (need_type(idxtype, &t_number, FALSE,
103 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000104 return FAIL;
105 if (is_slice)
106 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000107 idxtype = get_type_on_stack(cctx, 1);
Bram Moolenaarc6951a72022-12-29 20:56:24 +0000108 if (need_type(idxtype, &t_number, FALSE,
109 -2, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000110 return FAIL;
111 }
112 }
113
114 if (vartype == VAR_DICT)
115 {
116 if (is_slice)
117 {
118 emsg(_(e_cannot_slice_dictionary));
119 return FAIL;
120 }
Bram Moolenaar078a4612022-01-04 15:17:03 +0000121 if (typep->type_curr->tt_type == VAR_DICT)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000122 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000123 typep->type_curr = typep->type_curr->tt_member;
124 if (typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000125 // empty dict was used
Bram Moolenaar078a4612022-01-04 15:17:03 +0000126 typep->type_curr = &t_any;
127 if (typep->type_decl->tt_type == VAR_DICT)
128 {
129 typep->type_decl = typep->type_decl->tt_member;
130 if (typep->type_decl == &t_unknown)
131 // empty dict was used
132 typep->type_decl = &t_any;
133 }
134 else
135 typep->type_decl = typep->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000136 }
137 else
138 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +0000139 if (need_type(typep->type_curr, &t_dict_any, FALSE,
140 -2, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000141 return FAIL;
Bram Moolenaar078a4612022-01-04 15:17:03 +0000142 typep->type_curr = &t_any;
143 typep->type_decl = &t_any;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000144 }
Bram Moolenaard0132f42022-05-12 11:05:40 +0100145 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL
146 || generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000147 return FAIL;
148 if (keeping_dict != NULL)
149 *keeping_dict = TRUE;
150 }
151 else if (vartype == VAR_STRING)
152 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000153 typep->type_curr = &t_string;
154 typep->type_decl = &t_string;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000155 if ((is_slice
156 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
157 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
158 return FAIL;
159 }
160 else if (vartype == VAR_BLOB)
161 {
162 if (is_slice)
163 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000164 typep->type_curr = &t_blob;
165 typep->type_decl = &t_blob;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000166 if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL)
167 return FAIL;
168 }
169 else
170 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000171 typep->type_curr = &t_number;
172 typep->type_decl = &t_number;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000173 if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL)
174 return FAIL;
175 }
176 }
Bram Moolenaar4913d422022-10-17 13:13:32 +0100177 else if (vartype == VAR_LIST || typep->type_curr->tt_type == VAR_ANY
178 || typep->type_curr->tt_type == VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000179 {
180 if (is_slice)
181 {
182 if (generate_instr_drop(cctx,
183 vartype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
184 2) == FAIL)
185 return FAIL;
Bram Moolenaar5f4ef5f2022-02-06 18:36:53 +0000186 // a copy is made so the member type is no longer declared
187 if (typep->type_decl->tt_type == VAR_LIST)
188 typep->type_decl = &t_list_any;
Bram Moolenaaradbc08f2022-11-06 18:27:17 +0000189
190 // a copy is made, the composite is no longer "const"
191 if (typep->type_curr->tt_flags & TTFLAG_CONST)
192 {
193 type_T *type = copy_type(typep->type_curr, cctx->ctx_type_list);
194
195 if (type != typep->type_curr) // did get a copy
196 {
197 type->tt_flags &= ~(TTFLAG_CONST | TTFLAG_STATIC);
198 typep->type_curr = type;
199 }
200 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000201 }
202 else
203 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000204 if (typep->type_curr->tt_type == VAR_LIST)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000205 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000206 typep->type_curr = typep->type_curr->tt_member;
207 if (typep->type_curr == &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000208 // empty list was used
Bram Moolenaar078a4612022-01-04 15:17:03 +0000209 typep->type_curr = &t_any;
210 if (typep->type_decl->tt_type == VAR_LIST)
211 {
212 typep->type_decl = typep->type_decl->tt_member;
213 if (typep->type_decl == &t_unknown)
214 // empty list was used
215 typep->type_decl = &t_any;
216 }
217 else
218 typep->type_decl = typep->type_curr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000219 }
220 if (generate_instr_drop(cctx,
221 vartype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1)
222 == FAIL)
223 return FAIL;
224 }
225 }
226 else
227 {
228 switch (vartype)
229 {
230 case VAR_FUNC:
231 case VAR_PARTIAL:
232 emsg(_(e_cannot_index_a_funcref));
233 break;
234 case VAR_BOOL:
235 case VAR_SPECIAL:
236 case VAR_JOB:
237 case VAR_CHANNEL:
238 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000239 case VAR_CLASS:
240 case VAR_OBJECT:
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000241 case VAR_UNKNOWN:
242 case VAR_ANY:
243 case VAR_VOID:
244 emsg(_(e_cannot_index_special_variable));
245 break;
246 default:
247 emsg(_(e_string_list_dict_or_blob_required));
248 }
249 return FAIL;
250 }
251 return OK;
252}
253
254/*
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000255 * Compile ".member" coming after an object or class.
256 */
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000257 static int
258compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type)
259{
260 if (VIM_ISWHITE((*arg)[1]))
261 {
262 semsg(_(e_no_white_space_allowed_after_str_str), ".", *arg);
263 return FAIL;
264 }
265
Bram Moolenaar58b40092023-01-11 15:59:05 +0000266 class_T *cl = (class_T *)type->tt_member;
267 int is_super = type->tt_flags & TTFLAG_SUPER;
268 if (type == &t_super)
269 {
270 if (cctx->ctx_ufunc == NULL || cctx->ctx_ufunc->uf_class == NULL)
Bram Moolenaar58b40092023-01-11 15:59:05 +0000271 {
Bram Moolenaar6aa09372023-01-11 17:59:38 +0000272 emsg(_(e_using_super_not_in_class_function));
273 return FAIL;
Bram Moolenaar58b40092023-01-11 15:59:05 +0000274 }
Bram Moolenaar6aa09372023-01-11 17:59:38 +0000275 is_super = TRUE;
276 cl = cctx->ctx_ufunc->uf_class;
277 // Remove &t_super from the stack.
278 --cctx->ctx_type_stack.ga_len;
Bram Moolenaar58b40092023-01-11 15:59:05 +0000279 }
280 else if (type->tt_type == VAR_CLASS)
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000281 {
282 garray_T *instr = &cctx->ctx_instr;
283 if (instr->ga_len > 0)
284 {
285 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
286 if (isn->isn_type == ISN_LOADSCRIPT)
287 {
288 // The class was recognized as a script item. We only need
289 // to know what class it is, drop the instruction.
290 --instr->ga_len;
291 vim_free(isn->isn_arg.script.scriptref);
292 }
293 }
294 }
295
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000296 ++*arg;
297 char_u *name = *arg;
298 char_u *name_end = find_name_end(name, NULL, NULL, FNE_CHECK_START);
299 if (name_end == name)
300 return FAIL;
301 size_t len = name_end - name;
302
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000303 if (*name_end == '(')
304 {
Bram Moolenaar574950d2023-01-03 19:08:50 +0000305 int function_count;
Bram Moolenaar58b40092023-01-11 15:59:05 +0000306 int child_count;
Bram Moolenaar574950d2023-01-03 19:08:50 +0000307 ufunc_T **functions;
308
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000309 if (type->tt_type == VAR_CLASS)
310 {
Bram Moolenaar574950d2023-01-03 19:08:50 +0000311 function_count = cl->class_class_function_count;
Bram Moolenaar58b40092023-01-11 15:59:05 +0000312 child_count = cl->class_class_function_count_child;
Bram Moolenaar574950d2023-01-03 19:08:50 +0000313 functions = cl->class_class_functions;
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000314 }
315 else
316 {
Bram Moolenaar574950d2023-01-03 19:08:50 +0000317 // type->tt_type == VAR_OBJECT: method call
318 function_count = cl->class_obj_method_count;
Bram Moolenaar58b40092023-01-11 15:59:05 +0000319 child_count = cl->class_obj_method_count_child;
Bram Moolenaar574950d2023-01-03 19:08:50 +0000320 functions = cl->class_obj_methods;
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000321 }
Bram Moolenaar574950d2023-01-03 19:08:50 +0000322
323 ufunc_T *ufunc = NULL;
Bram Moolenaar58b40092023-01-11 15:59:05 +0000324 for (int i = is_super ? child_count : 0; i < function_count; ++i)
Bram Moolenaar574950d2023-01-03 19:08:50 +0000325 {
326 ufunc_T *fp = functions[i];
327 // Use a separate pointer to avoid that ASAN complains about
328 // uf_name[] only being 4 characters.
329 char_u *ufname = (char_u *)fp->uf_name;
330 if (STRNCMP(name, ufname, len) == 0 && ufname[len] == NUL)
331 {
332 ufunc = fp;
333 break;
334 }
335 }
336 if (ufunc == NULL)
337 {
338 // TODO: different error for object method?
339 semsg(_(e_method_not_found_on_class_str_str), cl->class_name, name);
340 return FAIL;
341 }
342
343 // Compile the arguments and call the class function or object method.
344 // The object method will know that the object is on the stack, just
345 // before the arguments.
346 *arg = skipwhite(name_end + 1);
347 int argcount = 0;
348 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
349 return FAIL;
350 return generate_CALL(cctx, ufunc, argcount);
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000351 }
Bram Moolenaar574950d2023-01-03 19:08:50 +0000352
353 if (type->tt_type == VAR_OBJECT)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000354 {
355 for (int i = 0; i < cl->class_obj_member_count; ++i)
356 {
Bram Moolenaard505d172022-12-18 21:42:55 +0000357 ocmember_T *m = &cl->class_obj_members[i];
358 if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000359 {
Bram Moolenaar62a69232023-01-24 15:07:04 +0000360 if (*name == '_' && !inside_class(cctx, cl))
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000361 {
Bram Moolenaard505d172022-12-18 21:42:55 +0000362 semsg(_(e_cannot_access_private_member_str), m->ocm_name);
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000363 return FAIL;
364 }
365
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000366 *arg = name_end;
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000367 if (cl->class_flags & CLASS_INTERFACE)
368 return generate_GET_ITF_MEMBER(cctx, cl, i, m->ocm_type);
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000369 return generate_GET_OBJ_MEMBER(cctx, i, m->ocm_type);
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000370 }
371 }
372
373 semsg(_(e_member_not_found_on_object_str_str), cl->class_name, name);
374 }
375 else
376 {
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000377 // load class member
378 int idx;
379 for (idx = 0; idx < cl->class_class_member_count; ++idx)
380 {
381 ocmember_T *m = &cl->class_class_members[idx];
382 if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
383 break;
384 }
385 if (idx < cl->class_class_member_count)
386 {
387 *arg = name_end;
388 return generate_CLASSMEMBER(cctx, TRUE, cl, idx);
389 }
390 semsg(_(e_class_member_not_found_str), name);
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000391 }
392
393 return FAIL;
394}
395
396/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000397 * Generate an instruction to load script-local variable "name", without the
398 * leading "s:".
399 * Also finds imported variables.
400 */
401 int
402compile_load_scriptvar(
403 cctx_T *cctx,
404 char_u *name, // variable NUL terminated
405 char_u *start, // start of variable
Bram Moolenaard0132f42022-05-12 11:05:40 +0100406 char_u **end) // end of variable, may be NULL
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000407{
408 scriptitem_T *si;
409 int idx;
410 imported_T *import;
411
412 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
413 return FAIL;
414 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaarb6a138e2022-02-08 21:17:22 +0000415 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx, NULL);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000416 if (idx >= 0)
417 {
418 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
419
420 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
421 current_sctx.sc_sid, idx, sv->sv_type);
422 return OK;
423 }
424
Bram Moolenaar4b1d9632022-02-13 21:51:08 +0000425 import = end == NULL ? NULL : find_imported(name, 0, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000426 if (import != NULL)
427 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000428 char_u *p = skipwhite(*end);
429 char_u *exp_name;
430 int cc;
Bram Moolenaarffe6e642022-04-01 13:23:47 +0100431 ufunc_T *ufunc = NULL;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000432 type_T *type;
Bram Moolenaard041f422022-01-12 19:54:00 +0000433 int done = FALSE;
434 int res = OK;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000435
436 // Need to lookup the member.
437 if (*p != '.')
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000438 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000439 semsg(_(e_expected_dot_after_name_str), start);
440 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000441 }
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000442 ++p;
443 if (VIM_ISWHITE(*p))
444 {
445 emsg(_(e_no_white_space_allowed_after_dot));
446 return FAIL;
447 }
448
449 // isolate one name
450 exp_name = p;
451 while (eval_isnamec(*p))
452 ++p;
453 cc = *p;
454 *p = NUL;
455
Bram Moolenaard041f422022-01-12 19:54:00 +0000456 si = SCRIPT_ITEM(import->imp_sid);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100457 if (si->sn_import_autoload && si->sn_state == SN_STATE_NOT_LOADED)
458 // "import autoload './dir/script.vim'" or
459 // "import autoload './autoload/script.vim'" - load script first
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100460 res = generate_SOURCE(cctx, import->imp_sid);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100461
462 if (res == OK)
463 {
464 if (si->sn_autoload_prefix != NULL
465 && si->sn_state == SN_STATE_NOT_LOADED)
466 {
467 char_u *auto_name =
468 concat_str(si->sn_autoload_prefix, exp_name);
469
470 // autoload script must be loaded later, access by the autoload
471 // name. If a '(' follows it must be a function. Otherwise we
472 // don't know, it can be "script.Func".
473 if (cc == '(' || paren_follows_after_expr)
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100474 res = generate_PUSHFUNC(cctx, auto_name, &t_func_any, TRUE);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100475 else
476 res = generate_AUTOLOAD(cctx, auto_name, &t_any);
477 vim_free(auto_name);
478 done = TRUE;
479 }
480 else if (si->sn_import_autoload
481 && si->sn_state == SN_STATE_NOT_LOADED)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100482 {
483 // If a '(' follows it must be a function. Otherwise we don't
484 // know, it can be "script.Func".
485 if (cc == '(' || paren_follows_after_expr)
486 {
487 char_u sid_name[MAX_FUNC_NAME_LEN];
488
489 func_name_with_sid(exp_name, import->imp_sid, sid_name);
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100490 res = generate_PUSHFUNC(cctx, sid_name, &t_func_any, TRUE);
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100491 }
492 else
493 res = generate_OLDSCRIPT(cctx, ISN_LOADEXPORT, exp_name,
494 import->imp_sid, &t_any);
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100495 done = TRUE;
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100496 }
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100497 else
498 {
499 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
500 cctx, NULL, TRUE);
501 }
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +0100502 }
Bram Moolenaarccbfd482022-03-31 16:18:23 +0100503
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000504 *p = cc;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000505 *end = p;
Bram Moolenaard041f422022-01-12 19:54:00 +0000506 if (done)
507 return res;
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000508
509 if (idx < 0)
510 {
511 if (ufunc != NULL)
512 {
513 // function call or function reference
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100514 generate_PUSHFUNC(cctx, ufunc->uf_name, NULL, TRUE);
Bram Moolenaard5f400c2022-01-06 21:10:28 +0000515 return OK;
516 }
517 return FAIL;
518 }
519
520 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
521 import->imp_sid,
522 idx,
523 type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000524 return OK;
525 }
526
Bram Moolenaard0132f42022-05-12 11:05:40 +0100527 // Can only get here if we know "name" is a script variable and not in a
528 // Vim9 script (variable is not in sn_var_vals): old style script.
529 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
Bram Moolenaar62aec932022-01-29 21:45:34 +0000530 &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000531}
532
533 static int
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000534generate_funcref(cctx_T *cctx, char_u *name, int has_g_prefix)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000535{
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000536 ufunc_T *ufunc = find_func(name, FALSE);
Bram Moolenaar139575d2022-03-15 19:29:30 +0000537 compiletype_T compile_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000538
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000539 // Reject a global non-autoload function found without the "g:" prefix.
540 if (ufunc == NULL || (!has_g_prefix && func_requires_g_prefix(ufunc)))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000541 return FAIL;
542
543 // Need to compile any default values to get the argument types.
Bram Moolenaar139575d2022-03-15 19:29:30 +0000544 compile_type = get_compile_type(ufunc);
545 if (func_needs_compiling(ufunc, compile_type)
Bram Moolenaar21dc8f12022-03-16 17:54:17 +0000546 && compile_def_function(ufunc, TRUE, compile_type, NULL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000547 return FAIL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100548 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000549}
550
551/*
552 * Compile a variable name into a load instruction.
553 * "end" points to just after the name.
554 * "is_expr" is TRUE when evaluating an expression, might be a funcref.
555 * When "error" is FALSE do not give an error when not found.
556 */
557 int
558compile_load(
559 char_u **arg,
560 char_u *end_arg,
561 cctx_T *cctx,
562 int is_expr,
563 int error)
564{
565 type_T *type;
566 char_u *name = NULL;
567 char_u *end = end_arg;
568 int res = FAIL;
569 int prev_called_emsg = called_emsg;
570
571 if (*(*arg + 1) == ':')
572 {
573 if (end <= *arg + 2)
574 {
575 isntype_T isn_type;
576
577 // load dictionary of namespace
578 switch (**arg)
579 {
580 case 'g': isn_type = ISN_LOADGDICT; break;
581 case 'w': isn_type = ISN_LOADWDICT; break;
582 case 't': isn_type = ISN_LOADTDICT; break;
583 case 'b': isn_type = ISN_LOADBDICT; break;
584 default:
585 semsg(_(e_namespace_not_supported_str), *arg);
586 goto theend;
587 }
588 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
589 goto theend;
590 res = OK;
591 }
592 else
593 {
594 isntype_T isn_type = ISN_DROP;
595
596 // load namespaced variable
597 name = vim_strnsave(*arg + 2, end - (*arg + 2));
598 if (name == NULL)
599 return FAIL;
600
601 switch (**arg)
602 {
Bram Moolenaarc3caa7f2022-05-25 19:15:10 +0100603 case 'v': res = generate_LOADV(cctx, name);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000604 break;
Bram Moolenaarafa048f2022-02-22 20:43:36 +0000605 case 's': if (current_script_is_vim9())
606 {
607 semsg(_(e_cannot_use_s_colon_in_vim9_script_str),
608 *arg);
609 vim_free(name);
610 return FAIL;
611 }
Kota Kato948a3892022-08-16 16:09:59 +0100612 if (is_expr && find_func(name, FALSE) != NULL)
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000613 res = generate_funcref(cctx, name, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000614 else
615 res = compile_load_scriptvar(cctx, name,
Bram Moolenaard0132f42022-05-12 11:05:40 +0100616 NULL, &end);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000617 break;
618 case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
619 {
620 if (is_expr && ASCII_ISUPPER(*name)
Bram Moolenaard9d2fd02022-01-13 21:15:21 +0000621 && find_func(name, FALSE) != NULL)
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000622 res = generate_funcref(cctx, name, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000623 else
624 isn_type = ISN_LOADG;
625 }
626 else
627 {
628 isn_type = ISN_LOADAUTO;
629 vim_free(name);
630 name = vim_strnsave(*arg, end - *arg);
631 if (name == NULL)
632 return FAIL;
633 }
634 break;
635 case 'w': isn_type = ISN_LOADW; break;
636 case 't': isn_type = ISN_LOADT; break;
637 case 'b': isn_type = ISN_LOADB; break;
638 default: // cannot happen, just in case
639 semsg(_(e_namespace_not_supported_str), *arg);
640 goto theend;
641 }
642 if (isn_type != ISN_DROP)
643 {
644 // Global, Buffer-local, Window-local and Tabpage-local
645 // variables can be defined later, thus we don't check if it
646 // exists, give an error at runtime.
Bram Moolenaarfa46ead2021-12-22 13:18:39 +0000647 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000648 }
649 }
650 }
651 else
652 {
653 size_t len = end - *arg;
654 int idx;
655 int gen_load = FALSE;
656 int gen_load_outer = 0;
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +0100657 int outer_loop_depth = -1;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +0100658 int outer_loop_idx = -1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000659
660 name = vim_strnsave(*arg, end - *arg);
661 if (name == NULL)
662 return FAIL;
663
Bram Moolenaar58b40092023-01-11 15:59:05 +0000664 if (STRCMP(name, "super") == 0
665 && cctx->ctx_ufunc != NULL
666 && (cctx->ctx_ufunc->uf_flags & (FC_OBJECT|FC_NEW)) == 0)
667 {
668 // super.SomeFunc() in a class function: push &t_super type, this
669 // is recognized in compile_subscript().
670 res = push_type_stack(cctx, &t_super);
671 if (*end != '.')
672 emsg(_(e_super_must_be_followed_by_dot));
673 }
674 else if (vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000675 {
676 script_autoload(name, FALSE);
677 res = generate_LOAD(cctx, ISN_LOADAUTO, 0, name, &t_any);
678 }
679 else if (arg_exists(*arg, len, &idx, &type, &gen_load_outer, cctx)
680 == OK)
681 {
682 if (gen_load_outer == 0)
683 gen_load = TRUE;
684 }
685 else
686 {
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000687 lvar_T lvar;
688 class_T *cl = NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000689
690 if (lookup_local(*arg, len, &lvar, cctx) == OK)
691 {
692 type = lvar.lv_type;
693 idx = lvar.lv_idx;
694 if (lvar.lv_from_outer != 0)
Bram Moolenaarf8addf12022-09-23 12:44:25 +0100695 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000696 gen_load_outer = lvar.lv_from_outer;
Bram Moolenaarf8addf12022-09-23 12:44:25 +0100697 outer_loop_depth = lvar.lv_loop_depth;
698 outer_loop_idx = lvar.lv_loop_idx;
699 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000700 else
701 gen_load = TRUE;
702 }
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000703 else if ((idx = class_member_index(*arg, len, &cl, cctx)) >= 0)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000704 {
705 res = generate_CLASSMEMBER(cctx, TRUE, cl, idx);
706 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000707 else
708 {
709 // "var" can be script-local even without using "s:" if it
710 // already exists in a Vim9 script or when it's imported.
Bram Moolenaardce24412022-02-08 20:35:30 +0000711 if (script_var_exists(*arg, len, cctx, NULL) == OK
Bram Moolenaar4b1d9632022-02-13 21:51:08 +0000712 || find_imported(name, 0, FALSE) != NULL)
Bram Moolenaard0132f42022-05-12 11:05:40 +0100713 res = compile_load_scriptvar(cctx, name, *arg, &end);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000714
715 // When evaluating an expression and the name starts with an
716 // uppercase letter it can be a user defined function.
717 // generate_funcref() will fail if the function can't be found.
718 if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
Bram Moolenaar848fadd2022-01-30 15:28:30 +0000719 res = generate_funcref(cctx, name, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000720 }
721 }
722 if (gen_load)
723 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
724 if (gen_load_outer > 0)
725 {
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +0100726 res = generate_LOADOUTER(cctx, idx, gen_load_outer,
727 outer_loop_depth, outer_loop_idx, type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000728 cctx->ctx_outer_used = TRUE;
729 }
730 }
731
732 *arg = end;
733
734theend:
735 if (res == FAIL && error && called_emsg == prev_called_emsg)
736 semsg(_(e_variable_not_found_str), name);
737 vim_free(name);
738 return res;
739}
740
741/*
742 * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR.
LemonBoyf3b48952022-05-05 13:53:03 +0100743 * "str_offset" is the number of leading bytes to skip from the string.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000744 * Returns FAIL if compilation fails.
745 */
746 static int
LemonBoyf3b48952022-05-05 13:53:03 +0100747compile_string(isn_T *isn, cctx_T *cctx, int str_offset)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000748{
LemonBoyf3b48952022-05-05 13:53:03 +0100749 char_u *s = isn->isn_arg.string + str_offset;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000750 garray_T save_ga = cctx->ctx_instr;
751 int expr_res;
752 int trailing_error;
753 int instr_count;
754 isn_T *instr = NULL;
755
756 // Remove the string type from the stack.
757 --cctx->ctx_type_stack.ga_len;
758
759 // Temporarily reset the list of instructions so that the jump labels are
760 // correct.
761 cctx->ctx_instr.ga_len = 0;
762 cctx->ctx_instr.ga_maxlen = 0;
763 cctx->ctx_instr.ga_data = NULL;
h-east01c5f2a2023-01-09 15:10:40 +0000764
765 // avoid peeking a next line
766 int galen_save = cctx->ctx_ufunc->uf_lines.ga_len;
767 cctx->ctx_ufunc->uf_lines.ga_len = 0;
768
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000769 expr_res = compile_expr0(&s, cctx);
h-east01c5f2a2023-01-09 15:10:40 +0000770
771 cctx->ctx_ufunc->uf_lines.ga_len = galen_save;
772
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000773 s = skipwhite(s);
774 trailing_error = *s != NUL;
775
776 if (expr_res == FAIL || trailing_error
777 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
778 {
779 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +0000780 semsg(_(e_trailing_characters_str), s);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000781 clear_instr_ga(&cctx->ctx_instr);
782 cctx->ctx_instr = save_ga;
783 ++cctx->ctx_type_stack.ga_len;
784 return FAIL;
785 }
786
787 // Move the generated instructions into the ISN_INSTR instruction, then
788 // restore the list of instructions.
789 instr_count = cctx->ctx_instr.ga_len;
790 instr = cctx->ctx_instr.ga_data;
791 instr[instr_count].isn_type = ISN_FINISH;
792
793 cctx->ctx_instr = save_ga;
794 vim_free(isn->isn_arg.string);
795 isn->isn_type = ISN_INSTR;
796 isn->isn_arg.instr = instr;
797 return OK;
798}
799
800/*
801 * Compile the argument expressions.
802 * "arg" points to just after the "(" and is advanced to after the ")"
803 */
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100804 int
LemonBoyf3b48952022-05-05 13:53:03 +0100805compile_arguments(
806 char_u **arg,
807 cctx_T *cctx,
808 int *argcount,
809 ca_special_T special_fn)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000810{
811 char_u *p = *arg;
812 char_u *whitep = *arg;
813 int must_end = FALSE;
814 int instr_count;
815
816 for (;;)
817 {
818 if (may_get_next_line(whitep, &p, cctx) == FAIL)
819 goto failret;
820 if (*p == ')')
821 {
822 *arg = p + 1;
823 return OK;
824 }
825 if (must_end)
826 {
827 semsg(_(e_missing_comma_before_argument_str), p);
828 return FAIL;
829 }
830
831 instr_count = cctx->ctx_instr.ga_len;
832 if (compile_expr0(&p, cctx) == FAIL)
833 return FAIL;
834 ++*argcount;
835
LemonBoyf3b48952022-05-05 13:53:03 +0100836 if (special_fn == CA_SEARCHPAIR && *argcount == 5
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000837 && cctx->ctx_instr.ga_len == instr_count + 1)
838 {
839 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
840
841 // {skip} argument of searchpair() can be compiled if not empty
842 if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL)
LemonBoyf3b48952022-05-05 13:53:03 +0100843 compile_string(isn, cctx, 0);
844 }
845 else if (special_fn == CA_SUBSTITUTE && *argcount == 3
846 && cctx->ctx_instr.ga_len == instr_count + 1)
847 {
848 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
849
850 // {sub} argument of substitute() can be compiled if it starts
851 // with \=
852 if (isn->isn_type == ISN_PUSHS && isn->isn_arg.string[0] == '\\'
Bram Moolenaar4913d422022-10-17 13:13:32 +0100853 && isn->isn_arg.string[1] == '=')
LemonBoyf3b48952022-05-05 13:53:03 +0100854 compile_string(isn, cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000855 }
856
857 if (*p != ',' && *skipwhite(p) == ',')
858 {
859 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
860 p = skipwhite(p);
861 }
862 if (*p == ',')
863 {
864 ++p;
865 if (*p != NUL && !VIM_ISWHITE(*p))
866 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
867 }
868 else
869 must_end = TRUE;
870 whitep = p;
871 p = skipwhite(p);
872 }
873failret:
874 emsg(_(e_missing_closing_paren));
875 return FAIL;
876}
877
878/*
879 * Compile a function call: name(arg1, arg2)
880 * "arg" points to "name", "arg + varlen" to the "(".
881 * "argcount_init" is 1 for "value->method()"
882 * Instructions:
883 * EVAL arg1
884 * EVAL arg2
885 * BCALL / DCALL / UCALL
886 */
887 static int
888compile_call(
889 char_u **arg,
890 size_t varlen,
891 cctx_T *cctx,
892 ppconst_T *ppconst,
893 int argcount_init)
894{
895 char_u *name = *arg;
896 char_u *p;
897 int argcount = argcount_init;
Bram Moolenaara6c18d32022-03-31 20:02:56 +0100898 char_u namebuf[MAX_FUNC_NAME_LEN];
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000899 char_u fname_buf[FLEN_FIXED + 1];
900 char_u *tofree = NULL;
901 int error = FCERR_NONE;
902 ufunc_T *ufunc = NULL;
903 int res = FAIL;
904 int is_autoload;
Bram Moolenaar62aec932022-01-29 21:45:34 +0000905 int has_g_namespace;
LemonBoyf3b48952022-05-05 13:53:03 +0100906 ca_special_T special_fn;
Bram Moolenaarf67c7172022-01-19 17:23:05 +0000907 imported_T *import;
908
909 if (varlen >= sizeof(namebuf))
910 {
911 semsg(_(e_name_too_long_str), name);
912 return FAIL;
913 }
914 vim_strncpy(namebuf, *arg, varlen);
915
Bram Moolenaar4b1d9632022-02-13 21:51:08 +0000916 import = find_imported(name, varlen, FALSE);
Bram Moolenaarf67c7172022-01-19 17:23:05 +0000917 if (import != NULL)
918 {
919 semsg(_(e_cannot_use_str_itself_it_is_imported), namebuf);
920 return FAIL;
921 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000922
923 // We can evaluate "has('name')" at compile time.
LemonBoy58f331a2022-04-02 21:59:06 +0100924 // We can evaluate "len('string')" at compile time.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000925 // We always evaluate "exists_compiled()" at compile time.
LemonBoy58f331a2022-04-02 21:59:06 +0100926 if ((varlen == 3
927 && (STRNCMP(*arg, "has", 3) == 0 || STRNCMP(*arg, "len", 3) == 0))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000928 || (varlen == 15 && STRNCMP(*arg, "exists_compiled", 6) == 0))
929 {
930 char_u *s = skipwhite(*arg + varlen + 1);
931 typval_T argvars[2];
932 int is_has = **arg == 'h';
LemonBoy58f331a2022-04-02 21:59:06 +0100933 int is_len = **arg == 'l';
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000934
935 argvars[0].v_type = VAR_UNKNOWN;
936 if (*s == '"')
Bram Moolenaar0abc2872022-05-10 13:24:30 +0100937 (void)eval_string(&s, &argvars[0], TRUE, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000938 else if (*s == '\'')
Bram Moolenaar0abc2872022-05-10 13:24:30 +0100939 (void)eval_lit_string(&s, &argvars[0], TRUE, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000940 s = skipwhite(s);
941 if (*s == ')' && argvars[0].v_type == VAR_STRING
942 && ((is_has && !dynamic_feature(argvars[0].vval.v_string))
943 || !is_has))
944 {
945 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
946
947 *arg = s + 1;
948 argvars[1].v_type = VAR_UNKNOWN;
949 tv->v_type = VAR_NUMBER;
950 tv->vval.v_number = 0;
951 if (is_has)
952 f_has(argvars, tv);
LemonBoy58f331a2022-04-02 21:59:06 +0100953 else if (is_len)
954 f_len(argvars, tv);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000955 else
956 f_exists(argvars, tv);
957 clear_tv(&argvars[0]);
958 ++ppconst->pp_used;
959 return OK;
960 }
961 clear_tv(&argvars[0]);
LemonBoy58f331a2022-04-02 21:59:06 +0100962 if (!is_has && !is_len)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000963 {
964 emsg(_(e_argument_of_exists_compiled_must_be_literal_string));
965 return FAIL;
966 }
967 }
968
969 if (generate_ppconst(cctx, ppconst) == FAIL)
970 return FAIL;
971
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000972 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
973
974 // We handle the "skip" argument of searchpair() and searchpairpos()
975 // differently.
LemonBoyf3b48952022-05-05 13:53:03 +0100976 if ((varlen == 6 && STRNCMP(*arg, "search", 6) == 0)
977 || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0)
978 || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0)
979 || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0))
980 special_fn = CA_SEARCHPAIR;
981 else if (varlen == 10 && STRNCMP(*arg, "substitute", 10) == 0)
982 special_fn = CA_SUBSTITUTE;
983 else
984 special_fn = CA_NOT_SPECIAL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000985
986 *arg = skipwhite(*arg + varlen + 1);
LemonBoyf3b48952022-05-05 13:53:03 +0100987 if (compile_arguments(arg, cctx, &argcount, special_fn) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000988 goto theend;
989
990 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
991 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
992 {
993 int idx;
994
995 // builtin function
996 idx = find_internal_func(name);
997 if (idx >= 0)
998 {
999 if (STRCMP(name, "flatten") == 0)
1000 {
1001 emsg(_(e_cannot_use_flatten_in_vim9_script));
1002 goto theend;
1003 }
1004
1005 if (STRCMP(name, "add") == 0 && argcount == 2)
1006 {
Bram Moolenaareb4a9ba2022-02-01 12:47:07 +00001007 type_T *type = get_decl_type_on_stack(cctx, 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001008
1009 // add() can be compiled to instructions if we know the type
1010 if (type->tt_type == VAR_LIST)
1011 {
1012 // inline "add(list, item)" so that the type can be checked
1013 res = generate_LISTAPPEND(cctx);
1014 idx = -1;
1015 }
1016 else if (type->tt_type == VAR_BLOB)
1017 {
1018 // inline "add(blob, nr)" so that the type can be checked
1019 res = generate_BLOBAPPEND(cctx);
1020 idx = -1;
1021 }
1022 }
1023
Bram Moolenaarf5fec052022-09-11 11:49:22 +01001024 if ((STRCMP(name, "writefile") == 0 && argcount > 2)
1025 || (STRCMP(name, "mkdir") == 0 && argcount > 1))
Bram Moolenaar806a2732022-09-04 15:40:36 +01001026 {
Bram Moolenaarf5fec052022-09-11 11:49:22 +01001027 // May have the "D" or "R" flag, reserve a variable for a
1028 // deferred function call.
Bram Moolenaar806a2732022-09-04 15:40:36 +01001029 if (get_defer_var_idx(cctx) == 0)
1030 idx = -1;
1031 }
1032
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001033 if (idx >= 0)
1034 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
1035 }
1036 else
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001037 emsg_funcname(e_unknown_function_str, namebuf);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001038 goto theend;
1039 }
1040
Bram Moolenaar62aec932022-01-29 21:45:34 +00001041 has_g_namespace = STRNCMP(namebuf, "g:", 2) == 0;
1042
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001043 // An argument or local variable can be a function reference, this
1044 // overrules a function name.
1045 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL
1046 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK)
1047 {
1048 // If we can find the function by name generate the right call.
1049 // Skip global functions here, a local funcref takes precedence.
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00001050 ufunc = find_func(name, FALSE);
Bram Moolenaar62aec932022-01-29 21:45:34 +00001051 if (ufunc != NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001052 {
Bram Moolenaar62aec932022-01-29 21:45:34 +00001053 if (!func_is_global(ufunc))
1054 {
1055 res = generate_CALL(cctx, ufunc, argcount);
1056 goto theend;
1057 }
1058 if (!has_g_namespace
1059 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL)
1060 {
1061 // A function name without g: prefix must be found locally.
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001062 emsg_funcname(e_unknown_function_str, namebuf);
Bram Moolenaar62aec932022-01-29 21:45:34 +00001063 goto theend;
1064 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001065 }
1066 }
1067
1068 // If the name is a variable, load it and use PCALL.
1069 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar848fadd2022-01-30 15:28:30 +00001070 // Not for some#Func(), it will be loaded later.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001071 p = namebuf;
Bram Moolenaar62aec932022-01-29 21:45:34 +00001072 if (!has_g_namespace && !is_autoload
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001073 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
1074 {
Bram Moolenaar078a4612022-01-04 15:17:03 +00001075 type_T *type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001076
1077 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
1078 goto theend;
1079 }
1080
1081 // If we can find a global function by name generate the right call.
1082 if (ufunc != NULL)
1083 {
1084 res = generate_CALL(cctx, ufunc, argcount);
1085 goto theend;
1086 }
1087
1088 // A global function may be defined only later. Need to figure out at
1089 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar62aec932022-01-29 21:45:34 +00001090 if (has_g_namespace || is_autoload)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001091 res = generate_UCALL(cctx, name, argcount);
1092 else
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001093 emsg_funcname(e_unknown_function_str, namebuf);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001094
1095theend:
1096 vim_free(tofree);
1097 return res;
1098}
1099
1100// like NAMESPACE_CHAR but with 'a' and 'l'.
1101#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
1102
1103/*
1104 * Find the end of a variable or function name. Unlike find_name_end() this
1105 * does not recognize magic braces.
1106 * When "use_namespace" is TRUE recognize "b:", "s:", etc.
1107 * Return a pointer to just after the name. Equal to "arg" if there is no
1108 * valid name.
1109 */
1110 char_u *
1111to_name_end(char_u *arg, int use_namespace)
1112{
1113 char_u *p;
1114
1115 // Quick check for valid starting character.
1116 if (!eval_isnamec1(*arg))
1117 return arg;
1118
1119 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
1120 // Include a namespace such as "s:var" and "v:var". But "n:" is not
1121 // and can be used in slice "[n:]".
1122 if (*p == ':' && (p != arg + 1
1123 || !use_namespace
1124 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
1125 break;
1126 return p;
1127}
1128
1129/*
1130 * Like to_name_end() but also skip over a list or dict constant.
1131 * Also accept "<SNR>123_Func".
1132 * This intentionally does not handle line continuation.
1133 */
1134 char_u *
1135to_name_const_end(char_u *arg)
1136{
1137 char_u *p = arg;
1138 typval_T rettv;
1139
1140 if (STRNCMP(p, "<SNR>", 5) == 0)
1141 p = skipdigits(p + 5);
1142 p = to_name_end(p, TRUE);
1143 if (p == arg && *arg == '[')
1144 {
1145
1146 // Can be "[1, 2, 3]->Func()".
1147 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
1148 p = arg;
1149 }
1150 return p;
1151}
1152
1153/*
1154 * parse a list: [expr, expr]
1155 * "*arg" points to the '['.
1156 * ppconst->pp_is_const is set if all items are a constant.
1157 */
1158 static int
1159compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1160{
1161 char_u *p = skipwhite(*arg + 1);
1162 char_u *whitep = *arg + 1;
1163 int count = 0;
1164 int is_const;
1165 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar2984ed32022-08-20 14:51:17 +01001166 int must_end = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001167
1168 for (;;)
1169 {
1170 if (may_get_next_line(whitep, &p, cctx) == FAIL)
1171 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00001172 semsg(_(e_missing_end_of_list_rsb_str), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001173 return FAIL;
1174 }
1175 if (*p == ',')
1176 {
1177 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
1178 return FAIL;
1179 }
1180 if (*p == ']')
1181 {
1182 ++p;
1183 break;
1184 }
Bram Moolenaar2984ed32022-08-20 14:51:17 +01001185 if (must_end)
1186 {
1187 semsg(_(e_missing_comma_in_list_str), p);
1188 return FAIL;
1189 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001190 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL)
1191 return FAIL;
1192 if (!is_const)
1193 is_all_const = FALSE;
1194 ++count;
1195 if (*p == ',')
1196 {
1197 ++p;
1198 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
1199 {
1200 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
1201 return FAIL;
1202 }
1203 }
Bram Moolenaar2984ed32022-08-20 14:51:17 +01001204 else
1205 must_end = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001206 whitep = p;
1207 p = skipwhite(p);
1208 }
1209 *arg = p;
1210
1211 ppconst->pp_is_const = is_all_const;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001212 return generate_NEWLIST(cctx, count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001213}
1214
1215/*
1216 * Parse a lambda: "(arg, arg) => expr"
1217 * "*arg" points to the '('.
1218 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
1219 */
1220 static int
1221compile_lambda(char_u **arg, cctx_T *cctx)
1222{
1223 int r;
1224 typval_T rettv;
1225 ufunc_T *ufunc;
1226 evalarg_T evalarg;
1227
1228 init_evalarg(&evalarg);
1229 evalarg.eval_flags = EVAL_EVALUATE;
1230 evalarg.eval_cctx = cctx;
1231
1232 // Get the funcref in "rettv".
1233 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
1234 if (r != OK)
1235 {
1236 clear_evalarg(&evalarg, NULL);
1237 return r;
1238 }
1239
1240 // "rettv" will now be a partial referencing the function.
1241 ufunc = rettv.vval.v_partial->pt_func;
1242 ++ufunc->uf_refcount;
1243 clear_tv(&rettv);
1244
1245 // Compile it here to get the return type. The return type is optional,
1246 // when it's missing use t_unknown. This is recognized in
1247 // compile_return().
1248 if (ufunc->uf_ret_type->tt_type == VAR_VOID)
1249 ufunc->uf_ret_type = &t_unknown;
1250 compile_def_function(ufunc, FALSE, cctx->ctx_compile_type, cctx);
1251
1252 // When the outer function is compiled for profiling or debugging, the
1253 // lambda may be called without profiling or debugging. Compile it here in
1254 // the right context.
1255 if (cctx->ctx_compile_type == CT_DEBUG
1256#ifdef FEAT_PROFILE
1257 || cctx->ctx_compile_type == CT_PROFILE
1258#endif
1259 )
1260 compile_def_function(ufunc, FALSE, CT_NONE, cctx);
1261
Bram Moolenaar139575d2022-03-15 19:29:30 +00001262 // if the outer function is not compiled for debugging or profiling, this
1263 // one might be
1264 if (cctx->ctx_compile_type == CT_NONE)
Bram Moolenaar96923b72022-03-15 15:57:04 +00001265 {
Bram Moolenaar139575d2022-03-15 19:29:30 +00001266 compiletype_T compile_type = get_compile_type(ufunc);
1267
1268 if (compile_type != CT_NONE)
1269 compile_def_function(ufunc, FALSE, compile_type, cctx);
Bram Moolenaar96923b72022-03-15 15:57:04 +00001270 }
1271
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001272 // The last entry in evalarg.eval_tofree_ga is a copy of the last line and
1273 // "*arg" may point into it. Point into the original line to avoid a
1274 // dangling pointer.
1275 if (evalarg.eval_using_cmdline)
1276 {
1277 garray_T *gap = &evalarg.eval_tofree_ga;
1278 size_t off = *arg - ((char_u **)gap->ga_data)[gap->ga_len - 1];
1279
1280 *arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
1281 + off;
Bram Moolenaarf8addf12022-09-23 12:44:25 +01001282 evalarg.eval_using_cmdline = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001283 }
1284
1285 clear_evalarg(&evalarg, NULL);
1286
1287 if (ufunc->uf_def_status == UF_COMPILED)
1288 {
1289 // The return type will now be known.
1290 set_function_type(ufunc);
1291
1292 // The function reference count will be 1. When the ISN_FUNCREF
1293 // instruction is deleted the reference count is decremented and the
1294 // function is freed.
Bram Moolenaara915fa02022-03-23 11:29:15 +00001295 return generate_FUNCREF(cctx, ufunc, NULL);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001296 }
1297
1298 func_ptr_unref(ufunc);
1299 return FAIL;
1300}
1301
1302/*
1303 * Get a lambda and compile it. Uses Vim9 syntax.
1304 */
1305 int
1306get_lambda_tv_and_compile(
1307 char_u **arg,
1308 typval_T *rettv,
1309 int types_optional,
1310 evalarg_T *evalarg)
1311{
1312 int r;
1313 ufunc_T *ufunc;
1314 int save_sc_version = current_sctx.sc_version;
1315
1316 // Get the funcref in "rettv".
1317 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
1318 r = get_lambda_tv(arg, rettv, types_optional, evalarg);
1319 current_sctx.sc_version = save_sc_version;
1320 if (r != OK)
Bram Moolenaar7f8a3b12022-05-12 22:03:01 +01001321 return r; // currently unreachable
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001322
1323 // "rettv" will now be a partial referencing the function.
1324 ufunc = rettv->vval.v_partial->pt_func;
1325
1326 // Compile it here to get the return type. The return type is optional,
1327 // when it's missing use t_unknown. This is recognized in
1328 // compile_return().
1329 if (ufunc->uf_ret_type == NULL || ufunc->uf_ret_type->tt_type == VAR_VOID)
1330 ufunc->uf_ret_type = &t_unknown;
1331 compile_def_function(ufunc, FALSE, CT_NONE, NULL);
1332
1333 if (ufunc->uf_def_status == UF_COMPILED)
1334 {
1335 // The return type will now be known.
1336 set_function_type(ufunc);
1337 return OK;
1338 }
1339 clear_tv(rettv);
1340 return FAIL;
1341}
1342
1343/*
1344 * parse a dict: {key: val, [key]: val}
1345 * "*arg" points to the '{'.
1346 * ppconst->pp_is_const is set if all item values are a constant.
1347 */
1348 static int
1349compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1350{
1351 garray_T *instr = &cctx->ctx_instr;
1352 int count = 0;
1353 dict_T *d = dict_alloc();
1354 dictitem_T *item;
1355 char_u *whitep = *arg + 1;
1356 char_u *p;
1357 int is_const;
1358 int is_all_const = TRUE; // reset when non-const encountered
1359
1360 if (d == NULL)
1361 return FAIL;
1362 if (generate_ppconst(cctx, ppconst) == FAIL)
1363 return FAIL;
1364 for (;;)
1365 {
1366 char_u *key = NULL;
1367
1368 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1369 {
1370 *arg = NULL;
1371 goto failret;
1372 }
1373
1374 if (**arg == '}')
1375 break;
1376
1377 if (**arg == '[')
1378 {
1379 isn_T *isn;
1380
1381 // {[expr]: value} uses an evaluated key.
1382 *arg = skipwhite(*arg + 1);
1383 if (compile_expr0(arg, cctx) == FAIL)
1384 return FAIL;
1385 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
1386 if (isn->isn_type == ISN_PUSHNR)
1387 {
1388 char buf[NUMBUFLEN];
1389
1390 // Convert to string at compile time.
1391 vim_snprintf(buf, NUMBUFLEN, "%lld", isn->isn_arg.number);
1392 isn->isn_type = ISN_PUSHS;
1393 isn->isn_arg.string = vim_strsave((char_u *)buf);
1394 }
1395 if (isn->isn_type == ISN_PUSHS)
1396 key = isn->isn_arg.string;
1397 else if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1398 return FAIL;
1399 *arg = skipwhite(*arg);
1400 if (**arg != ']')
1401 {
1402 emsg(_(e_missing_matching_bracket_after_dict_key));
1403 return FAIL;
1404 }
1405 ++*arg;
1406 }
1407 else
1408 {
1409 // {"name": value},
1410 // {'name': value},
1411 // {name: value} use "name" as a literal key
1412 key = get_literal_key(arg);
1413 if (key == NULL)
1414 return FAIL;
1415 if (generate_PUSHS(cctx, &key) == FAIL)
1416 return FAIL;
1417 }
1418
1419 // Check for duplicate keys, if using string keys.
1420 if (key != NULL)
1421 {
1422 item = dict_find(d, key, -1);
1423 if (item != NULL)
1424 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001425 semsg(_(e_duplicate_key_in_dictionary_str), key);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001426 goto failret;
1427 }
1428 item = dictitem_alloc(key);
1429 if (item != NULL)
1430 {
1431 item->di_tv.v_type = VAR_UNKNOWN;
1432 item->di_tv.v_lock = 0;
1433 if (dict_add(d, item) == FAIL)
1434 dictitem_free(item);
1435 }
1436 }
1437
1438 if (**arg != ':')
1439 {
1440 if (*skipwhite(*arg) == ':')
1441 semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg);
1442 else
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001443 semsg(_(e_missing_colon_in_dictionary_str), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001444 return FAIL;
1445 }
1446 whitep = *arg + 1;
1447 if (!IS_WHITE_OR_NUL(*whitep))
1448 {
1449 semsg(_(e_white_space_required_after_str_str), ":", *arg);
1450 return FAIL;
1451 }
1452
1453 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1454 {
1455 *arg = NULL;
1456 goto failret;
1457 }
1458
1459 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL)
1460 return FAIL;
1461 if (!is_const)
1462 is_all_const = FALSE;
1463 ++count;
1464
1465 whitep = *arg;
1466 if (may_get_next_line(whitep, arg, cctx) == FAIL)
1467 {
1468 *arg = NULL;
1469 goto failret;
1470 }
1471 if (**arg == '}')
1472 break;
1473 if (**arg != ',')
1474 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001475 semsg(_(e_missing_comma_in_dictionary_str), *arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001476 goto failret;
1477 }
1478 if (IS_WHITE_OR_NUL(*whitep))
1479 {
1480 semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep);
1481 return FAIL;
1482 }
1483 whitep = *arg + 1;
1484 if (!IS_WHITE_OR_NUL(*whitep))
1485 {
1486 semsg(_(e_white_space_required_after_str_str), ",", *arg);
1487 return FAIL;
1488 }
1489 *arg = skipwhite(whitep);
1490 }
1491
1492 *arg = *arg + 1;
1493
1494 // Allow for following comment, after at least one space.
1495 p = skipwhite(*arg);
1496 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
1497 *arg += STRLEN(*arg);
1498
1499 dict_unref(d);
1500 ppconst->pp_is_const = is_all_const;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01001501 return generate_NEWDICT(cctx, count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001502
1503failret:
1504 if (*arg == NULL)
1505 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001506 semsg(_(e_missing_dict_end_str), _("[end of lines]"));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001507 *arg = (char_u *)"";
1508 }
1509 dict_unref(d);
1510 return FAIL;
1511}
1512
1513/*
1514 * Compile "&option".
1515 */
1516 static int
1517compile_get_option(char_u **arg, cctx_T *cctx)
1518{
1519 typval_T rettv;
1520 char_u *start = *arg;
1521 int ret;
1522
1523 // parse the option and get the current value to get the type.
1524 rettv.v_type = VAR_UNKNOWN;
1525 ret = eval_option(arg, &rettv, TRUE);
1526 if (ret == OK)
1527 {
1528 // include the '&' in the name, eval_option() expects it.
1529 char_u *name = vim_strnsave(start, *arg - start);
1530 type_T *type = rettv.v_type == VAR_BOOL ? &t_bool
1531 : rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
1532
1533 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
1534 vim_free(name);
1535 }
1536 clear_tv(&rettv);
1537
1538 return ret;
1539}
1540
1541/*
1542 * Compile "$VAR".
1543 */
1544 static int
1545compile_get_env(char_u **arg, cctx_T *cctx)
1546{
1547 char_u *start = *arg;
1548 int len;
1549 int ret;
1550 char_u *name;
1551
1552 ++*arg;
1553 len = get_env_len(arg);
1554 if (len == 0)
1555 {
Bram Moolenaar5f25c382022-01-09 13:36:28 +00001556 semsg(_(e_syntax_error_at_str), start);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001557 return FAIL;
1558 }
1559
1560 // include the '$' in the name, eval_env_var() expects it.
1561 name = vim_strnsave(start, len + 1);
1562 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
1563 vim_free(name);
1564 return ret;
1565}
1566
1567/*
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001568 * Compile $"string" or $'string'.
LemonBoy2eaef102022-05-06 13:14:50 +01001569 */
1570 static int
1571compile_interp_string(char_u **arg, cctx_T *cctx)
1572{
1573 typval_T tv;
1574 int ret;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001575 int quote;
LemonBoy2eaef102022-05-06 13:14:50 +01001576 int evaluate = cctx->ctx_skip != SKIP_YES;
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001577 int count = 0;
1578 char_u *p;
LemonBoy2eaef102022-05-06 13:14:50 +01001579
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001580 // *arg is on the '$' character, move it to the first string character.
1581 ++*arg;
1582 quote = **arg;
1583 ++*arg;
LemonBoy2eaef102022-05-06 13:14:50 +01001584
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001585 for (;;)
1586 {
1587 // Get the string up to the matching quote or to a single '{'.
1588 // "arg" is advanced to either the quote or the '{'.
1589 if (quote == '"')
1590 ret = eval_string(arg, &tv, evaluate, TRUE);
1591 else
1592 ret = eval_lit_string(arg, &tv, evaluate, TRUE);
1593 if (ret == FAIL)
1594 break;
1595 if (evaluate)
1596 {
1597 if ((tv.vval.v_string != NULL && *tv.vval.v_string != NUL)
1598 || (**arg != '{' && count == 0))
1599 {
1600 // generate non-empty string or empty string if it's the only
1601 // one
1602 if (generate_PUSHS(cctx, &tv.vval.v_string) == FAIL)
1603 return FAIL;
1604 tv.vval.v_string = NULL; // don't free it now
1605 ++count;
1606 }
1607 clear_tv(&tv);
1608 }
1609
1610 if (**arg != '{')
1611 {
1612 // found terminating quote
1613 ++*arg;
1614 break;
1615 }
1616
1617 p = compile_one_expr_in_str(*arg, cctx);
1618 if (p == NULL)
1619 {
1620 ret = FAIL;
1621 break;
1622 }
1623 ++count;
1624 *arg = p;
1625 }
LemonBoy2eaef102022-05-06 13:14:50 +01001626
1627 if (ret == FAIL || !evaluate)
1628 return ret;
1629
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001630 // Small optimization, if there's only a single piece skip the ISN_CONCAT.
1631 if (count > 1)
1632 return generate_CONCAT(cctx, count);
LemonBoy2eaef102022-05-06 13:14:50 +01001633
Bram Moolenaar0abc2872022-05-10 13:24:30 +01001634 return OK;
LemonBoy2eaef102022-05-06 13:14:50 +01001635}
1636
1637/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001638 * Compile "@r".
1639 */
1640 static int
1641compile_get_register(char_u **arg, cctx_T *cctx)
1642{
1643 int ret;
1644
1645 ++*arg;
1646 if (**arg == NUL)
1647 {
1648 semsg(_(e_syntax_error_at_str), *arg - 1);
1649 return FAIL;
1650 }
1651 if (!valid_yank_reg(**arg, FALSE))
1652 {
1653 emsg_invreg(**arg);
1654 return FAIL;
1655 }
1656 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
1657 ++*arg;
1658 return ret;
1659}
1660
1661/*
1662 * Apply leading '!', '-' and '+' to constant "rettv".
1663 * When "numeric_only" is TRUE do not apply '!'.
1664 */
1665 static int
1666apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
1667{
1668 char_u *p = *end;
1669
1670 // this works from end to start
1671 while (p > start)
1672 {
1673 --p;
1674 if (*p == '-' || *p == '+')
1675 {
1676 // only '-' has an effect, for '+' we only check the type
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001677 if (rettv->v_type == VAR_FLOAT)
1678 {
1679 if (*p == '-')
1680 rettv->vval.v_float = -rettv->vval.v_float;
1681 }
1682 else
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001683 {
1684 varnumber_T val;
1685 int error = FALSE;
1686
1687 // tv_get_number_chk() accepts a string, but we don't want that
1688 // here
1689 if (check_not_string(rettv) == FAIL)
1690 return FAIL;
1691 val = tv_get_number_chk(rettv, &error);
1692 clear_tv(rettv);
1693 if (error)
1694 return FAIL;
1695 if (*p == '-')
1696 val = -val;
1697 rettv->v_type = VAR_NUMBER;
1698 rettv->vval.v_number = val;
1699 }
1700 }
1701 else if (numeric_only)
1702 {
1703 ++p;
1704 break;
1705 }
1706 else if (*p == '!')
1707 {
1708 int v = tv2bool(rettv);
1709
1710 // '!' is permissive in the type.
1711 clear_tv(rettv);
1712 rettv->v_type = VAR_BOOL;
1713 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
1714 }
1715 }
1716 *end = p;
1717 return OK;
1718}
1719
1720/*
1721 * Recognize v: variables that are constants and set "rettv".
1722 */
1723 static void
1724get_vim_constant(char_u **arg, typval_T *rettv)
1725{
1726 if (STRNCMP(*arg, "v:true", 6) == 0)
1727 {
1728 rettv->v_type = VAR_BOOL;
1729 rettv->vval.v_number = VVAL_TRUE;
1730 *arg += 6;
1731 }
1732 else if (STRNCMP(*arg, "v:false", 7) == 0)
1733 {
1734 rettv->v_type = VAR_BOOL;
1735 rettv->vval.v_number = VVAL_FALSE;
1736 *arg += 7;
1737 }
1738 else if (STRNCMP(*arg, "v:null", 6) == 0)
1739 {
1740 rettv->v_type = VAR_SPECIAL;
1741 rettv->vval.v_number = VVAL_NULL;
1742 *arg += 6;
1743 }
1744 else if (STRNCMP(*arg, "v:none", 6) == 0)
1745 {
1746 rettv->v_type = VAR_SPECIAL;
1747 rettv->vval.v_number = VVAL_NONE;
1748 *arg += 6;
1749 }
1750}
1751
1752 exprtype_T
1753get_compare_type(char_u *p, int *len, int *type_is)
1754{
1755 exprtype_T type = EXPR_UNKNOWN;
1756 int i;
1757
1758 switch (p[0])
1759 {
1760 case '=': if (p[1] == '=')
1761 type = EXPR_EQUAL;
1762 else if (p[1] == '~')
1763 type = EXPR_MATCH;
1764 break;
1765 case '!': if (p[1] == '=')
1766 type = EXPR_NEQUAL;
1767 else if (p[1] == '~')
1768 type = EXPR_NOMATCH;
1769 break;
1770 case '>': if (p[1] != '=')
1771 {
1772 type = EXPR_GREATER;
1773 *len = 1;
1774 }
1775 else
1776 type = EXPR_GEQUAL;
1777 break;
1778 case '<': if (p[1] != '=')
1779 {
1780 type = EXPR_SMALLER;
1781 *len = 1;
1782 }
1783 else
1784 type = EXPR_SEQUAL;
1785 break;
1786 case 'i': if (p[1] == 's')
1787 {
1788 // "is" and "isnot"; but not a prefix of a name
1789 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
1790 *len = 5;
1791 i = p[*len];
1792 if (!isalnum(i) && i != '_')
1793 {
1794 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
1795 *type_is = TRUE;
1796 }
1797 }
1798 break;
1799 }
1800 return type;
1801}
1802
1803/*
1804 * Skip over an expression, ignoring most errors.
1805 */
1806 void
1807skip_expr_cctx(char_u **arg, cctx_T *cctx)
1808{
1809 evalarg_T evalarg;
1810
1811 init_evalarg(&evalarg);
1812 evalarg.eval_cctx = cctx;
1813 skip_expr(arg, &evalarg);
1814 clear_evalarg(&evalarg, NULL);
1815}
1816
1817/*
1818 * Check that the top of the type stack has a type that can be used as a
1819 * condition. Give an error and return FAIL if not.
1820 */
1821 int
1822bool_on_stack(cctx_T *cctx)
1823{
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001824 type_T *type;
1825
Bram Moolenaar078a4612022-01-04 15:17:03 +00001826 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001827 if (type == &t_bool)
1828 return OK;
1829
Bram Moolenaar4913d422022-10-17 13:13:32 +01001830 if (type->tt_type == VAR_ANY
1831 || type->tt_type == VAR_UNKNOWN
1832 || type->tt_type == VAR_NUMBER
1833 || type == &t_number_bool
1834 || type == &t_const_number_bool)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001835 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
1836 // This requires a runtime type check.
1837 return generate_COND2BOOL(cctx);
1838
Bram Moolenaarc6951a72022-12-29 20:56:24 +00001839 return need_type(type, &t_bool, FALSE, -1, 0, cctx, FALSE, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001840}
1841
1842/*
1843 * Give the "white on both sides" error, taking the operator from "p[len]".
1844 */
1845 void
1846error_white_both(char_u *op, int len)
1847{
1848 char_u buf[10];
1849
1850 vim_strncpy(buf, op, len);
1851 semsg(_(e_white_space_required_before_and_after_str_at_str), buf, op);
1852}
1853
1854/*
1855 * Compile code to apply '-', '+' and '!'.
1856 * When "numeric_only" is TRUE do not apply '!'.
1857 */
1858 static int
1859compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
1860{
1861 char_u *p = *end;
1862
1863 // this works from end to start
1864 while (p > start)
1865 {
1866 --p;
1867 while (VIM_ISWHITE(*p))
1868 --p;
1869 if (*p == '-' || *p == '+')
1870 {
Bram Moolenaar73ade492022-12-27 20:54:41 +00001871 type_T *type = get_type_on_stack(cctx, 0);
1872 if (type->tt_type != VAR_FLOAT && need_type(type, &t_number,
Bram Moolenaarc6951a72022-12-29 20:56:24 +00001873 FALSE, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001874 return FAIL;
1875
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001876 // only '-' has an effect, for '+' we only check the type
Bram Moolenaar73ade492022-12-27 20:54:41 +00001877 if (*p == '-' && generate_instr(cctx, ISN_NEGATENR) == NULL)
1878 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001879 }
1880 else if (numeric_only)
1881 {
1882 ++p;
1883 break;
1884 }
1885 else
1886 {
1887 int invert = *p == '!';
1888
1889 while (p > start && (p[-1] == '!' || VIM_ISWHITE(p[-1])))
1890 {
1891 if (p[-1] == '!')
1892 invert = !invert;
1893 --p;
1894 }
1895 if (generate_2BOOL(cctx, invert, -1) == FAIL)
1896 return FAIL;
1897 }
1898 }
1899 *end = p;
1900 return OK;
1901}
1902
1903/*
1904 * Compile "(expression)": recursive!
1905 * Return FAIL/OK.
1906 */
1907 static int
1908compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
1909{
1910 int ret;
1911 char_u *p = *arg + 1;
1912
1913 if (may_get_next_line_error(p, arg, cctx) == FAIL)
1914 return FAIL;
1915 if (ppconst->pp_used <= PPSIZE - 10)
1916 {
1917 ret = compile_expr1(arg, cctx, ppconst);
1918 }
1919 else
1920 {
1921 // Not enough space in ppconst, flush constants.
1922 if (generate_ppconst(cctx, ppconst) == FAIL)
1923 return FAIL;
1924 ret = compile_expr0(arg, cctx);
1925 }
1926 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
1927 return FAIL;
1928 if (**arg == ')')
1929 ++*arg;
1930 else if (ret == OK)
1931 {
1932 emsg(_(e_missing_closing_paren));
1933 ret = FAIL;
1934 }
1935 return ret;
1936}
1937
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01001938static int compile_expr9(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
Bram Moolenaarc7349932022-01-16 20:59:39 +00001939
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001940/*
1941 * Compile whatever comes after "name" or "name()".
1942 * Advances "*arg" only when something was recognized.
1943 */
1944 static int
1945compile_subscript(
1946 char_u **arg,
1947 cctx_T *cctx,
1948 char_u *start_leader,
1949 char_u **end_leader,
1950 ppconst_T *ppconst)
1951{
1952 char_u *name_start = *end_leader;
1953 int keeping_dict = FALSE;
1954
1955 for (;;)
1956 {
1957 char_u *p = skipwhite(*arg);
Bram Moolenaarffdaca92022-12-09 21:41:48 +00001958 type_T *type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001959
1960 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
1961 {
1962 char_u *next = peek_next_line_from_context(cctx);
1963
Bram Moolenaard0fbb412022-10-19 18:04:49 +01001964 // If a following line starts with "->{", "->(" or "->X" advance to
1965 // that line, so that a line break before "->" is allowed.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001966 // Also if a following line starts with ".x".
1967 if (next != NULL &&
1968 ((next[0] == '-' && next[1] == '>'
1969 && (next[2] == '{'
Bram Moolenaard0fbb412022-10-19 18:04:49 +01001970 || next[2] == '('
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001971 || ASCII_ISALPHA(*skipwhite(next + 2))))
1972 || (next[0] == '.' && eval_isdictc(next[1]))))
1973 {
1974 next = next_line_from_context(cctx, TRUE);
1975 if (next == NULL)
1976 return FAIL;
1977 *arg = next;
1978 p = skipwhite(*arg);
1979 }
1980 }
1981
1982 // Do not skip over white space to find the "(", "execute 'x' (expr)"
1983 // is not a function call.
1984 if (**arg == '(')
1985 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001986 int argcount = 0;
1987
1988 if (generate_ppconst(cctx, ppconst) == FAIL)
1989 return FAIL;
1990 ppconst->pp_is_const = FALSE;
1991
1992 // funcref(arg)
Bram Moolenaar078a4612022-01-04 15:17:03 +00001993 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001994
1995 *arg = skipwhite(p + 1);
LemonBoyf3b48952022-05-05 13:53:03 +01001996 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001997 return FAIL;
1998 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
1999 return FAIL;
2000 if (keeping_dict)
2001 {
2002 keeping_dict = FALSE;
2003 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
2004 return FAIL;
2005 }
2006 }
2007 else if (*p == '-' && p[1] == '>')
2008 {
Bram Moolenaarc7349932022-01-16 20:59:39 +00002009 char_u *pstart = p;
2010 int alt;
2011 char_u *paren;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002012
Bram Moolenaarc7349932022-01-16 20:59:39 +00002013 // something->method()
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002014 if (generate_ppconst(cctx, ppconst) == FAIL)
2015 return FAIL;
2016 ppconst->pp_is_const = FALSE;
2017
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002018 // Apply the '!', '-' and '+' first:
2019 // -1.0->func() works like (-1.0)->func()
2020 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
2021 return FAIL;
2022
2023 p += 2;
2024 *arg = skipwhite(p);
2025 // No line break supported right after "->".
Bram Moolenaarc7349932022-01-16 20:59:39 +00002026
2027 // Three alternatives handled here:
2028 // 1. "base->name(" only a name, use compile_call()
2029 // 2. "base->(expr)(" evaluate "expr", then use PCALL
2030 // 3. "base->expr(" Same, find the end of "expr" by "("
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002031 if (**arg == '(')
Bram Moolenaarc7349932022-01-16 20:59:39 +00002032 alt = 2;
2033 else
2034 {
2035 // alternative 1 or 3
2036 p = *arg;
2037 if (!eval_isnamec1(*p))
2038 {
2039 semsg(_(e_trailing_characters_str), pstart);
2040 return FAIL;
2041 }
2042 if (ASCII_ISALPHA(*p) && p[1] == ':')
2043 p += 2;
2044 for ( ; eval_isnamec(*p); ++p)
2045 ;
2046 if (*p == '(')
2047 {
2048 // alternative 1
2049 alt = 1;
2050 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
2051 return FAIL;
2052 }
2053 else
2054 {
2055 // Must be alternative 3, find the "(". Only works within
2056 // one line.
2057 alt = 3;
2058 paren = vim_strchr(p, '(');
2059 if (paren == NULL)
2060 {
2061 semsg(_(e_missing_parenthesis_str), *arg);
2062 return FAIL;
2063 }
2064 }
2065 }
2066
2067 if (alt != 1)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002068 {
2069 int argcount = 1;
2070 garray_T *stack = &cctx->ctx_type_stack;
2071 int type_idx_start = stack->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002072 int expr_isn_start = cctx->ctx_instr.ga_len;
2073 int expr_isn_end;
2074 int arg_isn_count;
2075
Bram Moolenaarc7349932022-01-16 20:59:39 +00002076 if (alt == 2)
2077 {
2078 // Funcref call: list->(Refs[2])(arg)
2079 // or lambda: list->((arg) => expr)(arg)
2080 //
2081 // Fist compile the function expression.
2082 if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
2083 return FAIL;
2084 }
2085 else
2086 {
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002087 int fail;
2088 int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
Bram Moolenaar31ad32a2022-05-13 16:23:37 +01002089 int prev_did_emsg = did_emsg;
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002090
Bram Moolenaarc7349932022-01-16 20:59:39 +00002091 *paren = NUL;
Bram Moolenaard02dce22022-01-18 17:43:04 +00002092
2093 // instead of using LOADG for "import.Func" use PUSHFUNC
2094 ++paren_follows_after_expr;
2095
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002096 // do not look in the next line
2097 cctx->ctx_ufunc->uf_lines.ga_len = 1;
Bram Moolenaard02dce22022-01-18 17:43:04 +00002098
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002099 fail = compile_expr9(arg, cctx, ppconst) == FAIL
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002100 || *skipwhite(*arg) != NUL;
2101 *paren = '(';
Bram Moolenaard02dce22022-01-18 17:43:04 +00002102 --paren_follows_after_expr;
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002103 cctx->ctx_ufunc->uf_lines.ga_len = save_len;
Bram Moolenaard02dce22022-01-18 17:43:04 +00002104
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002105 if (fail)
Bram Moolenaarc7349932022-01-16 20:59:39 +00002106 {
Bram Moolenaar31ad32a2022-05-13 16:23:37 +01002107 if (did_emsg == prev_did_emsg)
2108 semsg(_(e_invalid_expression_str), pstart);
Bram Moolenaarc7349932022-01-16 20:59:39 +00002109 return FAIL;
2110 }
Bram Moolenaarc7349932022-01-16 20:59:39 +00002111 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002112
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002113 // Compile the arguments.
2114 if (**arg != '(')
2115 {
2116 if (*skipwhite(*arg) == '(')
Bram Moolenaar3a846e62022-01-01 16:21:00 +00002117 emsg(_(e_no_white_space_allowed_before_parenthesis));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002118 else
2119 semsg(_(e_missing_parenthesis_str), *arg);
2120 return FAIL;
2121 }
Bram Moolenaar6389baa2022-01-17 20:50:40 +00002122
2123 // Remember the next instruction index, where the instructions
2124 // for arguments are being written.
2125 expr_isn_end = cctx->ctx_instr.ga_len;
2126
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002127 *arg = skipwhite(*arg + 1);
LemonBoyf3b48952022-05-05 13:53:03 +01002128 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL)
2129 == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002130 return FAIL;
2131
2132 // Move the instructions for the arguments to before the
2133 // instructions of the expression and move the type of the
2134 // expression after the argument types. This is what ISN_PCALL
2135 // expects.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002136 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
2137 if (arg_isn_count > 0)
2138 {
2139 int expr_isn_count = expr_isn_end - expr_isn_start;
2140 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count);
Bram Moolenaar078a4612022-01-04 15:17:03 +00002141 type_T *decl_type;
2142 type2_T *typep;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002143
2144 if (isn == NULL)
2145 return FAIL;
2146 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
2147 + expr_isn_start,
2148 sizeof(isn_T) * expr_isn_count);
2149 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
2150 + expr_isn_start,
2151 ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end,
2152 sizeof(isn_T) * arg_isn_count);
2153 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
2154 + expr_isn_start + arg_isn_count,
2155 isn, sizeof(isn_T) * expr_isn_count);
2156 vim_free(isn);
2157
Bram Moolenaar078a4612022-01-04 15:17:03 +00002158 typep = ((type2_T *)stack->ga_data) + type_idx_start;
2159 type = typep->type_curr;
2160 decl_type = typep->type_decl;
2161 mch_memmove(((type2_T *)stack->ga_data) + type_idx_start,
2162 ((type2_T *)stack->ga_data) + type_idx_start + 1,
2163 sizeof(type2_T)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002164 * (stack->ga_len - type_idx_start - 1));
Bram Moolenaar078a4612022-01-04 15:17:03 +00002165 typep = ((type2_T *)stack->ga_data) + stack->ga_len - 1;
2166 typep->type_curr = type;
2167 typep->type_decl = decl_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002168 }
2169
Bram Moolenaar078a4612022-01-04 15:17:03 +00002170 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002171 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
2172 return FAIL;
2173 }
Bram Moolenaarc7349932022-01-16 20:59:39 +00002174
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002175 if (keeping_dict)
2176 {
2177 keeping_dict = FALSE;
2178 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
2179 return FAIL;
2180 }
2181 }
2182 else if (**arg == '[')
2183 {
2184 int is_slice = FALSE;
2185
2186 // list index: list[123]
2187 // dict member: dict[key]
2188 // string index: text[123]
2189 // blob index: blob[123]
2190 if (generate_ppconst(cctx, ppconst) == FAIL)
2191 return FAIL;
2192 ppconst->pp_is_const = FALSE;
2193
2194 ++p;
2195 if (may_get_next_line_error(p, arg, cctx) == FAIL)
2196 return FAIL;
2197 if (**arg == ':')
2198 {
2199 // missing first index is equal to zero
2200 generate_PUSHNR(cctx, 0);
2201 }
2202 else
2203 {
2204 if (compile_expr0(arg, cctx) == FAIL)
2205 return FAIL;
2206 if (**arg == ':')
2207 {
2208 semsg(_(e_white_space_required_before_and_after_str_at_str),
2209 ":", *arg);
2210 return FAIL;
2211 }
2212 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2213 return FAIL;
2214 *arg = skipwhite(*arg);
2215 }
2216 if (**arg == ':')
2217 {
2218 is_slice = TRUE;
2219 ++*arg;
2220 if (!IS_WHITE_OR_NUL(**arg) && **arg != ']')
2221 {
2222 semsg(_(e_white_space_required_before_and_after_str_at_str),
2223 ":", *arg);
2224 return FAIL;
2225 }
2226 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2227 return FAIL;
2228 if (**arg == ']')
2229 // missing second index is equal to end of string
2230 generate_PUSHNR(cctx, -1);
2231 else
2232 {
2233 if (compile_expr0(arg, cctx) == FAIL)
2234 return FAIL;
2235 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2236 return FAIL;
2237 *arg = skipwhite(*arg);
2238 }
2239 }
2240
2241 if (**arg != ']')
2242 {
2243 emsg(_(e_missing_closing_square_brace));
2244 return FAIL;
2245 }
2246 *arg = *arg + 1;
2247
2248 if (keeping_dict)
2249 {
2250 keeping_dict = FALSE;
2251 if (generate_instr(cctx, ISN_CLEARDICT) == NULL)
2252 return FAIL;
2253 }
2254 if (compile_member(is_slice, &keeping_dict, cctx) == FAIL)
2255 return FAIL;
2256 }
2257 else if (*p == '.' && p[1] != '.')
2258 {
2259 // dictionary member: dict.name
2260 if (generate_ppconst(cctx, ppconst) == FAIL)
2261 return FAIL;
2262 ppconst->pp_is_const = FALSE;
2263
Bram Moolenaar912bfee2023-01-15 20:18:55 +00002264 if ((type = get_type_on_stack(cctx, 0)) != &t_unknown
2265 && (type->tt_type == VAR_CLASS
2266 || type->tt_type == VAR_OBJECT))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002267 {
Bram Moolenaar912bfee2023-01-15 20:18:55 +00002268 // class member: SomeClass.varname
2269 // class method: SomeClass.SomeMethod()
2270 // class constructor: SomeClass.new()
2271 // object member: someObject.varname, this.varname
2272 // object method: someObject.SomeMethod(), this.SomeMethod()
2273 *arg = p;
2274 if (compile_class_object_index(cctx, arg, type) == FAIL)
2275 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002276 }
Bram Moolenaar912bfee2023-01-15 20:18:55 +00002277 else
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002278 {
Bram Moolenaar912bfee2023-01-15 20:18:55 +00002279 *arg = p + 1;
2280 if (IS_WHITE_OR_NUL(**arg))
2281 {
2282 emsg(_(e_missing_name_after_dot));
2283 return FAIL;
2284 }
2285 p = *arg;
2286 if (eval_isdictc(*p))
2287 while (eval_isnamec(*p))
2288 MB_PTR_ADV(p);
2289 if (p == *arg)
2290 {
2291 semsg(_(e_syntax_error_at_str), *arg);
2292 return FAIL;
2293 }
2294 if (keeping_dict && generate_instr(cctx, ISN_CLEARDICT) == NULL)
2295 return FAIL;
2296 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
2297 return FAIL;
2298 keeping_dict = TRUE;
2299 *arg = p;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002300 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002301 }
2302 else
2303 break;
2304 }
2305
2306 // Turn "dict.Func" into a partial for "Func" bound to "dict".
2307 // This needs to be done at runtime to be able to check the type.
Bram Moolenaar1ff9c442022-05-17 15:03:33 +01002308 if (keeping_dict && cctx->ctx_skip != SKIP_YES
2309 && generate_instr(cctx, ISN_USEDICT) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002310 return FAIL;
2311
2312 return OK;
2313}
2314
2315/*
2316 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
2317 * "arg" is advanced until after the expression, skipping white space.
2318 *
2319 * If the value is a constant "ppconst->pp_used" will be non-zero.
2320 * Before instructions are generated, any values in "ppconst" will generated.
2321 *
2322 * This is the compiling equivalent of eval1(), eval2(), etc.
2323 */
2324
2325/*
2326 * number number constant
2327 * 0zFFFFFFFF Blob constant
2328 * "string" string constant
2329 * 'string' literal string constant
2330 * &option-name option value
2331 * @r register contents
2332 * identifier variable value
2333 * function() function call
2334 * $VAR environment variable
2335 * (expression) nested expression
2336 * [expr, expr] List
2337 * {key: val, [key]: val} Dictionary
2338 *
2339 * Also handle:
2340 * ! in front logical NOT
2341 * - in front unary minus
2342 * + in front unary plus (ignored)
2343 * trailing (arg) funcref/partial call
2344 * trailing [] subscript in String or List
2345 * trailing .name entry in Dictionary
2346 * trailing ->name() method call
2347 */
2348 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002349compile_expr9(
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002350 char_u **arg,
2351 cctx_T *cctx,
2352 ppconst_T *ppconst)
2353{
2354 char_u *start_leader, *end_leader;
2355 int ret = OK;
2356 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
2357 int used_before = ppconst->pp_used;
2358
2359 ppconst->pp_is_const = FALSE;
2360
2361 /*
2362 * Skip '!', '-' and '+' characters. They are handled later.
2363 */
2364 start_leader = *arg;
2365 if (eval_leader(arg, TRUE) == FAIL)
2366 return FAIL;
2367 end_leader = *arg;
2368
2369 rettv->v_type = VAR_UNKNOWN;
2370 switch (**arg)
2371 {
2372 /*
2373 * Number constant.
2374 */
2375 case '0': // also for blob starting with 0z
2376 case '1':
2377 case '2':
2378 case '3':
2379 case '4':
2380 case '5':
2381 case '6':
2382 case '7':
2383 case '8':
2384 case '9':
2385 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
2386 return FAIL;
2387 // Apply "-" and "+" just before the number now, right to
2388 // left. Matters especially when "->" follows. Stops at
2389 // '!'.
2390 if (apply_leader(rettv, TRUE,
2391 start_leader, &end_leader) == FAIL)
2392 {
2393 clear_tv(rettv);
2394 return FAIL;
2395 }
2396 break;
2397
2398 /*
2399 * String constant: "string".
2400 */
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002401 case '"': if (eval_string(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002402 return FAIL;
2403 break;
2404
2405 /*
2406 * Literal string constant: 'str''ing'.
2407 */
Bram Moolenaar0abc2872022-05-10 13:24:30 +01002408 case '\'': if (eval_lit_string(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002409 return FAIL;
2410 break;
2411
2412 /*
2413 * Constant Vim variable.
2414 */
2415 case 'v': get_vim_constant(arg, rettv);
2416 ret = NOTDONE;
2417 break;
2418
2419 /*
2420 * "true" constant
2421 */
2422 case 't': if (STRNCMP(*arg, "true", 4) == 0
2423 && !eval_isnamec((*arg)[4]))
2424 {
2425 *arg += 4;
2426 rettv->v_type = VAR_BOOL;
2427 rettv->vval.v_number = VVAL_TRUE;
2428 }
2429 else
2430 ret = NOTDONE;
2431 break;
2432
2433 /*
2434 * "false" constant
2435 */
2436 case 'f': if (STRNCMP(*arg, "false", 5) == 0
2437 && !eval_isnamec((*arg)[5]))
2438 {
2439 *arg += 5;
2440 rettv->v_type = VAR_BOOL;
2441 rettv->vval.v_number = VVAL_FALSE;
2442 }
2443 else
2444 ret = NOTDONE;
2445 break;
2446
2447 /*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00002448 * "null" or "null_*" constant
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002449 */
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00002450 case 'n': if (STRNCMP(*arg, "null", 4) == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002451 {
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00002452 char_u *p = *arg + 4;
2453 int len;
2454
2455 for (len = 0; eval_isnamec(p[len]); ++len)
2456 ;
2457 ret = handle_predefined(*arg, len + 4, rettv);
2458 if (ret == FAIL)
2459 ret = NOTDONE;
2460 else
2461 *arg += len + 4;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002462 }
2463 else
2464 ret = NOTDONE;
2465 break;
2466
2467 /*
2468 * List: [expr, expr]
2469 */
2470 case '[': if (generate_ppconst(cctx, ppconst) == FAIL)
2471 return FAIL;
2472 ret = compile_list(arg, cctx, ppconst);
2473 break;
2474
2475 /*
2476 * Dictionary: {'key': val, 'key': val}
2477 */
2478 case '{': if (generate_ppconst(cctx, ppconst) == FAIL)
2479 return FAIL;
2480 ret = compile_dict(arg, cctx, ppconst);
2481 break;
2482
2483 /*
2484 * Option value: &name
2485 */
2486 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
2487 return FAIL;
2488 ret = compile_get_option(arg, cctx);
2489 break;
2490
2491 /*
2492 * Environment variable: $VAR.
LemonBoy2eaef102022-05-06 13:14:50 +01002493 * Interpolated string: $"string" or $'string'.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002494 */
2495 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
2496 return FAIL;
LemonBoy2eaef102022-05-06 13:14:50 +01002497 if ((*arg)[1] == '"' || (*arg)[1] == '\'')
2498 ret = compile_interp_string(arg, cctx);
2499 else
2500 ret = compile_get_env(arg, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002501 break;
2502
2503 /*
2504 * Register contents: @r.
2505 */
2506 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
2507 return FAIL;
2508 ret = compile_get_register(arg, cctx);
2509 break;
2510 /*
2511 * nested expression: (expression).
2512 * lambda: (arg, arg) => expr
2513 * funcref: (arg, arg) => { statement }
2514 */
2515 case '(': // if compile_lambda returns NOTDONE then it must be (expr)
2516 ret = compile_lambda(arg, cctx);
2517 if (ret == NOTDONE)
2518 ret = compile_parenthesis(arg, cctx, ppconst);
2519 break;
2520
2521 default: ret = NOTDONE;
2522 break;
2523 }
2524 if (ret == FAIL)
2525 return FAIL;
2526
2527 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
2528 {
2529 if (cctx->ctx_skip == SKIP_YES)
2530 clear_tv(rettv);
2531 else
2532 // A constant expression can possibly be handled compile time,
2533 // return the value instead of generating code.
2534 ++ppconst->pp_used;
2535 }
2536 else if (ret == NOTDONE)
2537 {
2538 char_u *p;
2539 int r;
2540
2541 if (!eval_isnamec1(**arg))
2542 {
2543 if (!vim9_bad_comment(*arg))
2544 {
2545 if (ends_excmd(*skipwhite(*arg)))
2546 semsg(_(e_empty_expression_str), *arg);
2547 else
2548 semsg(_(e_name_expected_str), *arg);
2549 }
2550 return FAIL;
2551 }
2552
2553 // "name" or "name()"
2554 p = to_name_end(*arg, TRUE);
2555 if (p - *arg == (size_t)1 && **arg == '_')
2556 {
2557 emsg(_(e_cannot_use_underscore_here));
2558 return FAIL;
2559 }
2560
2561 if (*p == '(')
2562 {
2563 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
2564 }
2565 else
2566 {
2567 if (cctx->ctx_skip != SKIP_YES
2568 && generate_ppconst(cctx, ppconst) == FAIL)
2569 return FAIL;
2570 r = compile_load(arg, p, cctx, TRUE, TRUE);
2571 }
2572 if (r == FAIL)
2573 return FAIL;
2574 }
2575
2576 // Handle following "[]", ".member", etc.
2577 // Then deal with prefixed '-', '+' and '!', if not done already.
2578 if (compile_subscript(arg, cctx, start_leader, &end_leader,
2579 ppconst) == FAIL)
2580 return FAIL;
2581 if (ppconst->pp_used > 0)
2582 {
2583 // apply the '!', '-' and '+' before the constant
2584 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
2585 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
2586 return FAIL;
2587 return OK;
2588 }
2589 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
2590 return FAIL;
2591 return OK;
2592}
2593
2594/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002595 * <type>expr9: runtime type check / conversion
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002596 */
2597 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002598compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002599{
2600 type_T *want_type = NULL;
2601
2602 // Recognize <type>
2603 if (**arg == '<' && eval_isnamec1((*arg)[1]))
2604 {
2605 ++*arg;
2606 want_type = parse_type(arg, cctx->ctx_type_list, TRUE);
2607 if (want_type == NULL)
2608 return FAIL;
2609
2610 if (**arg != '>')
2611 {
2612 if (*skipwhite(*arg) == '>')
2613 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
2614 else
2615 emsg(_(e_missing_gt));
2616 return FAIL;
2617 }
2618 ++*arg;
2619 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
2620 return FAIL;
2621 }
2622
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002623 if (compile_expr9(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002624 return FAIL;
2625
2626 if (want_type != NULL)
2627 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002628 type_T *actual;
2629 where_T where = WHERE_INIT;
2630
2631 generate_ppconst(cctx, ppconst);
Bram Moolenaar078a4612022-01-04 15:17:03 +00002632 actual = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +00002633 if (check_type_maybe(want_type, actual, FALSE, where) != OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002634 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002635 if (need_type(actual, want_type, FALSE,
2636 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002637 return FAIL;
2638 }
2639 }
2640
2641 return OK;
2642}
2643
2644/*
2645 * * number multiplication
2646 * / number division
2647 * % number modulo
2648 */
2649 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002650compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002651{
2652 char_u *op;
2653 char_u *next;
2654 int ppconst_used = ppconst->pp_used;
2655
2656 // get the first expression
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002657 if (compile_expr8(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002658 return FAIL;
2659
2660 /*
2661 * Repeat computing, until no "*", "/" or "%" is following.
2662 */
2663 for (;;)
2664 {
2665 op = may_peek_next_line(cctx, *arg, &next);
2666 if (*op != '*' && *op != '/' && *op != '%')
2667 break;
2668 if (next != NULL)
2669 {
2670 *arg = next_line_from_context(cctx, TRUE);
2671 op = skipwhite(*arg);
2672 }
2673
2674 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
2675 {
2676 error_white_both(op, 1);
2677 return FAIL;
2678 }
2679 if (may_get_next_line_error(op + 1, arg, cctx) == FAIL)
2680 return FAIL;
2681
2682 // get the second expression
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002683 if (compile_expr8(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002684 return FAIL;
2685
2686 if (ppconst->pp_used == ppconst_used + 2
2687 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
2688 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
2689 {
2690 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
2691 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
2692 varnumber_T res = 0;
2693 int failed = FALSE;
2694
2695 // both are numbers: compute the result
2696 switch (*op)
2697 {
2698 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
2699 break;
2700 case '/': res = num_divide(tv1->vval.v_number,
2701 tv2->vval.v_number, &failed);
2702 break;
2703 case '%': res = num_modulus(tv1->vval.v_number,
2704 tv2->vval.v_number, &failed);
2705 break;
2706 }
2707 if (failed)
2708 return FAIL;
2709 tv1->vval.v_number = res;
2710 --ppconst->pp_used;
2711 }
2712 else
2713 {
2714 generate_ppconst(cctx, ppconst);
2715 generate_two_op(cctx, op);
2716 }
2717 }
2718
2719 return OK;
2720}
2721
2722/*
2723 * + number addition or list/blobl concatenation
2724 * - number subtraction
2725 * .. string concatenation
2726 */
2727 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002728compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002729{
2730 char_u *op;
2731 char_u *next;
2732 int oplen;
2733 int ppconst_used = ppconst->pp_used;
2734
2735 // get the first variable
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002736 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002737 return FAIL;
2738
2739 /*
2740 * Repeat computing, until no "+", "-" or ".." is following.
2741 */
2742 for (;;)
2743 {
2744 op = may_peek_next_line(cctx, *arg, &next);
2745 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
2746 break;
2747 if (op[0] == op[1] && *op != '.' && next)
2748 // Finding "++" or "--" on the next line is a separate command.
2749 // But ".." is concatenation.
2750 break;
2751 oplen = (*op == '.' ? 2 : 1);
2752 if (next != NULL)
2753 {
2754 *arg = next_line_from_context(cctx, TRUE);
2755 op = skipwhite(*arg);
2756 }
2757
2758 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
2759 {
2760 error_white_both(op, oplen);
2761 return FAIL;
2762 }
2763
2764 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL)
2765 return FAIL;
2766
2767 // get the second expression
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002768 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002769 return FAIL;
2770
2771 if (ppconst->pp_used == ppconst_used + 2
2772 && (*op == '.'
2773 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
2774 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
2775 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
2776 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
2777 {
2778 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
2779 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
2780
2781 // concat/subtract/add constant numbers
2782 if (*op == '+')
2783 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
2784 else if (*op == '-')
2785 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
2786 else
2787 {
2788 // concatenate constant strings
2789 char_u *s1 = tv1->vval.v_string;
2790 char_u *s2 = tv2->vval.v_string;
2791 size_t len1 = STRLEN(s1);
2792
2793 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
2794 if (tv1->vval.v_string == NULL)
2795 {
2796 clear_ppconst(ppconst);
2797 return FAIL;
2798 }
2799 mch_memmove(tv1->vval.v_string, s1, len1);
2800 STRCPY(tv1->vval.v_string + len1, s2);
2801 vim_free(s1);
2802 vim_free(s2);
2803 }
2804 --ppconst->pp_used;
2805 }
2806 else
2807 {
2808 generate_ppconst(cctx, ppconst);
2809 ppconst->pp_is_const = FALSE;
2810 if (*op == '.')
2811 {
2812 if (may_generate_2STRING(-2, FALSE, cctx) == FAIL
2813 || may_generate_2STRING(-1, FALSE, cctx) == FAIL)
2814 return FAIL;
LemonBoy372bcce2022-04-25 12:43:20 +01002815 if (generate_CONCAT(cctx, 2) == FAIL)
2816 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002817 }
2818 else
2819 generate_two_op(cctx, op);
2820 }
2821 }
2822
2823 return OK;
2824}
2825
2826/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002827 * expr6a >> expr6b
2828 * expr6a << expr6b
2829 *
2830 * Produces instructions:
2831 * OPNR bitwise left or right shift
2832 */
2833 static int
2834compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2835{
2836 exprtype_T type = EXPR_UNKNOWN;
2837 char_u *p;
2838 char_u *next;
2839 int len = 2;
2840 int ppconst_used = ppconst->pp_used;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002841 isn_T *isn;
2842
2843 // get the first variable
2844 if (compile_expr6(arg, cctx, ppconst) == FAIL)
2845 return FAIL;
2846
2847 /*
2848 * Repeat computing, until no "+", "-" or ".." is following.
2849 */
2850 for (;;)
2851 {
2852 type = EXPR_UNKNOWN;
2853
2854 p = may_peek_next_line(cctx, *arg, &next);
2855 if (p[0] == '<' && p[1] == '<')
2856 type = EXPR_LSHIFT;
2857 else if (p[0] == '>' && p[1] == '>')
2858 type = EXPR_RSHIFT;
2859
2860 if (type == EXPR_UNKNOWN)
2861 return OK;
2862
2863 // Handle a bitwise left or right shift operator
2864 if (ppconst->pp_used == ppconst_used + 1)
2865 {
Bram Moolenaar5b529232022-05-22 21:53:26 +01002866 if (ppconst->pp_tv[ppconst->pp_used - 1].v_type != VAR_NUMBER)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002867 {
2868 // left operand should be a number
2869 emsg(_(e_bitshift_ops_must_be_number));
2870 return FAIL;
2871 }
2872 }
2873 else
2874 {
2875 type_T *t = get_type_on_stack(cctx, 0);
2876
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002877 if (need_type(t, &t_number, FALSE, 0, 0, cctx, FALSE, FALSE) == FAIL)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002878 {
2879 emsg(_(e_bitshift_ops_must_be_number));
2880 return FAIL;
2881 }
2882 }
2883
2884 if (next != NULL)
2885 {
2886 *arg = next_line_from_context(cctx, TRUE);
2887 p = skipwhite(*arg);
2888 }
2889
2890 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
2891 {
2892 error_white_both(p, len);
2893 return FAIL;
2894 }
2895
2896 // get the second variable
2897 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
2898 return FAIL;
2899
2900 if (compile_expr6(arg, cctx, ppconst) == FAIL)
2901 return FAIL;
2902
2903 if (ppconst->pp_used == ppconst_used + 2)
2904 {
Bram Moolenaar5b529232022-05-22 21:53:26 +01002905 typval_T *tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
2906 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
2907
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002908 // Both sides are a constant, compute the result now.
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002909 if (tv2->v_type != VAR_NUMBER || tv2->vval.v_number < 0)
2910 {
2911 // right operand should be a positive number
2912 if (tv2->v_type != VAR_NUMBER)
2913 emsg(_(e_bitshift_ops_must_be_number));
2914 else
dundargocc57b5bc2022-11-02 13:30:51 +00002915 emsg(_(e_bitshift_ops_must_be_positive));
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002916 return FAIL;
2917 }
2918
2919 if (tv2->vval.v_number > MAX_LSHIFT_BITS)
2920 tv1->vval.v_number = 0;
2921 else if (type == EXPR_LSHIFT)
Bram Moolenaar68e64d22022-05-22 22:07:52 +01002922 tv1->vval.v_number =
2923 (uvarnumber_T)tv1->vval.v_number << tv2->vval.v_number;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002924 else
Bram Moolenaar338bf582022-05-22 20:16:32 +01002925 tv1->vval.v_number =
2926 (uvarnumber_T)tv1->vval.v_number >> tv2->vval.v_number;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002927 clear_tv(tv2);
2928 --ppconst->pp_used;
2929 }
2930 else
2931 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002932 if (need_type(get_type_on_stack(cctx, 0), &t_number, FALSE,
2933 0, 0, cctx, FALSE, FALSE) == FAIL)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002934 {
2935 emsg(_(e_bitshift_ops_must_be_number));
2936 return FAIL;
2937 }
2938
2939 generate_ppconst(cctx, ppconst);
2940
2941 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
2942 if (isn == NULL)
2943 return FAIL;
2944
2945 if (isn != NULL)
2946 isn->isn_arg.op.op_type = type;
2947 }
2948 }
2949
2950 return OK;
2951}
2952
2953/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002954 * expr5a == expr5b
2955 * expr5a =~ expr5b
2956 * expr5a != expr5b
2957 * expr5a !~ expr5b
2958 * expr5a > expr5b
2959 * expr5a >= expr5b
2960 * expr5a < expr5b
2961 * expr5a <= expr5b
2962 * expr5a is expr5b
2963 * expr5a isnot expr5b
2964 *
2965 * Produces instructions:
2966 * EVAL expr5a Push result of "expr5a"
2967 * EVAL expr5b Push result of "expr5b"
2968 * COMPARE one of the compare instructions
2969 */
2970 static int
2971compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
2972{
2973 exprtype_T type = EXPR_UNKNOWN;
2974 char_u *p;
2975 char_u *next;
2976 int len = 2;
2977 int type_is = FALSE;
2978 int ppconst_used = ppconst->pp_used;
2979
2980 // get the first variable
2981 if (compile_expr5(arg, cctx, ppconst) == FAIL)
2982 return FAIL;
2983
2984 p = may_peek_next_line(cctx, *arg, &next);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01002985
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002986 type = get_compare_type(p, &len, &type_is);
2987
2988 /*
2989 * If there is a comparative operator, use it.
2990 */
2991 if (type != EXPR_UNKNOWN)
2992 {
2993 int ic = FALSE; // Default: do not ignore case
2994
2995 if (next != NULL)
2996 {
2997 *arg = next_line_from_context(cctx, TRUE);
2998 p = skipwhite(*arg);
2999 }
3000 if (type_is && (p[len] == '?' || p[len] == '#'))
3001 {
3002 semsg(_(e_invalid_expression_str), *arg);
3003 return FAIL;
3004 }
3005 // extra question mark appended: ignore case
3006 if (p[len] == '?')
3007 {
3008 ic = TRUE;
3009 ++len;
3010 }
3011 // extra '#' appended: match case (ignored)
3012 else if (p[len] == '#')
3013 ++len;
3014 // nothing appended: match case
3015
3016 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
3017 {
3018 error_white_both(p, len);
3019 return FAIL;
3020 }
3021
3022 // get the second variable
3023 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
3024 return FAIL;
3025
3026 if (compile_expr5(arg, cctx, ppconst) == FAIL)
3027 return FAIL;
3028
3029 if (ppconst->pp_used == ppconst_used + 2)
3030 {
Bram Moolenaar5b529232022-05-22 21:53:26 +01003031 typval_T *tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003032 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
3033 int ret;
3034
3035 // Both sides are a constant, compute the result now.
3036 // First check for a valid combination of types, this is more
3037 // strict than typval_compare().
3038 if (check_compare_types(type, tv1, tv2) == FAIL)
3039 ret = FAIL;
3040 else
3041 {
3042 ret = typval_compare(tv1, tv2, type, ic);
3043 tv1->v_type = VAR_BOOL;
3044 tv1->vval.v_number = tv1->vval.v_number
3045 ? VVAL_TRUE : VVAL_FALSE;
3046 clear_tv(tv2);
3047 --ppconst->pp_used;
3048 }
3049 return ret;
3050 }
3051
3052 generate_ppconst(cctx, ppconst);
3053 return generate_COMPARE(cctx, type, ic);
3054 }
3055
3056 return OK;
3057}
3058
3059static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
3060
3061/*
3062 * Compile || or &&.
3063 */
3064 static int
3065compile_and_or(
3066 char_u **arg,
3067 cctx_T *cctx,
3068 char *op,
3069 ppconst_T *ppconst,
3070 int ppconst_used UNUSED)
3071{
3072 char_u *next;
3073 char_u *p = may_peek_next_line(cctx, *arg, &next);
3074 int opchar = *op;
3075
3076 if (p[0] == opchar && p[1] == opchar)
3077 {
3078 garray_T *instr = &cctx->ctx_instr;
3079 garray_T end_ga;
3080 int save_skip = cctx->ctx_skip;
3081
3082 /*
3083 * Repeat until there is no following "||" or "&&"
3084 */
3085 ga_init2(&end_ga, sizeof(int), 10);
3086 while (p[0] == opchar && p[1] == opchar)
3087 {
3088 long start_lnum = SOURCING_LNUM;
3089 long save_sourcing_lnum;
3090 int start_ctx_lnum = cctx->ctx_lnum;
3091 int save_lnum;
3092 int const_used;
3093 int status;
3094 jumpwhen_T jump_when = opchar == '|'
3095 ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE;
3096
3097 if (next != NULL)
3098 {
3099 *arg = next_line_from_context(cctx, TRUE);
3100 p = skipwhite(*arg);
3101 }
3102
3103 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3104 {
3105 semsg(_(e_white_space_required_before_and_after_str_at_str),
3106 op, p);
3107 ga_clear(&end_ga);
3108 return FAIL;
3109 }
3110
3111 save_sourcing_lnum = SOURCING_LNUM;
3112 SOURCING_LNUM = start_lnum;
3113 save_lnum = cctx->ctx_lnum;
3114 cctx->ctx_lnum = start_ctx_lnum;
3115
3116 status = check_ppconst_bool(ppconst);
3117 if (status != FAIL)
3118 {
3119 // Use the last ppconst if possible.
3120 if (ppconst->pp_used > 0)
3121 {
3122 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
3123 int is_true = tv2bool(tv);
3124
3125 if ((is_true && opchar == '|')
3126 || (!is_true && opchar == '&'))
3127 {
3128 // For "false && expr" and "true || expr" the "expr"
3129 // does not need to be evaluated.
3130 cctx->ctx_skip = SKIP_YES;
3131 clear_tv(tv);
3132 tv->v_type = VAR_BOOL;
3133 tv->vval.v_number = is_true ? VVAL_TRUE : VVAL_FALSE;
3134 }
3135 else
3136 {
3137 // For "true && expr" and "false || expr" only "expr"
3138 // needs to be evaluated.
3139 --ppconst->pp_used;
3140 jump_when = JUMP_NEVER;
3141 }
3142 }
3143 else
3144 {
3145 // Every part must evaluate to a bool.
3146 status = bool_on_stack(cctx);
3147 }
3148 }
3149 if (status != FAIL)
3150 status = ga_grow(&end_ga, 1);
3151 cctx->ctx_lnum = save_lnum;
3152 if (status == FAIL)
3153 {
3154 ga_clear(&end_ga);
3155 return FAIL;
3156 }
3157
3158 if (jump_when != JUMP_NEVER)
3159 {
3160 if (cctx->ctx_skip != SKIP_YES)
3161 {
3162 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3163 ++end_ga.ga_len;
3164 }
3165 generate_JUMP(cctx, jump_when, 0);
3166 }
3167
3168 // eval the next expression
3169 SOURCING_LNUM = save_sourcing_lnum;
3170 if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
3171 {
3172 ga_clear(&end_ga);
3173 return FAIL;
3174 }
3175
3176 const_used = ppconst->pp_used;
3177 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
3178 : compile_expr4(arg, cctx, ppconst)) == FAIL)
3179 {
3180 ga_clear(&end_ga);
3181 return FAIL;
3182 }
3183
3184 // "0 || 1" results in true, "1 && 0" results in false.
3185 if (ppconst->pp_used == const_used + 1)
3186 {
3187 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
3188
3189 if (tv->v_type == VAR_NUMBER
3190 && (tv->vval.v_number == 1 || tv->vval.v_number == 0))
3191 {
3192 tv->vval.v_number = tv->vval.v_number == 1
3193 ? VVAL_TRUE : VVAL_FALSE;
3194 tv->v_type = VAR_BOOL;
3195 }
3196 }
3197
3198 p = may_peek_next_line(cctx, *arg, &next);
3199 }
3200
3201 if (check_ppconst_bool(ppconst) == FAIL)
3202 {
3203 ga_clear(&end_ga);
3204 return FAIL;
3205 }
3206
3207 if (cctx->ctx_skip != SKIP_YES && ppconst->pp_used == 0)
3208 // Every part must evaluate to a bool.
3209 if (bool_on_stack(cctx) == FAIL)
3210 {
3211 ga_clear(&end_ga);
3212 return FAIL;
3213 }
3214
3215 if (end_ga.ga_len > 0)
3216 {
3217 // Fill in the end label in all jumps.
3218 generate_ppconst(cctx, ppconst);
3219 while (end_ga.ga_len > 0)
3220 {
3221 isn_T *isn;
3222
3223 --end_ga.ga_len;
3224 isn = ((isn_T *)instr->ga_data)
3225 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3226 isn->isn_arg.jump.jump_where = instr->ga_len;
3227 }
3228 }
3229 ga_clear(&end_ga);
3230
3231 cctx->ctx_skip = save_skip;
3232 }
3233
3234 return OK;
3235}
3236
3237/*
3238 * expr4a && expr4a && expr4a logical AND
3239 *
3240 * Produces instructions:
3241 * EVAL expr4a Push result of "expr4a"
3242 * COND2BOOL convert to bool if needed
3243 * JUMP_IF_COND_FALSE end
3244 * EVAL expr4b Push result of "expr4b"
3245 * JUMP_IF_COND_FALSE end
3246 * EVAL expr4c Push result of "expr4c"
3247 * end:
3248 */
3249 static int
3250compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3251{
3252 int ppconst_used = ppconst->pp_used;
3253
3254 // get the first variable
3255 if (compile_expr4(arg, cctx, ppconst) == FAIL)
3256 return FAIL;
3257
3258 // || and && work almost the same
3259 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
3260}
3261
3262/*
3263 * expr3a || expr3b || expr3c logical OR
3264 *
3265 * Produces instructions:
3266 * EVAL expr3a Push result of "expr3a"
3267 * COND2BOOL convert to bool if needed
3268 * JUMP_IF_COND_TRUE end
3269 * EVAL expr3b Push result of "expr3b"
3270 * JUMP_IF_COND_TRUE end
3271 * EVAL expr3c Push result of "expr3c"
3272 * end:
3273 */
3274 static int
3275compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3276{
3277 int ppconst_used = ppconst->pp_used;
3278
3279 // eval the first expression
3280 if (compile_expr3(arg, cctx, ppconst) == FAIL)
3281 return FAIL;
3282
3283 // || and && work almost the same
3284 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
3285}
3286
3287/*
3288 * Toplevel expression: expr2 ? expr1a : expr1b
3289 * Produces instructions:
3290 * EVAL expr2 Push result of "expr2"
3291 * JUMP_IF_FALSE alt jump if false
3292 * EVAL expr1a
3293 * JUMP_ALWAYS end
3294 * alt: EVAL expr1b
3295 * end:
3296 *
3297 * Toplevel expression: expr2 ?? expr1
3298 * Produces instructions:
3299 * EVAL expr2 Push result of "expr2"
3300 * JUMP_AND_KEEP_IF_TRUE end jump if true
3301 * EVAL expr1
3302 * end:
3303 */
3304 int
3305compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3306{
3307 char_u *p;
3308 int ppconst_used = ppconst->pp_used;
3309 char_u *next;
3310
3311 // Ignore all kinds of errors when not producing code.
3312 if (cctx->ctx_skip == SKIP_YES)
3313 {
Bram Moolenaar83d0cec2022-02-04 21:17:58 +00003314 int prev_did_emsg = did_emsg;
3315
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003316 skip_expr_cctx(arg, cctx);
Bram Moolenaar83d0cec2022-02-04 21:17:58 +00003317 return did_emsg == prev_did_emsg ? OK : FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003318 }
3319
3320 // Evaluate the first expression.
3321 if (compile_expr2(arg, cctx, ppconst) == FAIL)
3322 return FAIL;
3323
3324 p = may_peek_next_line(cctx, *arg, &next);
3325 if (*p == '?')
3326 {
3327 int op_falsy = p[1] == '?';
3328 garray_T *instr = &cctx->ctx_instr;
3329 garray_T *stack = &cctx->ctx_type_stack;
3330 int alt_idx = instr->ga_len;
3331 int end_idx = 0;
3332 isn_T *isn;
3333 type_T *type1 = NULL;
3334 int has_const_expr = FALSE;
3335 int const_value = FALSE;
3336 int save_skip = cctx->ctx_skip;
3337
3338 if (next != NULL)
3339 {
3340 *arg = next_line_from_context(cctx, TRUE);
3341 p = skipwhite(*arg);
3342 }
3343
3344 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
3345 {
3346 semsg(_(e_white_space_required_before_and_after_str_at_str),
3347 op_falsy ? "??" : "?", p);
3348 return FAIL;
3349 }
3350
3351 if (ppconst->pp_used == ppconst_used + 1)
3352 {
3353 // the condition is a constant, we know whether the ? or the :
3354 // expression is to be evaluated.
3355 has_const_expr = TRUE;
3356 if (op_falsy)
3357 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
3358 else
3359 {
3360 int error = FALSE;
3361
3362 const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
3363 &error);
3364 if (error)
3365 return FAIL;
3366 }
3367 cctx->ctx_skip = save_skip == SKIP_YES ||
3368 (op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
3369
3370 if (op_falsy && cctx->ctx_skip == SKIP_YES)
3371 // "left ?? right" and "left" is truthy: produce "left"
3372 generate_ppconst(cctx, ppconst);
3373 else
3374 {
3375 clear_tv(&ppconst->pp_tv[ppconst_used]);
3376 --ppconst->pp_used;
3377 }
3378 }
3379 else
3380 {
3381 generate_ppconst(cctx, ppconst);
3382 if (op_falsy)
3383 end_idx = instr->ga_len;
3384 generate_JUMP(cctx, op_falsy
3385 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
3386 if (op_falsy)
Bram Moolenaar078a4612022-01-04 15:17:03 +00003387 type1 = get_type_on_stack(cctx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003388 }
3389
3390 // evaluate the second expression; any type is accepted
3391 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
3392 return FAIL;
3393 if (compile_expr1(arg, cctx, ppconst) == FAIL)
3394 return FAIL;
3395
3396 if (!has_const_expr)
3397 {
3398 generate_ppconst(cctx, ppconst);
3399
3400 if (!op_falsy)
3401 {
3402 // remember the type and drop it
Bram Moolenaar078a4612022-01-04 15:17:03 +00003403 type1 = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003404 --stack->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003405
3406 end_idx = instr->ga_len;
3407 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3408
3409 // jump here from JUMP_IF_FALSE
3410 isn = ((isn_T *)instr->ga_data) + alt_idx;
3411 isn->isn_arg.jump.jump_where = instr->ga_len;
3412 }
3413 }
3414
3415 if (!op_falsy)
3416 {
3417 // Check for the ":".
3418 p = may_peek_next_line(cctx, *arg, &next);
3419 if (*p != ':')
3420 {
3421 emsg(_(e_missing_colon_after_questionmark));
3422 return FAIL;
3423 }
3424 if (next != NULL)
3425 {
3426 *arg = next_line_from_context(cctx, TRUE);
3427 p = skipwhite(*arg);
3428 }
3429
3430 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3431 {
3432 semsg(_(e_white_space_required_before_and_after_str_at_str),
3433 ":", p);
3434 return FAIL;
3435 }
3436
3437 // evaluate the third expression
3438 if (has_const_expr)
3439 cctx->ctx_skip = save_skip == SKIP_YES || const_value
3440 ? SKIP_YES : SKIP_NOT;
3441 if (may_get_next_line_error(p + 1, arg, cctx) == FAIL)
3442 return FAIL;
3443 if (compile_expr1(arg, cctx, ppconst) == FAIL)
3444 return FAIL;
3445 }
3446
3447 if (!has_const_expr)
3448 {
3449 type_T **typep;
3450
3451 generate_ppconst(cctx, ppconst);
Bram Moolenaarfa46ead2021-12-22 13:18:39 +00003452 ppconst->pp_is_const = FALSE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003453
3454 // If the types differ, the result has a more generic type.
Bram Moolenaar078a4612022-01-04 15:17:03 +00003455 typep = &((((type2_T *)stack->ga_data)
3456 + stack->ga_len - 1)->type_curr);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00003457 common_type(type1, *typep, typep, cctx->ctx_type_list);
3458
3459 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
3460 isn = ((isn_T *)instr->ga_data) + end_idx;
3461 isn->isn_arg.jump.jump_where = instr->ga_len;
3462 }
3463
3464 cctx->ctx_skip = save_skip;
3465 }
3466 return OK;
3467}
3468
3469/*
3470 * Toplevel expression.
3471 * Sets "is_const" (if not NULL) to indicate the value is a constant.
3472 * Returns OK or FAIL.
3473 */
3474 int
3475compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const)
3476{
3477 ppconst_T ppconst;
3478
3479 CLEAR_FIELD(ppconst);
3480 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
3481 {
3482 clear_ppconst(&ppconst);
3483 return FAIL;
3484 }
3485 if (is_const != NULL)
3486 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const;
3487 if (generate_ppconst(cctx, &ppconst) == FAIL)
3488 return FAIL;
3489 return OK;
3490}
3491
3492/*
3493 * Toplevel expression.
3494 */
3495 int
3496compile_expr0(char_u **arg, cctx_T *cctx)
3497{
3498 return compile_expr0_ext(arg, cctx, NULL);
3499}
3500
3501
3502#endif // defined(FEAT_EVAL)