blob: f6d1fb3d8b1598d83b1fdfed833a96a3c3c71048 [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
Bram Moolenaarefd88552020-06-18 20:50:10 +020026// values for ctx_skip
27typedef enum {
28 SKIP_NOT, // condition is a constant, produce code
29 SKIP_YES, // condition is a constant, do NOT produce code
Bram Moolenaar280b0dc2020-06-20 13:29:03 +020030 SKIP_UNKNOWN // condition is not a constant, produce code
Bram Moolenaarefd88552020-06-18 20:50:10 +020031} skip_T;
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033/*
34 * Chain of jump instructions where the end label needs to be set.
35 */
36typedef struct endlabel_S endlabel_T;
37struct endlabel_S {
38 endlabel_T *el_next; // chain end_label locations
39 int el_end_label; // instruction idx where to set end
40};
41
42/*
43 * info specific for the scope of :if / elseif / else
44 */
45typedef struct {
Bram Moolenaarefd88552020-06-18 20:50:10 +020046 int is_seen_else;
Bram Moolenaarced68a02021-01-24 17:53:47 +010047 int is_seen_skip_not; // a block was unconditionally executed
Bram Moolenaarefd88552020-06-18 20:50:10 +020048 int is_had_return; // every block ends in :return
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010049 int is_if_label; // instruction idx at IF or ELSEIF
50 endlabel_T *is_end_label; // instructions to set end label
51} ifscope_T;
52
53/*
54 * info specific for the scope of :while
55 */
56typedef struct {
57 int ws_top_label; // instruction idx at WHILE
58 endlabel_T *ws_end_label; // instructions to set end
59} whilescope_T;
60
61/*
62 * info specific for the scope of :for
63 */
64typedef struct {
65 int fs_top_label; // instruction idx at FOR
66 endlabel_T *fs_end_label; // break instructions
67} forscope_T;
68
69/*
70 * info specific for the scope of :try
71 */
72typedef struct {
73 int ts_try_label; // instruction idx at TRY
74 endlabel_T *ts_end_label; // jump to :finally or :endtry
75 int ts_catch_label; // instruction idx of last CATCH
76 int ts_caught_all; // "catch" without argument encountered
77} tryscope_T;
78
79typedef enum {
80 NO_SCOPE,
81 IF_SCOPE,
82 WHILE_SCOPE,
83 FOR_SCOPE,
84 TRY_SCOPE,
85 BLOCK_SCOPE
86} scopetype_T;
87
88/*
89 * Info for one scope, pointed to by "ctx_scope".
90 */
91typedef struct scope_S scope_T;
92struct scope_S {
93 scope_T *se_outer; // scope containing this one
94 scopetype_T se_type;
95 int se_local_count; // ctx_locals.ga_len before scope
Bram Moolenaarefd88552020-06-18 20:50:10 +020096 skip_T se_skip_save; // ctx_skip before the block
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010097 union {
98 ifscope_T se_if;
99 whilescope_T se_while;
100 forscope_T se_for;
101 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +0100102 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100103};
104
105/*
106 * Entry for "ctx_locals". Used for arguments and local variables.
107 */
108typedef struct {
109 char_u *lv_name;
110 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200111 int lv_idx; // index of the variable on the stack
Bram Moolenaarab360522021-01-10 14:02:28 +0100112 int lv_from_outer; // nesting level, using ctx_outer scope
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200113 int lv_const; // when TRUE cannot be assigned to
114 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100115} lvar_T;
116
117/*
118 * Context for compiling lines of Vim script.
119 * Stores info about the local variables and condition stack.
120 */
121struct cctx_S {
122 ufunc_T *ctx_ufunc; // current function
123 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200124 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125 garray_T ctx_instr; // generated instructions
126
Bram Moolenaarb2049902021-01-24 12:53:53 +0100127 int ctx_profiling; // when TRUE generate ISN_PROF_START
128
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100129 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200130 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100131
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200132 int ctx_has_closure; // set to one if a closures was created in
133 // the function
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200134
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135 garray_T ctx_imports; // imported items
136
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200137 skip_T ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100138 scope_T *ctx_scope; // current scope, NULL at toplevel
Bram Moolenaarefd88552020-06-18 20:50:10 +0200139 int ctx_had_return; // last seen statement was "return"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100140
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200141 cctx_T *ctx_outer; // outer scope for lambda or nested
142 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200143 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200144
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100145 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200146 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +0200147
Bram Moolenaar02194d22020-10-24 23:08:38 +0200148 int ctx_has_cmdmod; // ISN_CMDMOD was generated
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100149};
150
Bram Moolenaarcdc40c42020-12-26 17:43:08 +0100151static void delete_def_function_contents(dfunc_T *dfunc, int mark_deleted);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152
153/*
Bram Moolenaar709664c2020-12-12 14:33:41 +0100154 * Lookup variable "name" in the local scope and return it in "lvar".
Bram Moolenaarab360522021-01-10 14:02:28 +0100155 * "lvar->lv_from_outer" is incremented accordingly.
Bram Moolenaar709664c2020-12-12 14:33:41 +0100156 * If "lvar" is NULL only check if the variable can be found.
157 * Return FAIL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100158 */
Bram Moolenaar709664c2020-12-12 14:33:41 +0100159 static int
160lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100161{
162 int idx;
Bram Moolenaar709664c2020-12-12 14:33:41 +0100163 lvar_T *lvp;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100164
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100165 if (len == 0)
Bram Moolenaar709664c2020-12-12 14:33:41 +0100166 return FAIL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200167
168 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100169 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
170 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100171 lvp = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
172 if (STRNCMP(name, lvp->lv_name, len) == 0
173 && STRLEN(lvp->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200174 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100175 if (lvar != NULL)
176 {
177 *lvar = *lvp;
Bram Moolenaarab360522021-01-10 14:02:28 +0100178 lvar->lv_from_outer = 0;
Bram Moolenaar709664c2020-12-12 14:33:41 +0100179 }
180 return OK;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200181 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100182 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200183
184 // Find local in outer function scope.
185 if (cctx->ctx_outer != NULL)
186 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100187 if (lookup_local(name, len, lvar, cctx->ctx_outer) == OK)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200188 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100189 if (lvar != NULL)
190 {
191 cctx->ctx_outer_used = TRUE;
Bram Moolenaarab360522021-01-10 14:02:28 +0100192 ++lvar->lv_from_outer;
Bram Moolenaar709664c2020-12-12 14:33:41 +0100193 }
194 return OK;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200195 }
196 }
197
Bram Moolenaar709664c2020-12-12 14:33:41 +0100198 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100199}
200
201/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200202 * Lookup an argument in the current function and an enclosing function.
203 * Returns the argument index in "idxp"
204 * Returns the argument type in "type"
205 * Sets "gen_load_outer" to TRUE if found in outer scope.
206 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100207 */
208 static int
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200209arg_exists(
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200210 char_u *name,
211 size_t len,
212 int *idxp,
213 type_T **type,
214 int *gen_load_outer,
215 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100216{
217 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200218 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100219
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100220 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200221 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100222 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
223 {
224 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
225
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200226 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
227 {
228 if (idxp != NULL)
229 {
230 // Arguments are located above the frame pointer. One further
231 // if there is a vararg argument
232 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
233 + STACK_FRAME_SIZE)
234 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
235
236 if (cctx->ctx_ufunc->uf_arg_types != NULL)
237 *type = cctx->ctx_ufunc->uf_arg_types[idx];
238 else
239 *type = &t_any;
240 }
241 return OK;
242 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100243 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100244
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200245 va_name = cctx->ctx_ufunc->uf_va_name;
246 if (va_name != NULL
247 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
248 {
249 if (idxp != NULL)
250 {
251 // varargs is always the last argument
252 *idxp = -STACK_FRAME_SIZE - 1;
253 *type = cctx->ctx_ufunc->uf_va_type;
254 }
255 return OK;
256 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100257
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200258 if (cctx->ctx_outer != NULL)
259 {
260 // Lookup the name for an argument of the outer function.
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200261 if (arg_exists(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200262 == OK)
263 {
Bram Moolenaar44ec21c2021-02-12 21:50:57 +0100264 if (gen_load_outer != NULL)
265 ++*gen_load_outer;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200266 return OK;
267 }
268 }
269
270 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271}
272
273/*
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200274 * Lookup a script-local variable in the current script, possibly defined in a
275 * block that contains the function "cctx->ctx_ufunc".
276 * "cctx" is NULL at the script level.
Bram Moolenaar18062fc2021-03-05 21:35:47 +0100277 * If "len" is <= 0 "name" must be NUL terminated.
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200278 * Return NULL when not found.
279 */
280 static sallvar_T *
281find_script_var(char_u *name, size_t len, cctx_T *cctx)
282{
283 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
284 hashitem_T *hi;
285 int cc;
286 sallvar_T *sav;
287 ufunc_T *ufunc;
288
289 // Find the list of all script variables with the right name.
290 if (len > 0)
291 {
292 cc = name[len];
293 name[len] = NUL;
294 }
295 hi = hash_find(&si->sn_all_vars.dv_hashtab, name);
296 if (len > 0)
297 name[len] = cc;
298 if (HASHITEM_EMPTY(hi))
299 return NULL;
300
301 sav = HI2SAV(hi);
302 if (sav->sav_block_id == 0 || cctx == NULL)
303 // variable defined in the script scope or not in a function.
304 return sav;
305
306 // Go over the variables with this name and find one that was visible
307 // from the function.
308 ufunc = cctx->ctx_ufunc;
309 while (sav != NULL)
310 {
311 int idx;
312
313 // Go over the blocks that this function was defined in. If the
314 // variable block ID matches it was visible to the function.
315 for (idx = 0; idx < ufunc->uf_block_depth; ++idx)
316 if (ufunc->uf_block_ids[idx] == sav->sav_block_id)
317 return sav;
318 sav = sav->sav_next;
319 }
320
321 return NULL;
322}
323
324/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +0100325 * Return TRUE if the script context is Vim9 script.
Bram Moolenaar84367732020-08-23 15:21:55 +0200326 */
327 static int
328script_is_vim9()
329{
330 return SCRIPT_ITEM(current_sctx.sc_sid)->sn_version == SCRIPT_VERSION_VIM9;
331}
332
333/*
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200334 * Lookup a variable (without s: prefix) in the current script.
Bram Moolenaar53900992020-08-22 19:02:02 +0200335 * If "vim9script" is TRUE the script must be Vim9 script. Used for "var"
336 * without "s:".
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200337 * "cctx" is NULL at the script level.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100338 * Returns OK or FAIL.
339 */
Bram Moolenaarb4893b82021-02-21 22:20:24 +0100340 int
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200341script_var_exists(char_u *name, size_t len, int vim9script, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100342{
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200343 int is_vim9_script;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100344
Bram Moolenaar9c4f5522020-09-25 21:47:28 +0200345 if (current_sctx.sc_sid <= 0)
346 return FAIL;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200347 is_vim9_script = script_is_vim9();
348 if (vim9script && !is_vim9_script)
Bram Moolenaar53900992020-08-22 19:02:02 +0200349 return FAIL;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200350 if (is_vim9_script)
351 {
352 // Check script variables that were visible where the function was
353 // defined.
354 if (find_script_var(name, len, cctx) != NULL)
355 return OK;
356 }
357 else
358 {
359 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
360 dictitem_T *di;
361 int cc;
362
363 // Check script variables that are currently visible
364 cc = name[len];
365 name[len] = NUL;
366 di = find_var_in_ht(ht, 0, name, TRUE);
367 name[len] = cc;
368 if (di != NULL)
369 return OK;
370 }
371
372 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100373}
374
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100375/*
Bram Moolenaare0890d62021-02-17 14:52:14 +0100376 * Return TRUE if "name" is a local variable, argument, script variable or
377 * imported.
378 */
379 static int
380variable_exists(char_u *name, size_t len, cctx_T *cctx)
381{
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100382 return (cctx != NULL
383 && (lookup_local(name, len, NULL, cctx) == OK
384 || arg_exists(name, len, NULL, NULL, NULL, cctx) == OK))
Bram Moolenaare0890d62021-02-17 14:52:14 +0100385 || script_var_exists(name, len, FALSE, cctx) == OK
386 || find_imported(name, len, cctx) != NULL;
387}
388
389/*
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100390 * Check if "p[len]" is already defined, either in script "import_sid" or in
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200391 * compilation context "cctx". "cctx" is NULL at the script level.
Bram Moolenaar0f769812020-09-12 18:32:34 +0200392 * Does not check the global namespace.
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100393 * If "is_arg" is TRUE the error message is for an argument name.
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100394 * Return FAIL and give an error if it defined.
395 */
396 int
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100397check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100398{
Bram Moolenaar0f769812020-09-12 18:32:34 +0200399 int c = p[len];
400 ufunc_T *ufunc = NULL;
Bram Moolenaarad486a02020-08-01 23:22:18 +0200401
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100402 if (script_var_exists(p, len, FALSE, cctx) == OK)
403 {
404 if (is_arg)
405 semsg(_(e_argument_already_declared_in_script_str), p);
406 else
407 semsg(_(e_variable_already_declared_in_script_str), p);
408 return FAIL;
409 }
410
Bram Moolenaarad486a02020-08-01 23:22:18 +0200411 p[len] = NUL;
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100412 if ((cctx != NULL
Bram Moolenaar709664c2020-12-12 14:33:41 +0100413 && (lookup_local(p, len, NULL, cctx) == OK
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200414 || arg_exists(p, len, NULL, NULL, NULL, cctx) == OK))
Bram Moolenaarad486a02020-08-01 23:22:18 +0200415 || find_imported(p, len, cctx) != NULL
Bram Moolenaar0f769812020-09-12 18:32:34 +0200416 || (ufunc = find_func_even_dead(p, FALSE, cctx)) != NULL)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100417 {
Bram Moolenaar0f769812020-09-12 18:32:34 +0200418 // A local or script-local function can shadow a global function.
419 if (ufunc == NULL || !func_is_global(ufunc)
420 || (p[0] == 'g' && p[1] == ':'))
421 {
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100422 if (is_arg)
423 semsg(_(e_argument_name_shadows_existing_variable_str), p);
424 else
425 semsg(_(e_name_already_defined_str), p);
Bram Moolenaar0f769812020-09-12 18:32:34 +0200426 p[len] = c;
Bram Moolenaar0f769812020-09-12 18:32:34 +0200427 return FAIL;
428 }
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100429 }
Bram Moolenaarad486a02020-08-01 23:22:18 +0200430 p[len] = c;
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100431 return OK;
432}
433
Bram Moolenaar65b95452020-07-19 14:03:09 +0200434
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100435/////////////////////////////////////////////////////////////////////
436// Following generate_ functions expect the caller to call ga_grow().
437
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200438#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return NULL
439#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return OK
Bram Moolenaar080457c2020-03-03 21:53:32 +0100440
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100441/*
442 * Generate an instruction without arguments.
443 * Returns a pointer to the new instruction, NULL if failed.
444 */
445 static isn_T *
446generate_instr(cctx_T *cctx, isntype_T isn_type)
447{
448 garray_T *instr = &cctx->ctx_instr;
449 isn_T *isn;
450
Bram Moolenaar080457c2020-03-03 21:53:32 +0100451 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100452 if (ga_grow(instr, 1) == FAIL)
453 return NULL;
454 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
455 isn->isn_type = isn_type;
456 isn->isn_lnum = cctx->ctx_lnum + 1;
457 ++instr->ga_len;
458
459 return isn;
460}
461
462/*
463 * Generate an instruction without arguments.
464 * "drop" will be removed from the stack.
465 * Returns a pointer to the new instruction, NULL if failed.
466 */
467 static isn_T *
468generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
469{
470 garray_T *stack = &cctx->ctx_type_stack;
471
Bram Moolenaar080457c2020-03-03 21:53:32 +0100472 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100473 stack->ga_len -= drop;
474 return generate_instr(cctx, isn_type);
475}
476
477/*
478 * Generate instruction "isn_type" and put "type" on the type stack.
479 */
480 static isn_T *
481generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
482{
483 isn_T *isn;
484 garray_T *stack = &cctx->ctx_type_stack;
485
486 if ((isn = generate_instr(cctx, isn_type)) == NULL)
487 return NULL;
488
489 if (ga_grow(stack, 1) == FAIL)
490 return NULL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +0200491 ((type_T **)stack->ga_data)[stack->ga_len] = type == NULL ? &t_any : type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100492 ++stack->ga_len;
493
494 return isn;
495}
496
497/*
498 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200499 * But only for simple types.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100500 */
501 static int
502may_generate_2STRING(int offset, cctx_T *cctx)
503{
504 isn_T *isn;
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200505 isntype_T isntype = ISN_2STRING;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100506 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +0100507 type_T **type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100508
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +0100509 RETURN_OK_IF_SKIP(cctx);
510 type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200511 switch ((*type)->tt_type)
512 {
513 // nothing to be done
514 case VAR_STRING: return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100515
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200516 // conversion possible
517 case VAR_SPECIAL:
518 case VAR_BOOL:
519 case VAR_NUMBER:
520 case VAR_FLOAT:
521 break;
522
523 // conversion possible (with runtime check)
524 case VAR_ANY:
525 case VAR_UNKNOWN:
526 isntype = ISN_2STRING_ANY;
527 break;
528
529 // conversion not possible
530 case VAR_VOID:
531 case VAR_BLOB:
532 case VAR_FUNC:
533 case VAR_PARTIAL:
534 case VAR_LIST:
535 case VAR_DICT:
536 case VAR_JOB:
537 case VAR_CHANNEL:
538 to_string_error((*type)->tt_type);
539 return FAIL;
540 }
541
542 *type = &t_string;
543 if ((isn = generate_instr(cctx, isntype)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100544 return FAIL;
545 isn->isn_arg.number = offset;
546
547 return OK;
548}
549
550 static int
551check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
552{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200553 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100554 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200555 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100556 {
557 if (*op == '+')
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200558 emsg(_(e_wrong_argument_type_for_plus));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100559 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200560 semsg(_(e_char_requires_number_or_float_arguments), *op);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100561 return FAIL;
562 }
563 return OK;
564}
565
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200566 static int
567generate_add_instr(
568 cctx_T *cctx,
569 vartype_T vartype,
570 type_T *type1,
571 type_T *type2)
572{
Bram Moolenaar399ea812020-12-15 21:28:57 +0100573 garray_T *stack = &cctx->ctx_type_stack;
574 isn_T *isn = generate_instr_drop(cctx,
575 vartype == VAR_NUMBER ? ISN_OPNR
576 : vartype == VAR_LIST ? ISN_ADDLIST
577 : vartype == VAR_BLOB ? ISN_ADDBLOB
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200578#ifdef FEAT_FLOAT
Bram Moolenaar399ea812020-12-15 21:28:57 +0100579 : vartype == VAR_FLOAT ? ISN_OPFLOAT
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200580#endif
Bram Moolenaar399ea812020-12-15 21:28:57 +0100581 : ISN_OPANY, 1);
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200582
583 if (vartype != VAR_LIST && vartype != VAR_BLOB
584 && type1->tt_type != VAR_ANY
585 && type2->tt_type != VAR_ANY
586 && check_number_or_float(
587 type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL)
588 return FAIL;
589
590 if (isn != NULL)
591 isn->isn_arg.op.op_type = EXPR_ADD;
Bram Moolenaar399ea812020-12-15 21:28:57 +0100592
593 // When concatenating two lists with different member types the member type
594 // becomes "any".
595 if (vartype == VAR_LIST
596 && type1->tt_type == VAR_LIST && type2->tt_type == VAR_LIST
597 && type1->tt_member != type2->tt_member)
598 (((type_T **)stack->ga_data)[stack->ga_len - 1]) = &t_list_any;
599
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200600 return isn == NULL ? FAIL : OK;
601}
602
603/*
604 * Get the type to use for an instruction for an operation on "type1" and
605 * "type2". If they are matching use a type-specific instruction. Otherwise
606 * fall back to runtime type checking.
607 */
608 static vartype_T
609operator_type(type_T *type1, type_T *type2)
610{
611 if (type1->tt_type == type2->tt_type
612 && (type1->tt_type == VAR_NUMBER
613 || type1->tt_type == VAR_LIST
614#ifdef FEAT_FLOAT
615 || type1->tt_type == VAR_FLOAT
616#endif
617 || type1->tt_type == VAR_BLOB))
618 return type1->tt_type;
619 return VAR_ANY;
620}
621
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100622/*
623 * Generate an instruction with two arguments. The instruction depends on the
624 * type of the arguments.
625 */
626 static int
627generate_two_op(cctx_T *cctx, char_u *op)
628{
629 garray_T *stack = &cctx->ctx_type_stack;
630 type_T *type1;
631 type_T *type2;
632 vartype_T vartype;
633 isn_T *isn;
634
Bram Moolenaar080457c2020-03-03 21:53:32 +0100635 RETURN_OK_IF_SKIP(cctx);
636
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200637 // Get the known type of the two items on the stack.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
639 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200640 vartype = operator_type(type1, type2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100641
642 switch (*op)
643 {
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200644 case '+':
645 if (generate_add_instr(cctx, vartype, type1, type2) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100646 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100647 break;
648
649 case '-':
650 case '*':
651 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
652 op) == FAIL)
653 return FAIL;
654 if (vartype == VAR_NUMBER)
655 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
656#ifdef FEAT_FLOAT
657 else if (vartype == VAR_FLOAT)
658 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
659#endif
660 else
661 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
662 if (isn != NULL)
663 isn->isn_arg.op.op_type = *op == '*'
664 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
665 break;
666
Bram Moolenaar4c683752020-04-05 21:38:23 +0200667 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100668 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200669 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100670 && type2->tt_type != VAR_NUMBER))
671 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200672 emsg(_(e_percent_requires_number_arguments));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100673 return FAIL;
674 }
675 isn = generate_instr_drop(cctx,
676 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
677 if (isn != NULL)
678 isn->isn_arg.op.op_type = EXPR_REM;
679 break;
680 }
681
682 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200683 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100684 {
685 type_T *type = &t_any;
686
687#ifdef FEAT_FLOAT
688 // float+number and number+float results in float
689 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
690 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
691 type = &t_float;
692#endif
693 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
694 }
695
696 return OK;
697}
698
699/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200700 * Get the instruction to use for comparing "type1" with "type2"
701 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100702 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200703 static isntype_T
Bram Moolenaar657137c2021-01-09 15:45:23 +0100704get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100705{
706 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100707
Bram Moolenaar4c683752020-04-05 21:38:23 +0200708 if (type1 == VAR_UNKNOWN)
709 type1 = VAR_ANY;
710 if (type2 == VAR_UNKNOWN)
711 type2 = VAR_ANY;
712
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100713 if (type1 == type2)
714 {
715 switch (type1)
716 {
717 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
718 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
719 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
720 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
721 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
722 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
723 case VAR_LIST: isntype = ISN_COMPARELIST; break;
724 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
725 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100726 default: isntype = ISN_COMPAREANY; break;
727 }
728 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200729 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100730 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
731 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
732 isntype = ISN_COMPAREANY;
733
Bram Moolenaar657137c2021-01-09 15:45:23 +0100734 if ((exprtype == EXPR_IS || exprtype == EXPR_ISNOT)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100735 && (isntype == ISN_COMPAREBOOL
736 || isntype == ISN_COMPARESPECIAL
737 || isntype == ISN_COMPARENR
738 || isntype == ISN_COMPAREFLOAT))
739 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200740 semsg(_(e_cannot_use_str_with_str),
Bram Moolenaar657137c2021-01-09 15:45:23 +0100741 exprtype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200742 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100743 }
744 if (isntype == ISN_DROP
Bram Moolenaar657137c2021-01-09 15:45:23 +0100745 || ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
747 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
Bram Moolenaar657137c2021-01-09 15:45:23 +0100748 || ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
749 && exprtype != EXPR_IS && exprtype != EXPR_ISNOT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100750 && (type1 == VAR_BLOB || type2 == VAR_BLOB
751 || type1 == VAR_LIST || type2 == VAR_LIST))))
752 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200753 semsg(_(e_cannot_compare_str_with_str),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100754 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200755 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100756 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200757 return isntype;
758}
759
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200760 int
Bram Moolenaar657137c2021-01-09 15:45:23 +0100761check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2)
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200762{
763 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
764 return FAIL;
765 return OK;
766}
767
Bram Moolenaara5565e42020-05-09 15:44:01 +0200768/*
769 * Generate an ISN_COMPARE* instruction with a boolean result.
770 */
771 static int
Bram Moolenaar657137c2021-01-09 15:45:23 +0100772generate_COMPARE(cctx_T *cctx, exprtype_T exprtype, int ic)
Bram Moolenaara5565e42020-05-09 15:44:01 +0200773{
774 isntype_T isntype;
775 isn_T *isn;
776 garray_T *stack = &cctx->ctx_type_stack;
777 vartype_T type1;
778 vartype_T type2;
779
780 RETURN_OK_IF_SKIP(cctx);
781
782 // Get the known type of the two items on the stack. If they are matching
783 // use a type-specific instruction. Otherwise fall back to runtime type
784 // checking.
785 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
786 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar657137c2021-01-09 15:45:23 +0100787 isntype = get_compare_isn(exprtype, type1, type2);
Bram Moolenaara5565e42020-05-09 15:44:01 +0200788 if (isntype == ISN_DROP)
789 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100790
791 if ((isn = generate_instr(cctx, isntype)) == NULL)
792 return FAIL;
Bram Moolenaar657137c2021-01-09 15:45:23 +0100793 isn->isn_arg.op.op_type = exprtype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 isn->isn_arg.op.op_ic = ic;
795
796 // takes two arguments, puts one bool back
797 if (stack->ga_len >= 2)
798 {
799 --stack->ga_len;
800 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
801 }
802
803 return OK;
804}
805
806/*
807 * Generate an ISN_2BOOL instruction.
808 */
809 static int
810generate_2BOOL(cctx_T *cctx, int invert)
811{
812 isn_T *isn;
813 garray_T *stack = &cctx->ctx_type_stack;
814
Bram Moolenaar080457c2020-03-03 21:53:32 +0100815 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100816 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
817 return FAIL;
818 isn->isn_arg.number = invert;
819
820 // type becomes bool
821 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
822
823 return OK;
824}
825
Bram Moolenaar2bb26582020-10-03 22:52:39 +0200826/*
827 * Generate an ISN_COND2BOOL instruction.
828 */
829 static int
830generate_COND2BOOL(cctx_T *cctx)
831{
832 isn_T *isn;
833 garray_T *stack = &cctx->ctx_type_stack;
834
835 RETURN_OK_IF_SKIP(cctx);
836 if ((isn = generate_instr(cctx, ISN_COND2BOOL)) == NULL)
837 return FAIL;
838
839 // type becomes bool
840 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
841
842 return OK;
843}
844
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100845 static int
Bram Moolenaar5e654232020-09-16 15:22:00 +0200846generate_TYPECHECK(
847 cctx_T *cctx,
848 type_T *expected,
Bram Moolenaare32e5162021-01-21 20:21:29 +0100849 int offset,
850 int argidx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100851{
852 isn_T *isn;
853 garray_T *stack = &cctx->ctx_type_stack;
854
Bram Moolenaar080457c2020-03-03 21:53:32 +0100855 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100856 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
857 return FAIL;
Bram Moolenaar5e654232020-09-16 15:22:00 +0200858 isn->isn_arg.type.ct_type = alloc_type(expected);
Bram Moolenaarb3005ce2021-01-22 17:51:06 +0100859 isn->isn_arg.type.ct_off = (int8_T)offset;
860 isn->isn_arg.type.ct_arg_idx = (int8_T)argidx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100861
Bram Moolenaar5e654232020-09-16 15:22:00 +0200862 // type becomes expected
863 ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100864
865 return OK;
866}
867
Bram Moolenaaraa210a32021-01-02 15:41:03 +0100868 static int
869generate_SETTYPE(
870 cctx_T *cctx,
871 type_T *expected)
872{
873 isn_T *isn;
874
875 RETURN_OK_IF_SKIP(cctx);
876 if ((isn = generate_instr(cctx, ISN_SETTYPE)) == NULL)
877 return FAIL;
878 isn->isn_arg.type.ct_type = alloc_type(expected);
879 return OK;
880}
881
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100882/*
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200883 * Return TRUE if "actual" could be "expected" and a runtime typecheck is to be
884 * used. Return FALSE if the types will never match.
885 */
Bram Moolenaar193f6202020-11-16 20:08:35 +0100886 int
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200887use_typecheck(type_T *actual, type_T *expected)
888{
889 if (actual->tt_type == VAR_ANY
890 || actual->tt_type == VAR_UNKNOWN
891 || (actual->tt_type == VAR_FUNC
892 && (expected->tt_type == VAR_FUNC
893 || expected->tt_type == VAR_PARTIAL)
Bram Moolenaar328eac22021-01-07 19:23:08 +0100894 && (actual->tt_member == &t_any || actual->tt_argcount < 0)
895 && ((actual->tt_member == &t_void)
896 == (expected->tt_member == &t_void))))
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200897 return TRUE;
898 if ((actual->tt_type == VAR_LIST || actual->tt_type == VAR_DICT)
899 && actual->tt_type == expected->tt_type)
900 // This takes care of a nested list or dict.
901 return use_typecheck(actual->tt_member, expected->tt_member);
902 return FALSE;
903}
904
905/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200906 * Check that
Bram Moolenaar5e654232020-09-16 15:22:00 +0200907 * - "actual" matches "expected" type or
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200908 * - "actual" is a type that can be "expected" type: add a runtime check; or
909 * - return FAIL.
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200910 * If "actual_is_const" is TRUE then the type won't change at runtime, do not
911 * generate a TYPECHECK.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200912 */
Bram Moolenaar351ead02021-01-16 16:07:01 +0100913 int
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200914need_type(
915 type_T *actual,
916 type_T *expected,
917 int offset,
Bram Moolenaar351ead02021-01-16 16:07:01 +0100918 int arg_idx,
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200919 cctx_T *cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200920 int silent,
921 int actual_is_const)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200922{
Bram Moolenaarf785aa12021-02-11 21:19:34 +0100923 where_T where;
924
Bram Moolenaar4ed124c2020-09-09 20:03:46 +0200925 if (expected == &t_bool && actual != &t_bool
926 && (actual->tt_flags & TTFLAG_BOOL_OK))
927 {
928 // Using "0", "1" or the result of an expression with "&&" or "||" as a
929 // boolean is OK but requires a conversion.
930 generate_2BOOL(cctx, FALSE);
931 return OK;
932 }
933
Bram Moolenaarf785aa12021-02-11 21:19:34 +0100934 where.wt_index = arg_idx;
935 where.wt_variable = FALSE;
936 if (check_type(expected, actual, FALSE, where) == OK)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200937 return OK;
Bram Moolenaar5e654232020-09-16 15:22:00 +0200938
939 // If the actual type can be the expected type add a runtime check.
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200940 // If it's a constant a runtime check makes no sense.
941 if (!actual_is_const && use_typecheck(actual, expected))
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200942 {
Bram Moolenaare32e5162021-01-21 20:21:29 +0100943 generate_TYPECHECK(cctx, expected, offset, arg_idx);
Bram Moolenaar5e654232020-09-16 15:22:00 +0200944 return OK;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200945 }
Bram Moolenaar5e654232020-09-16 15:22:00 +0200946
947 if (!silent)
Bram Moolenaar351ead02021-01-16 16:07:01 +0100948 arg_type_mismatch(expected, actual, arg_idx);
Bram Moolenaar5e654232020-09-16 15:22:00 +0200949 return FAIL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200950}
951
952/*
Bram Moolenaarea2d4072020-11-12 12:08:51 +0100953 * Check that the top of the type stack has a type that can be used as a
954 * condition. Give an error and return FAIL if not.
955 */
956 static int
957bool_on_stack(cctx_T *cctx)
958{
959 garray_T *stack = &cctx->ctx_type_stack;
960 type_T *type;
961
962 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
963 if (type == &t_bool)
964 return OK;
965
966 if (type == &t_any || type == &t_number)
967 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
968 // This requires a runtime type check.
969 return generate_COND2BOOL(cctx);
970
Bram Moolenaar351ead02021-01-16 16:07:01 +0100971 return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE);
Bram Moolenaarea2d4072020-11-12 12:08:51 +0100972}
973
974/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100975 * Generate an ISN_PUSHNR instruction.
976 */
977 static int
978generate_PUSHNR(cctx_T *cctx, varnumber_T number)
979{
980 isn_T *isn;
Bram Moolenaar29a86ff2020-09-09 14:55:31 +0200981 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100982
Bram Moolenaar080457c2020-03-03 21:53:32 +0100983 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100984 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
985 return FAIL;
986 isn->isn_arg.number = number;
987
Bram Moolenaar29a86ff2020-09-09 14:55:31 +0200988 if (number == 0 || number == 1)
Bram Moolenaar29a86ff2020-09-09 14:55:31 +0200989 // A 0 or 1 number can also be used as a bool.
Bram Moolenaar3868f592020-12-25 13:20:41 +0100990 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_number_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100991 return OK;
992}
993
994/*
995 * Generate an ISN_PUSHBOOL instruction.
996 */
997 static int
998generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
999{
1000 isn_T *isn;
1001
Bram Moolenaar080457c2020-03-03 21:53:32 +01001002 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001003 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
1004 return FAIL;
1005 isn->isn_arg.number = number;
1006
1007 return OK;
1008}
1009
1010/*
1011 * Generate an ISN_PUSHSPEC instruction.
1012 */
1013 static int
1014generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
1015{
1016 isn_T *isn;
1017
Bram Moolenaar080457c2020-03-03 21:53:32 +01001018 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001019 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
1020 return FAIL;
1021 isn->isn_arg.number = number;
1022
1023 return OK;
1024}
1025
1026#ifdef FEAT_FLOAT
1027/*
1028 * Generate an ISN_PUSHF instruction.
1029 */
1030 static int
1031generate_PUSHF(cctx_T *cctx, float_T fnumber)
1032{
1033 isn_T *isn;
1034
Bram Moolenaar080457c2020-03-03 21:53:32 +01001035 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001036 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
1037 return FAIL;
1038 isn->isn_arg.fnumber = fnumber;
1039
1040 return OK;
1041}
1042#endif
1043
1044/*
1045 * Generate an ISN_PUSHS instruction.
1046 * Consumes "str".
1047 */
1048 static int
1049generate_PUSHS(cctx_T *cctx, char_u *str)
1050{
1051 isn_T *isn;
1052
Bram Moolenaar508b5612021-01-02 18:17:26 +01001053 if (cctx->ctx_skip == SKIP_YES)
1054 {
1055 vim_free(str);
1056 return OK;
1057 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001058 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
1059 return FAIL;
1060 isn->isn_arg.string = str;
1061
1062 return OK;
1063}
1064
1065/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001066 * Generate an ISN_PUSHCHANNEL instruction.
1067 * Consumes "channel".
1068 */
1069 static int
1070generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
1071{
1072 isn_T *isn;
1073
Bram Moolenaar080457c2020-03-03 21:53:32 +01001074 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001075 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
1076 return FAIL;
1077 isn->isn_arg.channel = channel;
1078
1079 return OK;
1080}
1081
1082/*
1083 * Generate an ISN_PUSHJOB instruction.
1084 * Consumes "job".
1085 */
1086 static int
1087generate_PUSHJOB(cctx_T *cctx, job_T *job)
1088{
1089 isn_T *isn;
1090
Bram Moolenaar080457c2020-03-03 21:53:32 +01001091 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001092 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001093 return FAIL;
1094 isn->isn_arg.job = job;
1095
1096 return OK;
1097}
1098
1099/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001100 * Generate an ISN_PUSHBLOB instruction.
1101 * Consumes "blob".
1102 */
1103 static int
1104generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1105{
1106 isn_T *isn;
1107
Bram Moolenaar080457c2020-03-03 21:53:32 +01001108 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001109 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1110 return FAIL;
1111 isn->isn_arg.blob = blob;
1112
1113 return OK;
1114}
1115
1116/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001117 * Generate an ISN_PUSHFUNC instruction with name "name".
1118 * Consumes "name".
1119 */
1120 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001121generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001122{
1123 isn_T *isn;
1124
Bram Moolenaar080457c2020-03-03 21:53:32 +01001125 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001126 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001127 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02001128 isn->isn_arg.string = name == NULL ? NULL : vim_strsave(name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001129
1130 return OK;
1131}
1132
1133/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001134 * Generate an ISN_GETITEM instruction with "index".
1135 */
1136 static int
1137generate_GETITEM(cctx_T *cctx, int index)
1138{
1139 isn_T *isn;
1140 garray_T *stack = &cctx->ctx_type_stack;
1141 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1142 type_T *item_type = &t_any;
1143
1144 RETURN_OK_IF_SKIP(cctx);
1145
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001146 if (type->tt_type != VAR_LIST)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001147 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001148 // cannot happen, caller has checked the type
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001149 emsg(_(e_listreq));
1150 return FAIL;
1151 }
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001152 item_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001153 if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
1154 return FAIL;
1155 isn->isn_arg.number = index;
1156
1157 // add the item type to the type stack
1158 if (ga_grow(stack, 1) == FAIL)
1159 return FAIL;
1160 ((type_T **)stack->ga_data)[stack->ga_len] = item_type;
1161 ++stack->ga_len;
1162 return OK;
1163}
1164
1165/*
Bram Moolenaar9af78762020-06-16 11:34:42 +02001166 * Generate an ISN_SLICE instruction with "count".
1167 */
1168 static int
1169generate_SLICE(cctx_T *cctx, int count)
1170{
1171 isn_T *isn;
1172
1173 RETURN_OK_IF_SKIP(cctx);
1174 if ((isn = generate_instr(cctx, ISN_SLICE)) == NULL)
1175 return FAIL;
1176 isn->isn_arg.number = count;
1177 return OK;
1178}
1179
1180/*
1181 * Generate an ISN_CHECKLEN instruction with "min_len".
1182 */
1183 static int
1184generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK)
1185{
1186 isn_T *isn;
1187
1188 RETURN_OK_IF_SKIP(cctx);
1189
1190 if ((isn = generate_instr(cctx, ISN_CHECKLEN)) == NULL)
1191 return FAIL;
1192 isn->isn_arg.checklen.cl_min_len = min_len;
1193 isn->isn_arg.checklen.cl_more_OK = more_OK;
1194
1195 return OK;
1196}
1197
1198/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001199 * Generate an ISN_STORE instruction.
1200 */
1201 static int
1202generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1203{
1204 isn_T *isn;
1205
Bram Moolenaar080457c2020-03-03 21:53:32 +01001206 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001207 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1208 return FAIL;
1209 if (name != NULL)
1210 isn->isn_arg.string = vim_strsave(name);
1211 else
1212 isn->isn_arg.number = idx;
1213
1214 return OK;
1215}
1216
1217/*
Bram Moolenaarab360522021-01-10 14:02:28 +01001218 * Generate an ISN_STOREOUTER instruction.
1219 */
1220 static int
1221generate_STOREOUTER(cctx_T *cctx, int idx, int level)
1222{
1223 isn_T *isn;
1224
1225 RETURN_OK_IF_SKIP(cctx);
1226 if ((isn = generate_instr_drop(cctx, ISN_STOREOUTER, 1)) == NULL)
1227 return FAIL;
1228 isn->isn_arg.outer.outer_idx = idx;
1229 isn->isn_arg.outer.outer_depth = level;
1230
1231 return OK;
1232}
1233
1234/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001235 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1236 */
1237 static int
1238generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1239{
1240 isn_T *isn;
1241
Bram Moolenaar080457c2020-03-03 21:53:32 +01001242 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001243 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1244 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001245 isn->isn_arg.storenr.stnr_idx = idx;
1246 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001247
1248 return OK;
1249}
1250
1251/*
1252 * Generate an ISN_STOREOPT instruction
1253 */
1254 static int
1255generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1256{
1257 isn_T *isn;
1258
Bram Moolenaar080457c2020-03-03 21:53:32 +01001259 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1c199f92020-08-07 21:28:34 +02001260 if ((isn = generate_instr_drop(cctx, ISN_STOREOPT, 1)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001261 return FAIL;
1262 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1263 isn->isn_arg.storeopt.so_flags = opt_flags;
1264
1265 return OK;
1266}
1267
1268/*
1269 * Generate an ISN_LOAD or similar instruction.
1270 */
1271 static int
1272generate_LOAD(
1273 cctx_T *cctx,
1274 isntype_T isn_type,
1275 int idx,
1276 char_u *name,
1277 type_T *type)
1278{
1279 isn_T *isn;
1280
Bram Moolenaar080457c2020-03-03 21:53:32 +01001281 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001282 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1283 return FAIL;
1284 if (name != NULL)
1285 isn->isn_arg.string = vim_strsave(name);
1286 else
1287 isn->isn_arg.number = idx;
1288
1289 return OK;
1290}
1291
1292/*
Bram Moolenaarab360522021-01-10 14:02:28 +01001293 * Generate an ISN_LOADOUTER instruction
1294 */
1295 static int
1296generate_LOADOUTER(
1297 cctx_T *cctx,
1298 int idx,
1299 int nesting,
1300 type_T *type)
1301{
1302 isn_T *isn;
1303
1304 RETURN_OK_IF_SKIP(cctx);
1305 if ((isn = generate_instr_type(cctx, ISN_LOADOUTER, type)) == NULL)
1306 return FAIL;
1307 isn->isn_arg.outer.outer_idx = idx;
1308 isn->isn_arg.outer.outer_depth = nesting;
1309
1310 return OK;
1311}
1312
1313/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001314 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001315 */
1316 static int
1317generate_LOADV(
1318 cctx_T *cctx,
1319 char_u *name,
1320 int error)
1321{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001322 int di_flags;
1323 int vidx = find_vim_var(name, &di_flags);
1324 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001325
Bram Moolenaar080457c2020-03-03 21:53:32 +01001326 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001327 if (vidx < 0)
1328 {
1329 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001330 semsg(_(e_variable_not_found_str), name);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001331 return FAIL;
1332 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02001333 type = typval2type_vimvar(get_vim_var_tv(vidx), cctx->ctx_type_list);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001334
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001335 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001336}
1337
1338/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001339 * Generate an ISN_UNLET instruction.
1340 */
1341 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001342generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001343{
1344 isn_T *isn;
1345
1346 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001347 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001348 return FAIL;
1349 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1350 isn->isn_arg.unlet.ul_forceit = forceit;
1351
1352 return OK;
1353}
1354
1355/*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001356 * Generate an ISN_LOCKCONST instruction.
1357 */
1358 static int
1359generate_LOCKCONST(cctx_T *cctx)
1360{
1361 isn_T *isn;
1362
1363 RETURN_OK_IF_SKIP(cctx);
1364 if ((isn = generate_instr(cctx, ISN_LOCKCONST)) == NULL)
1365 return FAIL;
1366 return OK;
1367}
1368
1369/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001370 * Generate an ISN_LOADS instruction.
1371 */
1372 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001373generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001374 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001375 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001376 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001377 int sid,
1378 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001379{
1380 isn_T *isn;
1381
Bram Moolenaar080457c2020-03-03 21:53:32 +01001382 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001383 if (isn_type == ISN_LOADS)
1384 isn = generate_instr_type(cctx, isn_type, type);
1385 else
1386 isn = generate_instr_drop(cctx, isn_type, 1);
1387 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001388 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001389 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1390 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391
1392 return OK;
1393}
1394
1395/*
1396 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1397 */
1398 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001399generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001400 cctx_T *cctx,
1401 isntype_T isn_type,
1402 int sid,
1403 int idx,
1404 type_T *type)
1405{
1406 isn_T *isn;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01001407 scriptref_T *sref;
1408 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001409
Bram Moolenaar080457c2020-03-03 21:53:32 +01001410 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001411 if (isn_type == ISN_LOADSCRIPT)
1412 isn = generate_instr_type(cctx, isn_type, type);
1413 else
1414 isn = generate_instr_drop(cctx, isn_type, 1);
1415 if (isn == NULL)
1416 return FAIL;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01001417
1418 // This requires three arguments, which doesn't fit in an instruction, thus
1419 // we need to allocate a struct for this.
1420 sref = ALLOC_ONE(scriptref_T);
1421 if (sref == NULL)
1422 return FAIL;
1423 isn->isn_arg.script.scriptref = sref;
1424 sref->sref_sid = sid;
1425 sref->sref_idx = idx;
1426 sref->sref_seq = si->sn_script_seq;
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001427 sref->sref_type = type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001428 return OK;
1429}
1430
1431/*
1432 * Generate an ISN_NEWLIST instruction.
1433 */
1434 static int
1435generate_NEWLIST(cctx_T *cctx, int count)
1436{
1437 isn_T *isn;
1438 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001439 type_T *type;
1440 type_T *member;
1441
Bram Moolenaar080457c2020-03-03 21:53:32 +01001442 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001443 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1444 return FAIL;
1445 isn->isn_arg.number = count;
1446
Bram Moolenaar127542b2020-08-09 17:22:04 +02001447 // get the member type from all the items on the stack.
Bram Moolenaar9c2b0662020-09-01 19:56:15 +02001448 if (count == 0)
1449 member = &t_void;
1450 else
1451 member = get_member_type_from_stack(
Bram Moolenaar127542b2020-08-09 17:22:04 +02001452 ((type_T **)stack->ga_data) + stack->ga_len, count, 1,
1453 cctx->ctx_type_list);
1454 type = get_list_type(member, cctx->ctx_type_list);
1455
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001456 // drop the value types
1457 stack->ga_len -= count;
1458
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001459 // add the list type to the type stack
1460 if (ga_grow(stack, 1) == FAIL)
1461 return FAIL;
1462 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1463 ++stack->ga_len;
1464
1465 return OK;
1466}
1467
1468/*
1469 * Generate an ISN_NEWDICT instruction.
1470 */
1471 static int
1472generate_NEWDICT(cctx_T *cctx, int count)
1473{
1474 isn_T *isn;
1475 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001476 type_T *type;
1477 type_T *member;
1478
Bram Moolenaar080457c2020-03-03 21:53:32 +01001479 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001480 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1481 return FAIL;
1482 isn->isn_arg.number = count;
1483
Bram Moolenaar9c2b0662020-09-01 19:56:15 +02001484 if (count == 0)
1485 member = &t_void;
1486 else
1487 member = get_member_type_from_stack(
Bram Moolenaar127542b2020-08-09 17:22:04 +02001488 ((type_T **)stack->ga_data) + stack->ga_len, count, 2,
1489 cctx->ctx_type_list);
1490 type = get_dict_type(member, cctx->ctx_type_list);
1491
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001492 // drop the key and value types
1493 stack->ga_len -= 2 * count;
1494
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001495 // add the dict type to the type stack
1496 if (ga_grow(stack, 1) == FAIL)
1497 return FAIL;
1498 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1499 ++stack->ga_len;
1500
1501 return OK;
1502}
1503
1504/*
1505 * Generate an ISN_FUNCREF instruction.
1506 */
1507 static int
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001508generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001509{
1510 isn_T *isn;
1511 garray_T *stack = &cctx->ctx_type_stack;
1512
Bram Moolenaar080457c2020-03-03 21:53:32 +01001513 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001514 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1515 return FAIL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001516 isn->isn_arg.funcref.fr_func = ufunc->uf_dfunc_idx;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02001517 cctx->ctx_has_closure = 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001518
Bram Moolenaarab360522021-01-10 14:02:28 +01001519 // if the referenced function is a closure, it may use items further up in
1520 // the nested context, including this one.
1521 if (ufunc->uf_flags & FC_CLOSURE)
1522 cctx->ctx_ufunc->uf_flags |= FC_CLOSURE;
1523
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001524 if (ga_grow(stack, 1) == FAIL)
1525 return FAIL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001526 ((type_T **)stack->ga_data)[stack->ga_len] =
1527 ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001528 ++stack->ga_len;
1529
1530 return OK;
1531}
1532
1533/*
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001534 * Generate an ISN_NEWFUNC instruction.
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001535 * "lambda_name" and "func_name" must be in allocated memory and will be
1536 * consumed.
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001537 */
1538 static int
1539generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
1540{
1541 isn_T *isn;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001542
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001543 if (cctx->ctx_skip == SKIP_YES)
1544 {
1545 vim_free(lambda_name);
1546 vim_free(func_name);
1547 return OK;
1548 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001549 if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001550 {
1551 vim_free(lambda_name);
1552 vim_free(func_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001553 return FAIL;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001554 }
1555 isn->isn_arg.newfunc.nf_lambda = lambda_name;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001556 isn->isn_arg.newfunc.nf_global = func_name;
1557
1558 return OK;
1559}
1560
1561/*
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01001562 * Generate an ISN_DEF instruction: list functions
1563 */
1564 static int
1565generate_DEF(cctx_T *cctx, char_u *name, size_t len)
1566{
1567 isn_T *isn;
1568
1569 RETURN_OK_IF_SKIP(cctx);
1570 if ((isn = generate_instr(cctx, ISN_DEF)) == NULL)
1571 return FAIL;
1572 if (len > 0)
1573 {
1574 isn->isn_arg.string = vim_strnsave(name, len);
1575 if (isn->isn_arg.string == NULL)
1576 return FAIL;
1577 }
1578 return OK;
1579}
1580
1581/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001582 * Generate an ISN_JUMP instruction.
1583 */
1584 static int
1585generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1586{
1587 isn_T *isn;
1588 garray_T *stack = &cctx->ctx_type_stack;
1589
Bram Moolenaar080457c2020-03-03 21:53:32 +01001590 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001591 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1592 return FAIL;
1593 isn->isn_arg.jump.jump_when = when;
1594 isn->isn_arg.jump.jump_where = where;
1595
1596 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1597 --stack->ga_len;
1598
1599 return OK;
1600}
1601
1602 static int
1603generate_FOR(cctx_T *cctx, int loop_idx)
1604{
1605 isn_T *isn;
1606 garray_T *stack = &cctx->ctx_type_stack;
1607
Bram Moolenaar080457c2020-03-03 21:53:32 +01001608 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1610 return FAIL;
1611 isn->isn_arg.forloop.for_idx = loop_idx;
1612
1613 if (ga_grow(stack, 1) == FAIL)
1614 return FAIL;
1615 // type doesn't matter, will be stored next
1616 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1617 ++stack->ga_len;
1618
1619 return OK;
1620}
Bram Moolenaarc150c092021-02-13 15:02:46 +01001621/*
1622 * Generate an ISN_TRYCONT instruction.
1623 */
1624 static int
1625generate_TRYCONT(cctx_T *cctx, int levels, int where)
1626{
1627 isn_T *isn;
1628
1629 RETURN_OK_IF_SKIP(cctx);
1630 if ((isn = generate_instr(cctx, ISN_TRYCONT)) == NULL)
1631 return FAIL;
1632 isn->isn_arg.trycont.tct_levels = levels;
1633 isn->isn_arg.trycont.tct_where = where;
1634
1635 return OK;
1636}
1637
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001638
1639/*
1640 * Generate an ISN_BCALL instruction.
Bram Moolenaar389df252020-07-09 21:20:47 +02001641 * "method_call" is TRUE for "value->method()"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001642 * Return FAIL if the number of arguments is wrong.
1643 */
1644 static int
Bram Moolenaar389df252020-07-09 21:20:47 +02001645generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001646{
1647 isn_T *isn;
1648 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar389df252020-07-09 21:20:47 +02001649 int argoff;
Bram Moolenaara1224cb2020-10-22 12:31:49 +02001650 type_T **argtypes = NULL;
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001651 type_T *maptype = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001652
Bram Moolenaar080457c2020-03-03 21:53:32 +01001653 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar389df252020-07-09 21:20:47 +02001654 argoff = check_internal_func(func_idx, argcount);
1655 if (argoff < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001656 return FAIL;
1657
Bram Moolenaar389df252020-07-09 21:20:47 +02001658 if (method_call && argoff > 1)
1659 {
1660 if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
1661 return FAIL;
1662 isn->isn_arg.shuffle.shfl_item = argcount;
1663 isn->isn_arg.shuffle.shfl_up = argoff - 1;
1664 }
1665
Bram Moolenaaraf7a9062020-10-21 16:49:17 +02001666 if (argcount > 0)
1667 {
1668 // Check the types of the arguments.
1669 argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
Bram Moolenaar351ead02021-01-16 16:07:01 +01001670 if (internal_func_check_arg_types(argtypes, func_idx, argcount,
1671 cctx) == FAIL)
Bram Moolenaar94738d82020-10-21 14:25:07 +02001672 return FAIL;
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001673 if (internal_func_is_map(func_idx))
1674 maptype = *argtypes;
Bram Moolenaaraf7a9062020-10-21 16:49:17 +02001675 }
Bram Moolenaar94738d82020-10-21 14:25:07 +02001676
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001677 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1678 return FAIL;
1679 isn->isn_arg.bfunc.cbf_idx = func_idx;
1680 isn->isn_arg.bfunc.cbf_argcount = argcount;
1681
Bram Moolenaar94738d82020-10-21 14:25:07 +02001682 // Drop the argument types and push the return type.
1683 stack->ga_len -= argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001684 if (ga_grow(stack, 1) == FAIL)
1685 return FAIL;
1686 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001687 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar94738d82020-10-21 14:25:07 +02001688 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001689
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001690 if (maptype != NULL && maptype->tt_member != NULL
1691 && maptype->tt_member != &t_any)
1692 // Check that map() didn't change the item types.
Bram Moolenaare32e5162021-01-21 20:21:29 +01001693 generate_TYPECHECK(cctx, maptype, -1, 1);
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001694
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001695 return OK;
1696}
1697
1698/*
Bram Moolenaar1dcae592020-10-19 19:02:42 +02001699 * Generate an ISN_LISTAPPEND instruction. Works like add().
1700 * Argument count is already checked.
1701 */
1702 static int
1703generate_LISTAPPEND(cctx_T *cctx)
1704{
1705 garray_T *stack = &cctx->ctx_type_stack;
1706 type_T *list_type;
1707 type_T *item_type;
1708 type_T *expected;
1709
1710 // Caller already checked that list_type is a list.
1711 list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
1712 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1713 expected = list_type->tt_member;
Bram Moolenaar351ead02021-01-16 16:07:01 +01001714 if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar1dcae592020-10-19 19:02:42 +02001715 return FAIL;
1716
1717 if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
1718 return FAIL;
1719
1720 --stack->ga_len; // drop the argument
1721 return OK;
1722}
1723
1724/*
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02001725 * Generate an ISN_BLOBAPPEND instruction. Works like add().
1726 * Argument count is already checked.
1727 */
1728 static int
1729generate_BLOBAPPEND(cctx_T *cctx)
1730{
1731 garray_T *stack = &cctx->ctx_type_stack;
1732 type_T *item_type;
1733
1734 // Caller already checked that blob_type is a blob.
1735 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar351ead02021-01-16 16:07:01 +01001736 if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02001737 return FAIL;
1738
1739 if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL)
1740 return FAIL;
1741
1742 --stack->ga_len; // drop the argument
1743 return OK;
1744}
1745
1746/*
Bram Moolenaarb2049902021-01-24 12:53:53 +01001747 * Return TRUE if "ufunc" should be compiled, taking into account whether
1748 * "profile" indicates profiling is to be done.
1749 */
1750 int
Bram Moolenaarf002a412021-01-24 13:34:18 +01001751func_needs_compiling(ufunc_T *ufunc, int profile UNUSED)
Bram Moolenaarb2049902021-01-24 12:53:53 +01001752{
1753 switch (ufunc->uf_def_status)
1754 {
Bram Moolenaarf002a412021-01-24 13:34:18 +01001755 case UF_NOT_COMPILED: break;
Bram Moolenaarb2049902021-01-24 12:53:53 +01001756 case UF_TO_BE_COMPILED: return TRUE;
1757 case UF_COMPILED:
1758 {
Bram Moolenaarf002a412021-01-24 13:34:18 +01001759#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01001760 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1761 + ufunc->uf_dfunc_idx;
1762
1763 return profile ? dfunc->df_instr_prof == NULL
1764 : dfunc->df_instr == NULL;
Bram Moolenaarf002a412021-01-24 13:34:18 +01001765#else
1766 break;
1767#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01001768 }
Bram Moolenaarf002a412021-01-24 13:34:18 +01001769 case UF_COMPILING: break;
Bram Moolenaarb2049902021-01-24 12:53:53 +01001770 }
Bram Moolenaarf002a412021-01-24 13:34:18 +01001771 return FALSE;
Bram Moolenaarb2049902021-01-24 12:53:53 +01001772}
1773
1774/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001775 * Generate an ISN_DCALL or ISN_UCALL instruction.
1776 * Return FAIL if the number of arguments is wrong.
1777 */
1778 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001779generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001780{
1781 isn_T *isn;
1782 garray_T *stack = &cctx->ctx_type_stack;
1783 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001784 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001785
Bram Moolenaar080457c2020-03-03 21:53:32 +01001786 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001787 if (argcount > regular_args && !has_varargs(ufunc))
1788 {
Bram Moolenaarb185a402020-09-18 22:42:00 +02001789 semsg(_(e_toomanyarg), printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001790 return FAIL;
1791 }
1792 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1793 {
Bram Moolenaarb185a402020-09-18 22:42:00 +02001794 semsg(_(e_toofewarg), printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001795 return FAIL;
1796 }
1797
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001798 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001799 {
1800 int i;
1801
1802 for (i = 0; i < argcount; ++i)
1803 {
1804 type_T *expected;
1805 type_T *actual;
1806
1807 if (i < regular_args)
1808 {
1809 if (ufunc->uf_arg_types == NULL)
1810 continue;
1811 expected = ufunc->uf_arg_types[i];
1812 }
Bram Moolenaar2f8cbc42020-09-16 17:22:59 +02001813 else if (ufunc->uf_va_type == NULL || ufunc->uf_va_type == &t_any)
1814 // possibly a lambda or "...: any"
Bram Moolenaar79e8db92020-08-14 22:16:33 +02001815 expected = &t_any;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001816 else
1817 expected = ufunc->uf_va_type->tt_member;
1818 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaare32e5162021-01-21 20:21:29 +01001819 if (need_type(actual, expected, -argcount + i, i + 1, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02001820 TRUE, FALSE) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001821 {
1822 arg_type_mismatch(expected, actual, i + 1);
1823 return FAIL;
1824 }
1825 }
Bram Moolenaare5ea3462021-01-25 21:01:48 +01001826 if (func_needs_compiling(ufunc, PROFILING(ufunc))
Bram Moolenaarb2049902021-01-24 12:53:53 +01001827 && compile_def_function(ufunc, ufunc->uf_ret_type == NULL,
Bram Moolenaare5ea3462021-01-25 21:01:48 +01001828 PROFILING(ufunc), NULL) == FAIL)
Bram Moolenaarb2049902021-01-24 12:53:53 +01001829 return FAIL;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001830 }
1831
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001832 if ((isn = generate_instr(cctx,
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001833 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
Bram Moolenaar822ba242020-05-24 23:00:18 +02001834 : ISN_UCALL)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001835 return FAIL;
Bram Moolenaara05e5242020-09-19 18:19:19 +02001836 if (isn->isn_type == ISN_DCALL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001837 {
1838 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1839 isn->isn_arg.dfunc.cdf_argcount = argcount;
1840 }
1841 else
1842 {
1843 // A user function may be deleted and redefined later, can't use the
1844 // ufunc pointer, need to look it up again at runtime.
1845 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1846 isn->isn_arg.ufunc.cuf_argcount = argcount;
1847 }
1848
1849 stack->ga_len -= argcount; // drop the arguments
1850 if (ga_grow(stack, 1) == FAIL)
1851 return FAIL;
1852 // add return value
1853 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1854 ++stack->ga_len;
1855
1856 return OK;
1857}
1858
1859/*
1860 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1861 */
1862 static int
1863generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1864{
1865 isn_T *isn;
1866 garray_T *stack = &cctx->ctx_type_stack;
1867
Bram Moolenaar080457c2020-03-03 21:53:32 +01001868 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001869 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1870 return FAIL;
1871 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1872 isn->isn_arg.ufunc.cuf_argcount = argcount;
1873
1874 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001875 if (ga_grow(stack, 1) == FAIL)
1876 return FAIL;
1877 // add return value
1878 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1879 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001880
1881 return OK;
1882}
1883
1884/*
1885 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001886 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001887 */
1888 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001889generate_PCALL(
1890 cctx_T *cctx,
1891 int argcount,
1892 char_u *name,
1893 type_T *type,
1894 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001895{
1896 isn_T *isn;
1897 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001898 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001899
Bram Moolenaar080457c2020-03-03 21:53:32 +01001900 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001901
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001902 if (type->tt_type == VAR_ANY)
1903 ret_type = &t_any;
1904 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001905 {
1906 if (type->tt_argcount != -1)
1907 {
1908 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1909
1910 if (argcount < type->tt_min_argcount - varargs)
1911 {
Bram Moolenaar6cf7e3b2020-10-28 14:31:16 +01001912 semsg(_(e_toofewarg), name);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001913 return FAIL;
1914 }
1915 if (!varargs && argcount > type->tt_argcount)
1916 {
Bram Moolenaar6cf7e3b2020-10-28 14:31:16 +01001917 semsg(_(e_toomanyarg), name);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001918 return FAIL;
1919 }
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01001920 if (type->tt_args != NULL)
1921 {
1922 int i;
1923
1924 for (i = 0; i < argcount; ++i)
1925 {
1926 int offset = -argcount + i - 1;
1927 type_T *actual = ((type_T **)stack->ga_data)[
1928 stack->ga_len + offset];
1929 type_T *expected;
1930
Bram Moolenaar32b3f822021-01-06 21:59:39 +01001931 if (varargs && i >= type->tt_argcount - 1)
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01001932 expected = type->tt_args[
Bram Moolenaar32b3f822021-01-06 21:59:39 +01001933 type->tt_argcount - 1]->tt_member;
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01001934 else
1935 expected = type->tt_args[i];
Bram Moolenaare32e5162021-01-21 20:21:29 +01001936 if (need_type(actual, expected, offset, i + 1,
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01001937 cctx, TRUE, FALSE) == FAIL)
1938 {
1939 arg_type_mismatch(expected, actual, i + 1);
1940 return FAIL;
1941 }
1942 }
1943 }
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001944 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001945 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001946 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001947 else
1948 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001949 semsg(_(e_not_callable_type_str), name);
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001950 return FAIL;
1951 }
1952
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001953 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1954 return FAIL;
1955 isn->isn_arg.pfunc.cpf_top = at_top;
1956 isn->isn_arg.pfunc.cpf_argcount = argcount;
1957
1958 stack->ga_len -= argcount; // drop the arguments
1959
1960 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001961 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001962
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001963 // If partial is above the arguments it must be cleared and replaced with
1964 // the return value.
1965 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1966 return FAIL;
1967
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001968 return OK;
1969}
1970
1971/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001972 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001973 */
1974 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001975generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001976{
1977 isn_T *isn;
1978 garray_T *stack = &cctx->ctx_type_stack;
1979 type_T *type;
1980
Bram Moolenaar080457c2020-03-03 21:53:32 +01001981 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001982 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001983 return FAIL;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001984 isn->isn_arg.string = vim_strnsave(name, len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001985
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001986 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001987 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001988 if (type->tt_type != VAR_DICT && type != &t_any)
1989 {
1990 emsg(_(e_dictreq));
1991 return FAIL;
1992 }
1993 // change dict type to dict member type
1994 if (type->tt_type == VAR_DICT)
Bram Moolenaar31a11b92021-01-10 19:23:27 +01001995 {
1996 ((type_T **)stack->ga_data)[stack->ga_len - 1] =
1997 type->tt_member == &t_unknown ? &t_any : type->tt_member;
1998 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001999
2000 return OK;
2001}
2002
2003/*
2004 * Generate an ISN_ECHO instruction.
2005 */
2006 static int
2007generate_ECHO(cctx_T *cctx, int with_white, int count)
2008{
2009 isn_T *isn;
2010
Bram Moolenaar080457c2020-03-03 21:53:32 +01002011 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002012 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
2013 return FAIL;
2014 isn->isn_arg.echo.echo_with_white = with_white;
2015 isn->isn_arg.echo.echo_count = count;
2016
2017 return OK;
2018}
2019
Bram Moolenaarad39c092020-02-26 18:23:43 +01002020/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002021 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01002022 */
2023 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002024generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01002025{
2026 isn_T *isn;
2027
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002028 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01002029 return FAIL;
2030 isn->isn_arg.number = count;
2031
2032 return OK;
2033}
2034
Bram Moolenaarc3516f72020-09-08 22:45:35 +02002035/*
2036 * Generate an ISN_PUT instruction.
2037 */
2038 static int
2039generate_PUT(cctx_T *cctx, int regname, linenr_T lnum)
2040{
2041 isn_T *isn;
2042
2043 RETURN_OK_IF_SKIP(cctx);
2044 if ((isn = generate_instr(cctx, ISN_PUT)) == NULL)
2045 return FAIL;
2046 isn->isn_arg.put.put_regname = regname;
2047 isn->isn_arg.put.put_lnum = lnum;
2048 return OK;
2049}
2050
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002051 static int
2052generate_EXEC(cctx_T *cctx, char_u *line)
2053{
2054 isn_T *isn;
2055
Bram Moolenaar080457c2020-03-03 21:53:32 +01002056 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002057 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
2058 return FAIL;
2059 isn->isn_arg.string = vim_strsave(line);
2060 return OK;
2061}
2062
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002063 static int
2064generate_EXECCONCAT(cctx_T *cctx, int count)
2065{
2066 isn_T *isn;
2067
2068 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
2069 return FAIL;
2070 isn->isn_arg.number = count;
2071 return OK;
2072}
2073
Bram Moolenaar08597872020-12-10 19:43:40 +01002074/*
2075 * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
2076 */
2077 static int
2078generate_RANGE(cctx_T *cctx, char_u *range)
2079{
2080 isn_T *isn;
2081 garray_T *stack = &cctx->ctx_type_stack;
2082
2083 if ((isn = generate_instr(cctx, ISN_RANGE)) == NULL)
2084 return FAIL;
2085 isn->isn_arg.string = range;
2086
2087 if (ga_grow(stack, 1) == FAIL)
2088 return FAIL;
2089 ((type_T **)stack->ga_data)[stack->ga_len] = &t_number;
2090 ++stack->ga_len;
2091 return OK;
2092}
2093
Bram Moolenaar792f7862020-11-23 08:31:18 +01002094 static int
2095generate_UNPACK(cctx_T *cctx, int var_count, int semicolon)
2096{
2097 isn_T *isn;
2098
2099 RETURN_OK_IF_SKIP(cctx);
2100 if ((isn = generate_instr(cctx, ISN_UNPACK)) == NULL)
2101 return FAIL;
2102 isn->isn_arg.unpack.unp_count = var_count;
2103 isn->isn_arg.unpack.unp_semicolon = semicolon;
2104 return OK;
2105}
2106
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002107/*
Bram Moolenaar02194d22020-10-24 23:08:38 +02002108 * Generate an instruction for any command modifiers.
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002109 */
2110 static int
Bram Moolenaare1004402020-10-24 20:49:43 +02002111generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002112{
2113 isn_T *isn;
2114
Bram Moolenaar02194d22020-10-24 23:08:38 +02002115 if (cmod->cmod_flags != 0
2116 || cmod->cmod_split != 0
2117 || cmod->cmod_verbose != 0
2118 || cmod->cmod_tab != 0
2119 || cmod->cmod_filter_regmatch.regprog != NULL)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002120 {
Bram Moolenaar02194d22020-10-24 23:08:38 +02002121 cctx->ctx_has_cmdmod = TRUE;
2122
2123 if ((isn = generate_instr(cctx, ISN_CMDMOD)) == NULL)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002124 return FAIL;
Bram Moolenaar02194d22020-10-24 23:08:38 +02002125 isn->isn_arg.cmdmod.cf_cmdmod = ALLOC_ONE(cmdmod_T);
2126 if (isn->isn_arg.cmdmod.cf_cmdmod == NULL)
2127 return FAIL;
2128 mch_memmove(isn->isn_arg.cmdmod.cf_cmdmod, cmod, sizeof(cmdmod_T));
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01002129 // filter program now belongs to the instruction
Bram Moolenaar02194d22020-10-24 23:08:38 +02002130 cmod->cmod_filter_regmatch.regprog = NULL;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002131 }
Bram Moolenaar02194d22020-10-24 23:08:38 +02002132
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002133 return OK;
2134}
2135
2136 static int
Bram Moolenaar02194d22020-10-24 23:08:38 +02002137generate_undo_cmdmods(cctx_T *cctx)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002138{
Bram Moolenaarf665e972020-12-05 19:17:16 +01002139 if (cctx->ctx_has_cmdmod && generate_instr(cctx, ISN_CMDMOD_REV) == NULL)
2140 return FAIL;
Bram Moolenaar7cd24222021-01-12 18:58:39 +01002141 cctx->ctx_has_cmdmod = FALSE;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002142 return OK;
2143}
2144
Bram Moolenaarf002a412021-01-24 13:34:18 +01002145#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01002146 static void
2147may_generate_prof_end(cctx_T *cctx, int prof_lnum)
2148{
2149 if (cctx->ctx_profiling && prof_lnum >= 0)
Bram Moolenaarb2049902021-01-24 12:53:53 +01002150 generate_instr(cctx, ISN_PROF_END);
Bram Moolenaarb2049902021-01-24 12:53:53 +01002151}
Bram Moolenaarf002a412021-01-24 13:34:18 +01002152#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01002153
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002154/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002155 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002156 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002157 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002158 static lvar_T *
Bram Moolenaare8211a32020-10-09 22:04:29 +02002159reserve_local(
2160 cctx_T *cctx,
2161 char_u *name,
2162 size_t len,
2163 int isConst,
2164 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002165{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002166 lvar_T *lvar;
2167
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002168 if (arg_exists(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002169 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002170 emsg_namelen(_(e_str_is_used_as_argument), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002171 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002172 }
2173
2174 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002175 return NULL;
2176 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaare8211a32020-10-09 22:04:29 +02002177 CLEAR_POINTER(lvar);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002178
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002179 // Every local variable uses the next entry on the stack. We could re-use
2180 // the last ones when leaving a scope, but then variables used in a closure
2181 // might get overwritten. To keep things simple do not re-use stack
2182 // entries. This is less efficient, but memory is cheap these days.
2183 lvar->lv_idx = cctx->ctx_locals_count++;
2184
Bram Moolenaar71ccd032020-06-12 22:59:11 +02002185 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002186 lvar->lv_const = isConst;
2187 lvar->lv_type = type;
2188
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002189 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002190}
2191
2192/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002193 * Remove local variables above "new_top".
2194 */
2195 static void
2196unwind_locals(cctx_T *cctx, int new_top)
2197{
2198 if (cctx->ctx_locals.ga_len > new_top)
2199 {
2200 int idx;
2201 lvar_T *lvar;
2202
2203 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
2204 {
2205 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
2206 vim_free(lvar->lv_name);
2207 }
2208 }
2209 cctx->ctx_locals.ga_len = new_top;
2210}
2211
2212/*
2213 * Free all local variables.
2214 */
2215 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002216free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01002217{
2218 unwind_locals(cctx, 0);
2219 ga_clear(&cctx->ctx_locals);
2220}
2221
2222/*
Bram Moolenaar08251752021-01-11 21:20:18 +01002223 * If "check_writable" is ASSIGN_CONST give an error if the variable was
2224 * defined with :final or :const, if "check_writable" is ASSIGN_FINAL give an
2225 * error if the variable was defined with :const.
2226 */
2227 static int
2228check_item_writable(svar_T *sv, int check_writable, char_u *name)
2229{
2230 if ((check_writable == ASSIGN_CONST && sv->sv_const != 0)
2231 || (check_writable == ASSIGN_FINAL
2232 && sv->sv_const == ASSIGN_CONST))
2233 {
2234 semsg(_(e_readonlyvar), name);
2235 return FAIL;
2236 }
2237 return OK;
2238}
2239
2240/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002241 * Find "name" in script-local items of script "sid".
Bram Moolenaar08251752021-01-11 21:20:18 +01002242 * Pass "check_writable" to check_item_writable().
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002243 * Returns the index in "sn_var_vals" if found.
2244 * If found but not in "sn_var_vals" returns -1.
Bram Moolenaar08251752021-01-11 21:20:18 +01002245 * If not found or the variable is not writable returns -2.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002246 */
2247 int
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002248get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002249{
2250 hashtab_T *ht;
2251 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002252 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002253 svar_T *sv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002254 int idx;
2255
Bram Moolenaare3d46852020-08-29 13:39:17 +02002256 if (!SCRIPT_ID_VALID(sid))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002257 return -1;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002258 if (sid == current_sctx.sc_sid)
2259 {
Bram Moolenaar209f0202020-10-15 13:57:56 +02002260 sallvar_T *sav = find_script_var(name, 0, cctx);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002261
2262 if (sav == NULL)
2263 return -2;
2264 idx = sav->sav_var_vals_idx;
2265 sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
Bram Moolenaar08251752021-01-11 21:20:18 +01002266 if (check_item_writable(sv, check_writable, name) == FAIL)
2267 return -2;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002268 return idx;
2269 }
2270
2271 // First look the name up in the hashtable.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002272 ht = &SCRIPT_VARS(sid);
2273 di = find_var_in_ht(ht, 0, name, TRUE);
2274 if (di == NULL)
2275 return -2;
2276
2277 // Now find the svar_T index in sn_var_vals.
2278 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2279 {
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002280 sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002281 if (sv->sv_tv == &di->di_tv)
2282 {
Bram Moolenaar08251752021-01-11 21:20:18 +01002283 if (check_item_writable(sv, check_writable, name) == FAIL)
2284 return -2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002285 return idx;
2286 }
2287 }
2288 return -1;
2289}
2290
2291/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02002292 * Find "name" in imported items of the current script or in "cctx" if not
2293 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002294 */
2295 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002296find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002297{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002298 int idx;
2299
Bram Moolenaare3d46852020-08-29 13:39:17 +02002300 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02002301 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002302 if (cctx != NULL)
2303 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2304 {
2305 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2306 + idx;
2307
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002308 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2309 : STRLEN(import->imp_name) == len
2310 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002311 return import;
2312 }
2313
Bram Moolenaarefa94442020-08-08 22:16:00 +02002314 return find_imported_in_script(name, len, current_sctx.sc_sid);
2315}
2316
2317 imported_T *
2318find_imported_in_script(char_u *name, size_t len, int sid)
2319{
Bram Moolenaare3d46852020-08-29 13:39:17 +02002320 scriptitem_T *si;
Bram Moolenaarefa94442020-08-08 22:16:00 +02002321 int idx;
2322
Bram Moolenaare3d46852020-08-29 13:39:17 +02002323 if (!SCRIPT_ID_VALID(sid))
2324 return NULL;
2325 si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002326 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2327 {
2328 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2329
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002330 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2331 : STRLEN(import->imp_name) == len
2332 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002333 return import;
2334 }
2335 return NULL;
2336}
2337
2338/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002339 * Free all imported variables.
2340 */
2341 static void
2342free_imported(cctx_T *cctx)
2343{
2344 int idx;
2345
2346 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2347 {
2348 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2349
2350 vim_free(import->imp_name);
2351 }
2352 ga_clear(&cctx->ctx_imports);
2353}
2354
2355/*
Bram Moolenaar23c55272020-06-21 16:58:13 +02002356 * Return a pointer to the next line that isn't empty or only contains a
2357 * comment. Skips over white space.
2358 * Returns NULL if there is none.
2359 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002360 char_u *
2361peek_next_line_from_context(cctx_T *cctx)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002362{
2363 int lnum = cctx->ctx_lnum;
2364
2365 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
2366 {
2367 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002368 char_u *p;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002369
Bram Moolenaarba60cc42020-08-12 19:15:33 +02002370 // ignore NULLs inserted for continuation lines
2371 if (line != NULL)
2372 {
2373 p = skipwhite(line);
2374 if (*p != NUL && !vim9_comment_start(p))
2375 return p;
2376 }
Bram Moolenaar23c55272020-06-21 16:58:13 +02002377 }
2378 return NULL;
2379}
2380
2381/*
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002382 * Called when checking for a following operator at "arg". When the rest of
2383 * the line is empty or only a comment, peek the next line. If there is a next
2384 * line return a pointer to it and set "nextp".
2385 * Otherwise skip over white space.
2386 */
2387 static char_u *
2388may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
2389{
2390 char_u *p = skipwhite(arg);
2391
2392 *nextp = NULL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002393 if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002394 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002395 *nextp = peek_next_line_from_context(cctx);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002396 if (*nextp != NULL)
2397 return *nextp;
2398 }
2399 return p;
2400}
2401
2402/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002403 * Get the next line of the function from "cctx".
Bram Moolenaar23c55272020-06-21 16:58:13 +02002404 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
Bram Moolenaare6085c52020-04-12 20:19:16 +02002405 * Returns NULL when at the end.
2406 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002407 char_u *
Bram Moolenaar23c55272020-06-21 16:58:13 +02002408next_line_from_context(cctx_T *cctx, int skip_comment)
Bram Moolenaare6085c52020-04-12 20:19:16 +02002409{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002410 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002411
2412 do
2413 {
2414 ++cctx->ctx_lnum;
2415 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002416 {
2417 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002418 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002419 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002420 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002421 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02002422 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002423 } while (line == NULL || *skipwhite(line) == NUL
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002424 || (skip_comment && vim9_comment_start(skipwhite(line))));
Bram Moolenaare6085c52020-04-12 20:19:16 +02002425 return line;
2426}
2427
2428/*
Bram Moolenaar5afd0812021-01-03 18:33:13 +01002429 * Skip over white space at "whitep" and assign to "*arg".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002430 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002431 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002432 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2433 */
2434 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002435may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002436{
Bram Moolenaar5afd0812021-01-03 18:33:13 +01002437 *arg = skipwhite(whitep);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002438 if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002439 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002440 char_u *next = next_line_from_context(cctx, TRUE);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002441
2442 if (next == NULL)
2443 return FAIL;
2444 *arg = skipwhite(next);
2445 }
2446 return OK;
2447}
2448
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002449/*
2450 * Idem, and give an error when failed.
2451 */
2452 static int
2453may_get_next_line_error(char_u *whitep, char_u **arg, cctx_T *cctx)
2454{
2455 if (may_get_next_line(whitep, arg, cctx) == FAIL)
2456 {
Bram Moolenaar8ff16e02020-12-07 21:49:52 +01002457 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002458 emsg(_(e_line_incomplete));
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002459 return FAIL;
2460 }
2461 return OK;
2462}
2463
2464
Bram Moolenaara5565e42020-05-09 15:44:01 +02002465// Structure passed between the compile_expr* functions to keep track of
2466// constants that have been parsed but for which no code was produced yet. If
2467// possible expressions on these constants are applied at compile time. If
2468// that is not possible, the code to push the constants needs to be generated
2469// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002470// Using 50 should be more than enough of 5 levels of ().
2471#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002472typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002473 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002474 int pp_used; // active entries in pp_tv[]
Bram Moolenaar334a8b42020-10-19 16:07:42 +02002475 int pp_is_const; // all generated code was constants, used for a
2476 // list or dict with constant members
Bram Moolenaara5565e42020-05-09 15:44:01 +02002477} ppconst_T;
2478
Bram Moolenaar334a8b42020-10-19 16:07:42 +02002479static int compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const);
Bram Moolenaar1c747212020-05-09 18:28:34 +02002480static int compile_expr0(char_u **arg, cctx_T *cctx);
2481static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2482
Bram Moolenaara5565e42020-05-09 15:44:01 +02002483/*
2484 * Generate a PUSH instruction for "tv".
2485 * "tv" will be consumed or cleared.
2486 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2487 */
2488 static int
2489generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2490{
2491 if (tv != NULL)
2492 {
2493 switch (tv->v_type)
2494 {
2495 case VAR_UNKNOWN:
2496 break;
2497 case VAR_BOOL:
2498 generate_PUSHBOOL(cctx, tv->vval.v_number);
2499 break;
2500 case VAR_SPECIAL:
2501 generate_PUSHSPEC(cctx, tv->vval.v_number);
2502 break;
2503 case VAR_NUMBER:
2504 generate_PUSHNR(cctx, tv->vval.v_number);
2505 break;
2506#ifdef FEAT_FLOAT
2507 case VAR_FLOAT:
2508 generate_PUSHF(cctx, tv->vval.v_float);
2509 break;
2510#endif
2511 case VAR_BLOB:
2512 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2513 tv->vval.v_blob = NULL;
2514 break;
2515 case VAR_STRING:
2516 generate_PUSHS(cctx, tv->vval.v_string);
2517 tv->vval.v_string = NULL;
2518 break;
2519 default:
2520 iemsg("constant type not supported");
2521 clear_tv(tv);
2522 return FAIL;
2523 }
2524 tv->v_type = VAR_UNKNOWN;
2525 }
2526 return OK;
2527}
2528
2529/*
2530 * Generate code for any ppconst entries.
2531 */
2532 static int
2533generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2534{
2535 int i;
2536 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002537 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002538
Bram Moolenaar9b68c822020-06-18 19:31:08 +02002539 cctx->ctx_skip = SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002540 for (i = 0; i < ppconst->pp_used; ++i)
2541 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2542 ret = FAIL;
2543 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002544 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002545 return ret;
2546}
2547
2548/*
2549 * Clear ppconst constants. Used when failing.
2550 */
2551 static void
2552clear_ppconst(ppconst_T *ppconst)
2553{
2554 int i;
2555
2556 for (i = 0; i < ppconst->pp_used; ++i)
2557 clear_tv(&ppconst->pp_tv[i]);
2558 ppconst->pp_used = 0;
2559}
2560
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002561/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002562 * Generate an instruction to load script-local variable "name", without the
2563 * leading "s:".
2564 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002565 */
2566 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002567compile_load_scriptvar(
2568 cctx_T *cctx,
2569 char_u *name, // variable NUL terminated
2570 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002571 char_u **end, // end of variable
2572 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002573{
Bram Moolenaare3d46852020-08-29 13:39:17 +02002574 scriptitem_T *si;
2575 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002576 imported_T *import;
2577
Bram Moolenaare3d46852020-08-29 13:39:17 +02002578 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
2579 return FAIL;
2580 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar08251752021-01-11 21:20:18 +01002581 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002582 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002583 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002584 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002585 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2586 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002587 }
2588 if (idx >= 0)
2589 {
2590 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2591
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002592 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002593 current_sctx.sc_sid, idx, sv->sv_type);
2594 return OK;
2595 }
2596
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002597 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002598 if (import != NULL)
2599 {
Bram Moolenaara6294952020-12-27 13:39:50 +01002600 if (import->imp_flags & IMP_FLAGS_STAR)
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002601 {
2602 char_u *p = skipwhite(*end);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002603 char_u *exp_name;
2604 int cc;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002605 ufunc_T *ufunc;
2606 type_T *type;
2607
2608 // Used "import * as Name", need to lookup the member.
2609 if (*p != '.')
2610 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002611 semsg(_(e_expected_dot_after_name_str), start);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002612 return FAIL;
2613 }
2614 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002615 if (VIM_ISWHITE(*p))
2616 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002617 emsg(_(e_no_white_space_allowed_after_dot));
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002618 return FAIL;
2619 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002620
Bram Moolenaar1c991142020-07-04 13:15:31 +02002621 // isolate one name
2622 exp_name = p;
2623 while (eval_isnamec(*p))
2624 ++p;
2625 cc = *p;
2626 *p = NUL;
2627
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002628 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type, cctx);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002629 *p = cc;
2630 p = skipwhite(p);
2631
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002632 // TODO: what if it is a function?
2633 if (idx < 0)
2634 return FAIL;
2635 *end = p;
2636
2637 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2638 import->imp_sid,
2639 idx,
2640 type);
2641 }
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002642 else if (import->imp_funcname != NULL)
2643 generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002644 else
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002645 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2646 import->imp_sid,
2647 import->imp_var_vals_idx,
2648 import->imp_type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002649 return OK;
2650 }
2651
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002652 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002653 semsg(_(e_item_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002654 return FAIL;
2655}
2656
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002657 static int
2658generate_funcref(cctx_T *cctx, char_u *name)
2659{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002660 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002661
2662 if (ufunc == NULL)
2663 return FAIL;
2664
Bram Moolenaarb8070e32020-07-23 20:56:04 +02002665 // Need to compile any default values to get the argument types.
Bram Moolenaare5ea3462021-01-25 21:01:48 +01002666 if (func_needs_compiling(ufunc, PROFILING(ufunc))
2667 && compile_def_function(ufunc, TRUE, PROFILING(ufunc), NULL)
Bram Moolenaarb2049902021-01-24 12:53:53 +01002668 == FAIL)
2669 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002670 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002671}
2672
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002673/*
2674 * Compile a variable name into a load instruction.
2675 * "end" points to just after the name.
Bram Moolenaar0f769812020-09-12 18:32:34 +02002676 * "is_expr" is TRUE when evaluating an expression, might be a funcref.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002677 * When "error" is FALSE do not give an error when not found.
2678 */
2679 static int
Bram Moolenaar0f769812020-09-12 18:32:34 +02002680compile_load(
2681 char_u **arg,
2682 char_u *end_arg,
2683 cctx_T *cctx,
2684 int is_expr,
2685 int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002686{
2687 type_T *type;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002688 char_u *name = NULL;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002689 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002690 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002691 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002692
2693 if (*(*arg + 1) == ':')
2694 {
2695 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002696 if (end <= *arg + 2)
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002697 {
2698 isntype_T isn_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002699
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002700 switch (**arg)
2701 {
2702 case 'g': isn_type = ISN_LOADGDICT; break;
2703 case 'w': isn_type = ISN_LOADWDICT; break;
2704 case 't': isn_type = ISN_LOADTDICT; break;
2705 case 'b': isn_type = ISN_LOADBDICT; break;
2706 default:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002707 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002708 goto theend;
2709 }
2710 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
2711 goto theend;
2712 res = OK;
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002713 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002714 else
2715 {
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002716 isntype_T isn_type = ISN_DROP;
2717
2718 name = vim_strnsave(*arg + 2, end - (*arg + 2));
2719 if (name == NULL)
2720 return FAIL;
2721
2722 switch (**arg)
2723 {
2724 case 'v': res = generate_LOADV(cctx, name, error);
2725 break;
2726 case 's': res = compile_load_scriptvar(cctx, name,
2727 NULL, NULL, error);
2728 break;
Bram Moolenaar03290b82020-12-19 16:30:44 +01002729 case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
2730 isn_type = ISN_LOADG;
2731 else
2732 {
2733 isn_type = ISN_LOADAUTO;
2734 vim_free(name);
2735 name = vim_strnsave(*arg, end - *arg);
2736 if (name == NULL)
2737 return FAIL;
2738 }
2739 break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002740 case 'w': isn_type = ISN_LOADW; break;
2741 case 't': isn_type = ISN_LOADT; break;
2742 case 'b': isn_type = ISN_LOADB; break;
Bram Moolenaar918a4242020-12-06 14:37:08 +01002743 default: // cannot happen, just in case
2744 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002745 goto theend;
2746 }
2747 if (isn_type != ISN_DROP)
2748 {
2749 // Global, Buffer-local, Window-local and Tabpage-local
2750 // variables can be defined later, thus we don't check if it
2751 // exists, give error at runtime.
2752 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
2753 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002754 }
2755 }
2756 else
2757 {
2758 size_t len = end - *arg;
2759 int idx;
2760 int gen_load = FALSE;
Bram Moolenaarab360522021-01-10 14:02:28 +01002761 int gen_load_outer = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002762
2763 name = vim_strnsave(*arg, end - *arg);
2764 if (name == NULL)
2765 return FAIL;
2766
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002767 if (arg_exists(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002768 {
Bram Moolenaarab360522021-01-10 14:02:28 +01002769 if (gen_load_outer == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002770 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002771 }
2772 else
2773 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01002774 lvar_T lvar;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002775
Bram Moolenaar709664c2020-12-12 14:33:41 +01002776 if (lookup_local(*arg, len, &lvar, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002777 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01002778 type = lvar.lv_type;
2779 idx = lvar.lv_idx;
Bram Moolenaarab360522021-01-10 14:02:28 +01002780 if (lvar.lv_from_outer != 0)
2781 gen_load_outer = lvar.lv_from_outer;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002782 else
2783 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002784 }
2785 else
2786 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02002787 // "var" can be script-local even without using "s:" if it
Bram Moolenaar53900992020-08-22 19:02:02 +02002788 // already exists in a Vim9 script or when it's imported.
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002789 if (script_var_exists(*arg, len, TRUE, cctx) == OK
Bram Moolenaar53900992020-08-22 19:02:02 +02002790 || find_imported(name, 0, cctx) != NULL)
2791 res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002792
Bram Moolenaar0f769812020-09-12 18:32:34 +02002793 // When evaluating an expression and the name starts with an
2794 // uppercase letter or "x:" it can be a user defined function.
Bram Moolenaar53900992020-08-22 19:02:02 +02002795 // TODO: this is just guessing
Bram Moolenaar0f769812020-09-12 18:32:34 +02002796 if (res == FAIL && is_expr
2797 && (ASCII_ISUPPER(*name) || name[1] == ':'))
Bram Moolenaara5565e42020-05-09 15:44:01 +02002798 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002799 }
2800 }
2801 if (gen_load)
2802 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarab360522021-01-10 14:02:28 +01002803 if (gen_load_outer > 0)
Bram Moolenaarfd777482020-08-12 19:42:01 +02002804 {
Bram Moolenaarab360522021-01-10 14:02:28 +01002805 res = generate_LOADOUTER(cctx, idx, gen_load_outer, type);
Bram Moolenaarfd777482020-08-12 19:42:01 +02002806 cctx->ctx_outer_used = TRUE;
2807 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002808 }
2809
2810 *arg = end;
2811
2812theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002813 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002814 semsg(_(e_variable_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002815 vim_free(name);
2816 return res;
2817}
2818
2819/*
2820 * Compile the argument expressions.
2821 * "arg" points to just after the "(" and is advanced to after the ")"
2822 */
2823 static int
2824compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2825{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002826 char_u *p = *arg;
2827 char_u *whitep = *arg;
Bram Moolenaar10e4f122020-09-20 22:43:52 +02002828 int must_end = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002829
Bram Moolenaare6085c52020-04-12 20:19:16 +02002830 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002831 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002832 if (may_get_next_line(whitep, &p, cctx) == FAIL)
2833 goto failret;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002834 if (*p == ')')
2835 {
2836 *arg = p + 1;
2837 return OK;
2838 }
Bram Moolenaar10e4f122020-09-20 22:43:52 +02002839 if (must_end)
2840 {
2841 semsg(_(e_missing_comma_before_argument_str), p);
2842 return FAIL;
2843 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002844
Bram Moolenaara5565e42020-05-09 15:44:01 +02002845 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002846 return FAIL;
2847 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002848
2849 if (*p != ',' && *skipwhite(p) == ',')
2850 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01002851 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002852 p = skipwhite(p);
2853 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002854 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002855 {
2856 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002857 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01002858 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002859 }
Bram Moolenaar10e4f122020-09-20 22:43:52 +02002860 else
2861 must_end = TRUE;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002862 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002863 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002864 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002865failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002866 emsg(_(e_missing_close));
2867 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002868}
2869
2870/*
2871 * Compile a function call: name(arg1, arg2)
2872 * "arg" points to "name", "arg + varlen" to the "(".
2873 * "argcount_init" is 1 for "value->method()"
2874 * Instructions:
2875 * EVAL arg1
2876 * EVAL arg2
2877 * BCALL / DCALL / UCALL
2878 */
2879 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02002880compile_call(
2881 char_u **arg,
2882 size_t varlen,
2883 cctx_T *cctx,
2884 ppconst_T *ppconst,
2885 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002886{
2887 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002888 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002889 int argcount = argcount_init;
2890 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002891 char_u fname_buf[FLEN_FIXED + 1];
2892 char_u *tofree = NULL;
2893 int error = FCERR_NONE;
Bram Moolenaarb3a01942020-11-17 19:56:09 +01002894 ufunc_T *ufunc = NULL;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002895 int res = FAIL;
Bram Moolenaara1773442020-08-12 15:21:22 +02002896 int is_autoload;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002897
Bram Moolenaara5565e42020-05-09 15:44:01 +02002898 // we can evaluate "has('name')" at compile time
2899 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
2900 {
2901 char_u *s = skipwhite(*arg + varlen + 1);
2902 typval_T argvars[2];
2903
2904 argvars[0].v_type = VAR_UNKNOWN;
2905 if (*s == '"')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002906 (void)eval_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002907 else if (*s == '\'')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002908 (void)eval_lit_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002909 s = skipwhite(s);
Bram Moolenaar8cebd432020-11-08 12:49:47 +01002910 if (*s == ')' && argvars[0].v_type == VAR_STRING
2911 && !dynamic_feature(argvars[0].vval.v_string))
Bram Moolenaara5565e42020-05-09 15:44:01 +02002912 {
2913 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
2914
2915 *arg = s + 1;
2916 argvars[1].v_type = VAR_UNKNOWN;
2917 tv->v_type = VAR_NUMBER;
2918 tv->vval.v_number = 0;
2919 f_has(argvars, tv);
2920 clear_tv(&argvars[0]);
2921 ++ppconst->pp_used;
2922 return OK;
2923 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002924 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002925 }
2926
2927 if (generate_ppconst(cctx, ppconst) == FAIL)
2928 return FAIL;
2929
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002930 if (varlen >= sizeof(namebuf))
2931 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002932 semsg(_(e_name_too_long_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002933 return FAIL;
2934 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002935 vim_strncpy(namebuf, *arg, varlen);
2936 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002937
2938 *arg = skipwhite(*arg + varlen + 1);
2939 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002940 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002941
Bram Moolenaar03290b82020-12-19 16:30:44 +01002942 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
Bram Moolenaara1773442020-08-12 15:21:22 +02002943 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002944 {
2945 int idx;
2946
2947 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002948 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002949 if (idx >= 0)
Bram Moolenaar1dcae592020-10-19 19:02:42 +02002950 {
Bram Moolenaar3b690062021-02-01 20:14:51 +01002951 if (STRCMP(name, "flatten") == 0)
2952 {
2953 emsg(_(e_cannot_use_flatten_in_vim9_script));
2954 goto theend;
2955 }
2956
Bram Moolenaar1dcae592020-10-19 19:02:42 +02002957 if (STRCMP(name, "add") == 0 && argcount == 2)
2958 {
2959 garray_T *stack = &cctx->ctx_type_stack;
2960 type_T *type = ((type_T **)stack->ga_data)[
2961 stack->ga_len - 2];
2962
Bram Moolenaare88c8e82020-11-01 17:03:37 +01002963 // add() can be compiled to instructions if we know the type
Bram Moolenaar1dcae592020-10-19 19:02:42 +02002964 if (type->tt_type == VAR_LIST)
2965 {
2966 // inline "add(list, item)" so that the type can be checked
2967 res = generate_LISTAPPEND(cctx);
2968 idx = -1;
2969 }
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02002970 else if (type->tt_type == VAR_BLOB)
2971 {
2972 // inline "add(blob, nr)" so that the type can be checked
2973 res = generate_BLOBAPPEND(cctx);
2974 idx = -1;
2975 }
Bram Moolenaar1dcae592020-10-19 19:02:42 +02002976 }
2977
2978 if (idx >= 0)
2979 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
2980 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002981 else
2982 semsg(_(e_unknownfunc), namebuf);
2983 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002984 }
2985
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01002986 // An argument or local variable can be a function reference, this
2987 // overrules a function name.
Bram Moolenaar709664c2020-12-12 14:33:41 +01002988 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01002989 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002990 {
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01002991 // If we can find the function by name generate the right call.
2992 // Skip global functions here, a local funcref takes precedence.
2993 ufunc = find_func(name, FALSE, cctx);
2994 if (ufunc != NULL && !func_is_global(ufunc))
2995 {
2996 res = generate_CALL(cctx, ufunc, argcount);
2997 goto theend;
2998 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002999 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003000
3001 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02003002 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaara1773442020-08-12 15:21:22 +02003003 // Not for eome#Func(), it will be loaded later.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003004 p = namebuf;
Bram Moolenaara1773442020-08-12 15:21:22 +02003005 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
Bram Moolenaar0f769812020-09-12 18:32:34 +02003006 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003007 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003008 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003009 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003010
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003011 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003012 goto theend;
3013 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003014
Bram Moolenaar0f769812020-09-12 18:32:34 +02003015 // If we can find a global function by name generate the right call.
3016 if (ufunc != NULL)
3017 {
3018 res = generate_CALL(cctx, ufunc, argcount);
3019 goto theend;
3020 }
3021
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003022 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003023 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaara1773442020-08-12 15:21:22 +02003024 if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload)
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003025 res = generate_UCALL(cctx, name, argcount);
3026 else
3027 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003028
3029theend:
3030 vim_free(tofree);
3031 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003032}
3033
3034// like NAMESPACE_CHAR but with 'a' and 'l'.
3035#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
3036
3037/*
3038 * Find the end of a variable or function name. Unlike find_name_end() this
3039 * does not recognize magic braces.
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003040 * When "use_namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003041 * Return a pointer to just after the name. Equal to "arg" if there is no
3042 * valid name.
3043 */
Bram Moolenaar2bede172020-11-19 18:53:18 +01003044 char_u *
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003045to_name_end(char_u *arg, int use_namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003046{
3047 char_u *p;
3048
3049 // Quick check for valid starting character.
3050 if (!eval_isnamec1(*arg))
3051 return arg;
3052
3053 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
3054 // Include a namespace such as "s:var" and "v:var". But "n:" is not
3055 // and can be used in slice "[n:]".
3056 if (*p == ':' && (p != arg + 1
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003057 || !use_namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003058 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
3059 break;
3060 return p;
3061}
3062
3063/*
3064 * Like to_name_end() but also skip over a list or dict constant.
Bram Moolenaar1c991142020-07-04 13:15:31 +02003065 * This intentionally does not handle line continuation.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003066 */
3067 char_u *
3068to_name_const_end(char_u *arg)
3069{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003070 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003071 typval_T rettv;
3072
3073 if (p == arg && *arg == '[')
3074 {
3075
3076 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003077 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003078 p = arg;
3079 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003080 return p;
3081}
3082
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003083/*
3084 * parse a list: [expr, expr]
3085 * "*arg" points to the '['.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003086 * ppconst->pp_is_const is set if all items are a constant.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003087 */
3088 static int
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003089compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003090{
3091 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003092 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003093 int count = 0;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003094 int is_const;
3095 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003096
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003097 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003098 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003099 if (may_get_next_line(whitep, &p, cctx) == FAIL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01003100 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003101 semsg(_(e_list_end), *arg);
3102 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003103 }
Bram Moolenaardb199212020-08-12 18:01:53 +02003104 if (*p == ',')
3105 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003106 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
Bram Moolenaardb199212020-08-12 18:01:53 +02003107 return FAIL;
3108 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003109 if (*p == ']')
3110 {
3111 ++p;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003112 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01003113 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003114 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL)
Bram Moolenaarc1f00662020-10-03 13:41:53 +02003115 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003116 if (!is_const)
3117 is_all_const = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003118 ++count;
3119 if (*p == ',')
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003120 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003121 ++p;
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003122 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
3123 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003124 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003125 return FAIL;
3126 }
3127 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003128 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003129 p = skipwhite(p);
3130 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003131 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003132
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003133 ppconst->pp_is_const = is_all_const;
3134 return generate_NEWLIST(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003135}
3136
3137/*
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01003138 * Parse a lambda: "(arg, arg) => expr"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003139 * "*arg" points to the '{'.
Bram Moolenaare462f522020-12-27 14:43:30 +01003140 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003141 */
3142 static int
3143compile_lambda(char_u **arg, cctx_T *cctx)
3144{
Bram Moolenaare462f522020-12-27 14:43:30 +01003145 int r;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003146 typval_T rettv;
3147 ufunc_T *ufunc;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003148 evalarg_T evalarg;
3149
3150 CLEAR_FIELD(evalarg);
3151 evalarg.eval_flags = EVAL_EVALUATE;
3152 evalarg.eval_cctx = cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003153
3154 // Get the funcref in "rettv".
Bram Moolenaare462f522020-12-27 14:43:30 +01003155 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
3156 if (r != OK)
Bram Moolenaar2ea79ad2020-10-18 23:32:13 +02003157 {
3158 clear_evalarg(&evalarg, NULL);
Bram Moolenaare462f522020-12-27 14:43:30 +01003159 return r;
Bram Moolenaar2ea79ad2020-10-18 23:32:13 +02003160 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01003161
Bram Moolenaar65c44152020-12-24 15:14:01 +01003162 // "rettv" will now be a partial referencing the function.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003163 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003164 ++ufunc->uf_refcount;
3165 clear_tv(&rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003166
Bram Moolenaar65c44152020-12-24 15:14:01 +01003167 // Compile the function into instructions.
Bram Moolenaare5ea3462021-01-25 21:01:48 +01003168 compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003169
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02003170 clear_evalarg(&evalarg, NULL);
3171
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02003172 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar5a849da2020-08-08 16:47:30 +02003173 {
3174 // The return type will now be known.
3175 set_function_type(ufunc);
3176
Bram Moolenaarfdeab652020-09-19 15:16:50 +02003177 // The function reference count will be 1. When the ISN_FUNCREF
3178 // instruction is deleted the reference count is decremented and the
3179 // function is freed.
Bram Moolenaar5a849da2020-08-08 16:47:30 +02003180 return generate_FUNCREF(cctx, ufunc);
3181 }
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003182
3183 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003184 return FAIL;
3185}
3186
3187/*
Bram Moolenaare0de1712020-12-02 17:36:54 +01003188 * parse a dict: {key: val, [key]: val}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003189 * "*arg" points to the '{'.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003190 * ppconst->pp_is_const is set if all item values are a constant.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003191 */
3192 static int
Bram Moolenaare0de1712020-12-02 17:36:54 +01003193compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003194{
3195 garray_T *instr = &cctx->ctx_instr;
3196 int count = 0;
3197 dict_T *d = dict_alloc();
3198 dictitem_T *item;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003199 char_u *whitep = *arg + 1;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003200 char_u *p;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003201 int is_const;
3202 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003203
3204 if (d == NULL)
3205 return FAIL;
Bram Moolenaard62d87d2021-01-04 17:40:12 +01003206 if (generate_ppconst(cctx, ppconst) == FAIL)
3207 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003208 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003209 {
Bram Moolenaar2bede172020-11-19 18:53:18 +01003210 char_u *key = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003211
Bram Moolenaar23c55272020-06-21 16:58:13 +02003212 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003213 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003214 *arg = NULL;
3215 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003216 }
3217
3218 if (**arg == '}')
3219 break;
3220
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003221 if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003222 {
Bram Moolenaar2bede172020-11-19 18:53:18 +01003223 isn_T *isn;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003224
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003225 // {[expr]: value} uses an evaluated key.
Bram Moolenaare0de1712020-12-02 17:36:54 +01003226 *arg = skipwhite(*arg + 1);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003227 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003228 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003229 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01003230 if (isn->isn_type == ISN_PUSHNR)
3231 {
3232 char buf[NUMBUFLEN];
3233
3234 // Convert to string at compile time.
3235 vim_snprintf(buf, NUMBUFLEN, "%lld", isn->isn_arg.number);
3236 isn->isn_type = ISN_PUSHS;
3237 isn->isn_arg.string = vim_strsave((char_u *)buf);
3238 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003239 if (isn->isn_type == ISN_PUSHS)
3240 key = isn->isn_arg.string;
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01003241 else if (may_generate_2STRING(-1, cctx) == FAIL)
3242 return FAIL;
Bram Moolenaare0de1712020-12-02 17:36:54 +01003243 *arg = skipwhite(*arg);
3244 if (**arg != ']')
Bram Moolenaar2bede172020-11-19 18:53:18 +01003245 {
Bram Moolenaare0de1712020-12-02 17:36:54 +01003246 emsg(_(e_missing_matching_bracket_after_dict_key));
3247 return FAIL;
Bram Moolenaar2bede172020-11-19 18:53:18 +01003248 }
Bram Moolenaare0de1712020-12-02 17:36:54 +01003249 ++*arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003250 }
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003251 else
3252 {
3253 // {"name": value},
3254 // {'name': value},
3255 // {name: value} use "name" as a literal key
3256 key = get_literal_key(arg);
3257 if (key == NULL)
3258 return FAIL;
3259 if (generate_PUSHS(cctx, key) == FAIL)
3260 return FAIL;
3261 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003262
3263 // Check for duplicate keys, if using string keys.
3264 if (key != NULL)
3265 {
3266 item = dict_find(d, key, -1);
3267 if (item != NULL)
3268 {
3269 semsg(_(e_duplicate_key), key);
3270 goto failret;
3271 }
3272 item = dictitem_alloc(key);
3273 if (item != NULL)
3274 {
3275 item->di_tv.v_type = VAR_UNKNOWN;
3276 item->di_tv.v_lock = 0;
3277 if (dict_add(d, item) == FAIL)
3278 dictitem_free(item);
3279 }
3280 }
3281
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003282 if (**arg != ':')
3283 {
Bram Moolenaar17a836c2020-08-12 17:35:58 +02003284 if (*skipwhite(*arg) == ':')
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003285 semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg);
Bram Moolenaar17a836c2020-08-12 17:35:58 +02003286 else
3287 semsg(_(e_missing_dict_colon), *arg);
3288 return FAIL;
3289 }
3290 whitep = *arg + 1;
3291 if (!IS_WHITE_OR_NUL(*whitep))
3292 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003293 semsg(_(e_white_space_required_after_str_str), ":", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003294 return FAIL;
3295 }
3296
Bram Moolenaar23c55272020-06-21 16:58:13 +02003297 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003298 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003299 *arg = NULL;
3300 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003301 }
3302
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003303 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003304 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003305 if (!is_const)
3306 is_all_const = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003307 ++count;
3308
Bram Moolenaar2c330432020-04-13 14:41:35 +02003309 whitep = *arg;
Bram Moolenaar23c55272020-06-21 16:58:13 +02003310 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003311 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003312 *arg = NULL;
3313 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003314 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003315 if (**arg == '}')
3316 break;
3317 if (**arg != ',')
3318 {
3319 semsg(_(e_missing_dict_comma), *arg);
3320 goto failret;
3321 }
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02003322 if (IS_WHITE_OR_NUL(*whitep))
3323 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003324 semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep);
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02003325 return FAIL;
3326 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003327 whitep = *arg + 1;
Bram Moolenaar9a13e182020-10-19 21:45:07 +02003328 if (!IS_WHITE_OR_NUL(*whitep))
3329 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003330 semsg(_(e_white_space_required_after_str_str), ",", *arg);
Bram Moolenaar9a13e182020-10-19 21:45:07 +02003331 return FAIL;
3332 }
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003333 *arg = skipwhite(whitep);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003334 }
3335
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003336 *arg = *arg + 1;
3337
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003338 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003339 p = skipwhite(*arg);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003340 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003341 *arg += STRLEN(*arg);
3342
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003343 dict_unref(d);
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003344 ppconst->pp_is_const = is_all_const;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003345 return generate_NEWDICT(cctx, count);
3346
3347failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003348 if (*arg == NULL)
Bram Moolenaar44aefff2020-10-05 19:23:59 +02003349 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003350 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar44aefff2020-10-05 19:23:59 +02003351 *arg = (char_u *)"";
3352 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003353 dict_unref(d);
3354 return FAIL;
3355}
3356
3357/*
3358 * Compile "&option".
3359 */
3360 static int
3361compile_get_option(char_u **arg, cctx_T *cctx)
3362{
3363 typval_T rettv;
3364 char_u *start = *arg;
3365 int ret;
3366
3367 // parse the option and get the current value to get the type.
3368 rettv.v_type = VAR_UNKNOWN;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003369 ret = eval_option(arg, &rettv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003370 if (ret == OK)
3371 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003372 // include the '&' in the name, eval_option() expects it.
Bram Moolenaard5ea8f02021-01-01 14:49:15 +01003373 char_u *name = vim_strnsave(start, *arg - start);
3374 type_T *type = rettv.v_type == VAR_BOOL ? &t_bool
3375 : rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003376
3377 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3378 vim_free(name);
3379 }
3380 clear_tv(&rettv);
3381
3382 return ret;
3383}
3384
3385/*
3386 * Compile "$VAR".
3387 */
3388 static int
3389compile_get_env(char_u **arg, cctx_T *cctx)
3390{
3391 char_u *start = *arg;
3392 int len;
3393 int ret;
3394 char_u *name;
3395
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003396 ++*arg;
3397 len = get_env_len(arg);
3398 if (len == 0)
3399 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003400 semsg(_(e_syntax_error_at_str), start - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003401 return FAIL;
3402 }
3403
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003404 // include the '$' in the name, eval_env_var() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003405 name = vim_strnsave(start, len + 1);
3406 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3407 vim_free(name);
3408 return ret;
3409}
3410
3411/*
3412 * Compile "@r".
3413 */
3414 static int
3415compile_get_register(char_u **arg, cctx_T *cctx)
3416{
3417 int ret;
3418
3419 ++*arg;
3420 if (**arg == NUL)
3421 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003422 semsg(_(e_syntax_error_at_str), *arg - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003423 return FAIL;
3424 }
Bram Moolenaar7226e5b2020-08-02 17:33:26 +02003425 if (!valid_yank_reg(**arg, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003426 {
3427 emsg_invreg(**arg);
3428 return FAIL;
3429 }
3430 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3431 ++*arg;
3432 return ret;
3433}
3434
3435/*
3436 * Apply leading '!', '-' and '+' to constant "rettv".
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003437 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003438 */
3439 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003440apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003441{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003442 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003443
3444 // this works from end to start
3445 while (p > start)
3446 {
3447 --p;
3448 if (*p == '-' || *p == '+')
3449 {
3450 // only '-' has an effect, for '+' we only check the type
3451#ifdef FEAT_FLOAT
3452 if (rettv->v_type == VAR_FLOAT)
3453 {
3454 if (*p == '-')
3455 rettv->vval.v_float = -rettv->vval.v_float;
3456 }
3457 else
3458#endif
3459 {
3460 varnumber_T val;
3461 int error = FALSE;
3462
3463 // tv_get_number_chk() accepts a string, but we don't want that
3464 // here
3465 if (check_not_string(rettv) == FAIL)
3466 return FAIL;
3467 val = tv_get_number_chk(rettv, &error);
3468 clear_tv(rettv);
3469 if (error)
3470 return FAIL;
3471 if (*p == '-')
3472 val = -val;
3473 rettv->v_type = VAR_NUMBER;
3474 rettv->vval.v_number = val;
3475 }
3476 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003477 else if (numeric_only)
3478 {
3479 ++p;
3480 break;
3481 }
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003482 else if (*p == '!')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003483 {
3484 int v = tv2bool(rettv);
3485
3486 // '!' is permissive in the type.
3487 clear_tv(rettv);
3488 rettv->v_type = VAR_BOOL;
3489 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3490 }
3491 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003492 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003493 return OK;
3494}
3495
3496/*
3497 * Recognize v: variables that are constants and set "rettv".
3498 */
3499 static void
3500get_vim_constant(char_u **arg, typval_T *rettv)
3501{
3502 if (STRNCMP(*arg, "v:true", 6) == 0)
3503 {
3504 rettv->v_type = VAR_BOOL;
3505 rettv->vval.v_number = VVAL_TRUE;
3506 *arg += 6;
3507 }
3508 else if (STRNCMP(*arg, "v:false", 7) == 0)
3509 {
3510 rettv->v_type = VAR_BOOL;
3511 rettv->vval.v_number = VVAL_FALSE;
3512 *arg += 7;
3513 }
3514 else if (STRNCMP(*arg, "v:null", 6) == 0)
3515 {
3516 rettv->v_type = VAR_SPECIAL;
3517 rettv->vval.v_number = VVAL_NULL;
3518 *arg += 6;
3519 }
3520 else if (STRNCMP(*arg, "v:none", 6) == 0)
3521 {
3522 rettv->v_type = VAR_SPECIAL;
3523 rettv->vval.v_number = VVAL_NONE;
3524 *arg += 6;
3525 }
3526}
3527
Bram Moolenaar657137c2021-01-09 15:45:23 +01003528 exprtype_T
Bram Moolenaar61a89812020-05-07 16:58:17 +02003529get_compare_type(char_u *p, int *len, int *type_is)
3530{
Bram Moolenaar657137c2021-01-09 15:45:23 +01003531 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar61a89812020-05-07 16:58:17 +02003532 int i;
3533
3534 switch (p[0])
3535 {
3536 case '=': if (p[1] == '=')
3537 type = EXPR_EQUAL;
3538 else if (p[1] == '~')
3539 type = EXPR_MATCH;
3540 break;
3541 case '!': if (p[1] == '=')
3542 type = EXPR_NEQUAL;
3543 else if (p[1] == '~')
3544 type = EXPR_NOMATCH;
3545 break;
3546 case '>': if (p[1] != '=')
3547 {
3548 type = EXPR_GREATER;
3549 *len = 1;
3550 }
3551 else
3552 type = EXPR_GEQUAL;
3553 break;
3554 case '<': if (p[1] != '=')
3555 {
3556 type = EXPR_SMALLER;
3557 *len = 1;
3558 }
3559 else
3560 type = EXPR_SEQUAL;
3561 break;
3562 case 'i': if (p[1] == 's')
3563 {
3564 // "is" and "isnot"; but not a prefix of a name
3565 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3566 *len = 5;
3567 i = p[*len];
3568 if (!isalnum(i) && i != '_')
3569 {
3570 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3571 *type_is = TRUE;
3572 }
3573 }
3574 break;
3575 }
3576 return type;
3577}
3578
3579/*
Bram Moolenaar7e368202020-12-25 21:56:57 +01003580 * Skip over an expression, ignoring most errors.
3581 */
3582 static void
3583skip_expr_cctx(char_u **arg, cctx_T *cctx)
3584{
3585 evalarg_T evalarg;
3586
3587 CLEAR_FIELD(evalarg);
3588 evalarg.eval_cctx = cctx;
3589 skip_expr(arg, &evalarg);
3590}
3591
3592/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003593 * Compile code to apply '-', '+' and '!'.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003594 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003595 */
3596 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003597compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003598{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003599 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003600
3601 // this works from end to start
3602 while (p > start)
3603 {
3604 --p;
Bram Moolenaar79cdf802020-11-18 17:39:05 +01003605 while (VIM_ISWHITE(*p))
3606 --p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003607 if (*p == '-' || *p == '+')
3608 {
3609 int negate = *p == '-';
3610 isn_T *isn;
3611
3612 // TODO: check type
3613 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3614 {
3615 --p;
3616 if (*p == '-')
3617 negate = !negate;
3618 }
3619 // only '-' has an effect, for '+' we only check the type
3620 if (negate)
3621 isn = generate_instr(cctx, ISN_NEGATENR);
3622 else
3623 isn = generate_instr(cctx, ISN_CHECKNR);
3624 if (isn == NULL)
3625 return FAIL;
3626 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003627 else if (numeric_only)
3628 {
3629 ++p;
3630 break;
3631 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003632 else
3633 {
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003634 int invert = *p == '!';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003635
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003636 while (p > start && (p[-1] == '!' || VIM_ISWHITE(p[-1])))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003637 {
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003638 if (p[-1] == '!')
3639 invert = !invert;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003640 --p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003641 }
3642 if (generate_2BOOL(cctx, invert) == FAIL)
3643 return FAIL;
3644 }
3645 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003646 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003647 return OK;
3648}
3649
3650/*
Bram Moolenaar7e368202020-12-25 21:56:57 +01003651 * Compile "(expression)": recursive!
3652 * Return FAIL/OK.
3653 */
3654 static int
3655compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3656{
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003657 int ret;
Bram Moolenaar24156692021-01-14 20:35:49 +01003658 char_u *p = *arg + 1;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003659
Bram Moolenaar24156692021-01-14 20:35:49 +01003660 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3661 return FAIL;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003662 if (ppconst->pp_used <= PPSIZE - 10)
3663 {
3664 ret = compile_expr1(arg, cctx, ppconst);
3665 }
3666 else
3667 {
3668 // Not enough space in ppconst, flush constants.
3669 if (generate_ppconst(cctx, ppconst) == FAIL)
3670 return FAIL;
3671 ret = compile_expr0(arg, cctx);
3672 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003673 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
3674 return FAIL;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003675 if (**arg == ')')
3676 ++*arg;
3677 else if (ret == OK)
3678 {
3679 emsg(_(e_missing_close));
3680 ret = FAIL;
3681 }
3682 return ret;
3683}
3684
3685/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003686 * Compile whatever comes after "name" or "name()".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003687 * Advances "*arg" only when something was recognized.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003688 */
3689 static int
3690compile_subscript(
3691 char_u **arg,
3692 cctx_T *cctx,
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003693 char_u *start_leader,
3694 char_u **end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003695 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003696{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003697 char_u *name_start = *end_leader;
3698
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003699 for (;;)
3700 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003701 char_u *p = skipwhite(*arg);
3702
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003703 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003704 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003705 char_u *next = peek_next_line_from_context(cctx);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003706
3707 // If a following line starts with "->{" or "->X" advance to that
3708 // line, so that a line break before "->" is allowed.
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003709 // Also if a following line starts with ".x".
3710 if (next != NULL &&
3711 ((next[0] == '-' && next[1] == '>'
3712 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003713 || (next[0] == '.' && eval_isdictc(next[1]))))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003714 {
3715 next = next_line_from_context(cctx, TRUE);
3716 if (next == NULL)
3717 return FAIL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003718 *arg = next;
3719 p = skipwhite(*arg);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003720 }
3721 }
3722
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01003723 // Do not skip over white space to find the "(", "execute 'x' ()" is
Bram Moolenaar2d6b20d2020-07-25 19:30:59 +02003724 // not a function call.
3725 if (**arg == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003726 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003727 garray_T *stack = &cctx->ctx_type_stack;
3728 type_T *type;
3729 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003730
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003731 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003732 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003733 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003734
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003735 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003736 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3737
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003738 *arg = skipwhite(p + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003739 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3740 return FAIL;
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003741 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003742 return FAIL;
3743 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003744 else if (*p == '-' && p[1] == '>')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003745 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003746 char_u *pstart = p;
3747
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003748 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003749 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003750 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003751
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003752 // something->method()
3753 // Apply the '!', '-' and '+' first:
3754 // -1.0->func() works like (-1.0)->func()
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003755 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003756 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003757
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003758 p += 2;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003759 *arg = skipwhite(p);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003760 // No line break supported right after "->".
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01003761 if (**arg == '(')
Bram Moolenaar65c44152020-12-24 15:14:01 +01003762 {
Bram Moolenaar7e368202020-12-25 21:56:57 +01003763 int argcount = 1;
3764 char_u *expr;
3765 garray_T *stack;
3766 type_T *type;
3767
3768 // Funcref call: list->(Refs[2])(arg)
3769 // or lambda: list->((arg) => expr)(arg)
3770 // Fist compile the arguments.
3771 expr = *arg;
3772 *arg = skipwhite(*arg + 1);
3773 skip_expr_cctx(arg, cctx);
3774 *arg = skipwhite(*arg);
3775 if (**arg != ')')
3776 {
3777 semsg(_(e_missing_paren), *arg);
3778 return FAIL;
3779 }
3780 ++*arg;
3781 if (**arg != '(')
3782 {
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01003783 if (*skipwhite(*arg) == '(')
3784 emsg(_(e_nowhitespace));
3785 else
3786 semsg(_(e_missing_paren), *arg);
Bram Moolenaar7e368202020-12-25 21:56:57 +01003787 return FAIL;
3788 }
3789
3790 *arg = skipwhite(*arg + 1);
3791 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3792 return FAIL;
3793
3794 // Compile the function expression.
3795 if (compile_parenthesis(&expr, cctx, ppconst) == FAIL)
3796 return FAIL;
3797
3798 stack = &cctx->ctx_type_stack;
3799 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3800 if (generate_PCALL(cctx, argcount,
3801 (char_u *)"[expression]", type, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003802 return FAIL;
3803 }
3804 else
3805 {
3806 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003807 p = *arg;
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003808 if (!eval_isnamec1(*p))
3809 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003810 semsg(_(e_trailing_arg), pstart);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003811 return FAIL;
3812 }
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003813 if (ASCII_ISALPHA(*p) && p[1] == ':')
3814 p += 2;
Bram Moolenaarc5da1fb2020-08-05 15:43:44 +02003815 for ( ; eval_isnamec(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003816 ;
3817 if (*p != '(')
3818 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003819 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003820 return FAIL;
3821 }
3822 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02003823 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003824 return FAIL;
3825 }
3826 }
Bram Moolenaarbadd8482020-07-31 22:38:17 +02003827 else if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003828 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003829 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003830 type_T **typep;
Bram Moolenaar56acb092020-08-16 14:48:19 +02003831 type_T *valtype;
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003832 vartype_T vtype;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003833 int is_slice = FALSE;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003834
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003835 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003836 // dict member: dict[key]
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003837 // string index: text[123]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003838 // TODO: blob index
3839 // TODO: more arguments
3840 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003841 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003842 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003843 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003844
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003845 ++p;
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003846 if (may_get_next_line_error(p, arg, cctx) == FAIL)
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003847 return FAIL;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003848 if (**arg == ':')
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01003849 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003850 // missing first index is equal to zero
3851 generate_PUSHNR(cctx, 0);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01003852 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003853 else
3854 {
3855 if (compile_expr0(arg, cctx) == FAIL)
3856 return FAIL;
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01003857 if (**arg == ':')
3858 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01003859 semsg(_(e_white_space_required_before_and_after_str_at_str),
3860 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01003861 return FAIL;
3862 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003863 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003864 return FAIL;
3865 *arg = skipwhite(*arg);
3866 }
3867 if (**arg == ':')
3868 {
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01003869 is_slice = TRUE;
3870 ++*arg;
3871 if (!IS_WHITE_OR_NUL(**arg) && **arg != ']')
3872 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01003873 semsg(_(e_white_space_required_before_and_after_str_at_str),
3874 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01003875 return FAIL;
3876 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003877 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003878 return FAIL;
3879 if (**arg == ']')
3880 // missing second index is equal to end of string
3881 generate_PUSHNR(cctx, -1);
3882 else
3883 {
3884 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar918a4242020-12-06 14:37:08 +01003885 return FAIL;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003886 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003887 return FAIL;
3888 *arg = skipwhite(*arg);
3889 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003890 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003891
3892 if (**arg != ']')
3893 {
3894 emsg(_(e_missbrac));
3895 return FAIL;
3896 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003897 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003898
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003899 // We can index a list and a dict. If we don't know the type
3900 // we can use the index value type.
3901 // TODO: If we don't know use an instruction to figure it out at
3902 // runtime.
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003903 typep = ((type_T **)stack->ga_data) + stack->ga_len
3904 - (is_slice ? 3 : 2);
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003905 vtype = (*typep)->tt_type;
Bram Moolenaar56acb092020-08-16 14:48:19 +02003906 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3907 // If the index is a string, the variable must be a Dict.
3908 if (*typep == &t_any && valtype == &t_string)
3909 vtype = VAR_DICT;
3910 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB)
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003911 {
Bram Moolenaar351ead02021-01-16 16:07:01 +01003912 if (need_type(valtype, &t_number, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003913 FALSE, FALSE) == FAIL)
Bram Moolenaar56acb092020-08-16 14:48:19 +02003914 return FAIL;
3915 if (is_slice)
3916 {
3917 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2];
Bram Moolenaar351ead02021-01-16 16:07:01 +01003918 if (need_type(valtype, &t_number, -2, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003919 FALSE, FALSE) == FAIL)
Bram Moolenaar56acb092020-08-16 14:48:19 +02003920 return FAIL;
3921 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003922 }
Bram Moolenaar56acb092020-08-16 14:48:19 +02003923
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003924 if (vtype == VAR_DICT)
3925 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003926 if (is_slice)
3927 {
3928 emsg(_(e_cannot_slice_dictionary));
3929 return FAIL;
3930 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003931 if ((*typep)->tt_type == VAR_DICT)
Bram Moolenaar31a11b92021-01-10 19:23:27 +01003932 {
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003933 *typep = (*typep)->tt_member;
Bram Moolenaar31a11b92021-01-10 19:23:27 +01003934 if (*typep == &t_unknown)
3935 // empty dict was used
3936 *typep = &t_any;
3937 }
Bram Moolenaar7892b952020-07-20 22:09:34 +02003938 else
3939 {
Bram Moolenaar351ead02021-01-16 16:07:01 +01003940 if (need_type(*typep, &t_dict_any, -2, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003941 FALSE, FALSE) == FAIL)
Bram Moolenaar7892b952020-07-20 22:09:34 +02003942 return FAIL;
3943 *typep = &t_any;
3944 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003945 if (may_generate_2STRING(-1, cctx) == FAIL)
3946 return FAIL;
3947 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
3948 return FAIL;
3949 }
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003950 else if (vtype == VAR_STRING)
3951 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003952 *typep = &t_string;
3953 if ((is_slice
3954 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
3955 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003956 return FAIL;
3957 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003958 else if (vtype == VAR_BLOB)
3959 {
3960 emsg("Sorry, blob index and slice not implemented yet");
3961 return FAIL;
3962 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003963 else if (vtype == VAR_LIST || *typep == &t_any)
Bram Moolenaarb13af502020-02-17 21:12:08 +01003964 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003965 if (is_slice)
3966 {
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003967 if (generate_instr_drop(cctx,
3968 vtype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
3969 2) == FAIL)
Bram Moolenaared591872020-08-15 22:14:53 +02003970 return FAIL;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003971 }
Bram Moolenaared591872020-08-15 22:14:53 +02003972 else
3973 {
3974 if ((*typep)->tt_type == VAR_LIST)
Bram Moolenaar31a11b92021-01-10 19:23:27 +01003975 {
Bram Moolenaared591872020-08-15 22:14:53 +02003976 *typep = (*typep)->tt_member;
Bram Moolenaar31a11b92021-01-10 19:23:27 +01003977 if (*typep == &t_unknown)
3978 // empty list was used
3979 *typep = &t_any;
3980 }
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003981 if (generate_instr_drop(cctx,
3982 vtype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX,
3983 1) == FAIL)
Bram Moolenaared591872020-08-15 22:14:53 +02003984 return FAIL;
3985 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003986 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003987 else
3988 {
Bram Moolenaar56acb092020-08-16 14:48:19 +02003989 emsg(_(e_string_list_dict_or_blob_required));
Bram Moolenaarb13af502020-02-17 21:12:08 +01003990 return FAIL;
3991 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003992 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003993 else if (*p == '.' && p[1] != '.')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003994 {
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003995 // dictionary member: dict.name
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003996 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003997 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003998 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003999
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004000 *arg = p + 1;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004001 if (may_get_next_line(*arg, arg, cctx) == FAIL)
Bram Moolenaarc1f00662020-10-03 13:41:53 +02004002 {
4003 emsg(_(e_missing_name_after_dot));
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004004 return FAIL;
Bram Moolenaarc1f00662020-10-03 13:41:53 +02004005 }
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004006 p = *arg;
Bram Moolenaarb13ab992020-07-27 21:43:28 +02004007 if (eval_isdictc(*p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004008 while (eval_isnamec(*p))
4009 MB_PTR_ADV(p);
4010 if (p == *arg)
4011 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004012 semsg(_(e_syntax_error_at_str), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004013 return FAIL;
4014 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004015 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004016 return FAIL;
4017 *arg = p;
4018 }
4019 else
4020 break;
4021 }
4022
4023 // TODO - see handle_subscript():
4024 // Turn "dict.Func" into a partial for "Func" bound to "dict".
4025 // Don't do this when "Func" is already a partial that was bound
4026 // explicitly (pt_auto is FALSE).
4027
4028 return OK;
4029}
4030
4031/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004032 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
4033 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004034 *
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004035 * If the value is a constant "ppconst->pp_used" will be non-zero.
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004036 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004037 *
4038 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004039 */
4040
4041/*
4042 * number number constant
4043 * 0zFFFFFFFF Blob constant
4044 * "string" string constant
4045 * 'string' literal string constant
4046 * &option-name option value
4047 * @r register contents
4048 * identifier variable value
4049 * function() function call
4050 * $VAR environment variable
4051 * (expression) nested expression
4052 * [expr, expr] List
Bram Moolenaare0de1712020-12-02 17:36:54 +01004053 * {key: val, [key]: val} Dictionary
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004054 *
4055 * Also handle:
4056 * ! in front logical NOT
4057 * - in front unary minus
4058 * + in front unary plus (ignored)
4059 * trailing (arg) funcref/partial call
4060 * trailing [] subscript in String or List
4061 * trailing .name entry in Dictionary
4062 * trailing ->name() method call
4063 */
4064 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004065compile_expr7(
4066 char_u **arg,
4067 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004068 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004069{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004070 char_u *start_leader, *end_leader;
4071 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004072 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02004073 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004074
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004075 ppconst->pp_is_const = FALSE;
4076
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004077 /*
4078 * Skip '!', '-' and '+' characters. They are handled later.
4079 */
4080 start_leader = *arg;
Bram Moolenaarb23279d2021-01-05 22:08:20 +01004081 if (eval_leader(arg, TRUE) == FAIL)
4082 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004083 end_leader = *arg;
4084
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004085 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004086 switch (**arg)
4087 {
4088 /*
4089 * Number constant.
4090 */
4091 case '0': // also for blob starting with 0z
4092 case '1':
4093 case '2':
4094 case '3':
4095 case '4':
4096 case '5':
4097 case '6':
4098 case '7':
4099 case '8':
4100 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004101 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004102 return FAIL;
Bram Moolenaar4301a722020-08-11 20:51:08 +02004103 // Apply "-" and "+" just before the number now, right to
4104 // left. Matters especially when "->" follows. Stops at
4105 // '!'.
4106 if (apply_leader(rettv, TRUE,
4107 start_leader, &end_leader) == FAIL)
4108 {
4109 clear_tv(rettv);
4110 return FAIL;
4111 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004112 break;
4113
4114 /*
4115 * String constant: "string".
4116 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004117 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004118 return FAIL;
4119 break;
4120
4121 /*
4122 * Literal string constant: 'str''ing'.
4123 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004124 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004125 return FAIL;
4126 break;
4127
4128 /*
4129 * Constant Vim variable.
4130 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004131 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004132 ret = NOTDONE;
4133 break;
4134
4135 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004136 * "true" constant
4137 */
4138 case 't': if (STRNCMP(*arg, "true", 4) == 0
4139 && !eval_isnamec((*arg)[4]))
4140 {
4141 *arg += 4;
4142 rettv->v_type = VAR_BOOL;
4143 rettv->vval.v_number = VVAL_TRUE;
4144 }
4145 else
4146 ret = NOTDONE;
4147 break;
4148
4149 /*
4150 * "false" constant
4151 */
4152 case 'f': if (STRNCMP(*arg, "false", 5) == 0
4153 && !eval_isnamec((*arg)[5]))
4154 {
4155 *arg += 5;
4156 rettv->v_type = VAR_BOOL;
4157 rettv->vval.v_number = VVAL_FALSE;
4158 }
4159 else
4160 ret = NOTDONE;
4161 break;
4162
4163 /*
Bram Moolenaar67977822021-01-03 21:53:53 +01004164 * "null" constant
4165 */
4166 case 'n': if (STRNCMP(*arg, "null", 4) == 0
4167 && !eval_isnamec((*arg)[5]))
4168 {
4169 *arg += 4;
4170 rettv->v_type = VAR_SPECIAL;
4171 rettv->vval.v_number = VVAL_NULL;
4172 }
4173 else
4174 ret = NOTDONE;
4175 break;
4176
4177 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004178 * List: [expr, expr]
4179 */
Bram Moolenaare507ff12021-01-31 21:47:42 +01004180 case '[': if (generate_ppconst(cctx, ppconst) == FAIL)
4181 return FAIL;
4182 ret = compile_list(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004183 break;
4184
4185 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004186 * Dictionary: {'key': val, 'key': val}
4187 */
Bram Moolenaare507ff12021-01-31 21:47:42 +01004188 case '{': if (generate_ppconst(cctx, ppconst) == FAIL)
4189 return FAIL;
4190 ret = compile_dict(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004191 break;
4192
4193 /*
4194 * Option value: &name
4195 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004196 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
4197 return FAIL;
4198 ret = compile_get_option(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004199 break;
4200
4201 /*
4202 * Environment variable: $VAR.
4203 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004204 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
4205 return FAIL;
4206 ret = compile_get_env(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004207 break;
4208
4209 /*
4210 * Register contents: @r.
4211 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004212 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
4213 return FAIL;
4214 ret = compile_get_register(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004215 break;
4216 /*
4217 * nested expression: (expression).
Bram Moolenaar65c44152020-12-24 15:14:01 +01004218 * lambda: (arg, arg) => expr
4219 * funcref: (arg, arg) => { statement }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004220 */
Bram Moolenaare462f522020-12-27 14:43:30 +01004221 case '(': // if compile_lambda returns NOTDONE then it must be (expr)
4222 ret = compile_lambda(arg, cctx);
4223 if (ret == NOTDONE)
Bram Moolenaar7e368202020-12-25 21:56:57 +01004224 ret = compile_parenthesis(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004225 break;
4226
4227 default: ret = NOTDONE;
4228 break;
4229 }
4230 if (ret == FAIL)
4231 return FAIL;
4232
Bram Moolenaar1c747212020-05-09 18:28:34 +02004233 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004234 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004235 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004236 clear_tv(rettv);
4237 else
4238 // A constant expression can possibly be handled compile time,
4239 // return the value instead of generating code.
4240 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004241 }
4242 else if (ret == NOTDONE)
4243 {
4244 char_u *p;
4245 int r;
4246
4247 if (!eval_isnamec1(**arg))
4248 {
Bram Moolenaare4984292020-12-13 14:19:25 +01004249 if (ends_excmd(*skipwhite(*arg)))
4250 semsg(_(e_empty_expression_str), *arg);
4251 else
4252 semsg(_(e_name_expected_str), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004253 return FAIL;
4254 }
4255
4256 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01004257 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004258 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02004259 {
4260 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
4261 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004262 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02004263 {
4264 if (generate_ppconst(cctx, ppconst) == FAIL)
4265 return FAIL;
Bram Moolenaar0f769812020-09-12 18:32:34 +02004266 r = compile_load(arg, p, cctx, TRUE, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004267 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004268 if (r == FAIL)
4269 return FAIL;
4270 }
4271
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004272 // Handle following "[]", ".member", etc.
4273 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004274 if (compile_subscript(arg, cctx, start_leader, &end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02004275 ppconst) == FAIL)
4276 return FAIL;
4277 if (ppconst->pp_used > 0)
4278 {
4279 // apply the '!', '-' and '+' before the constant
4280 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004281 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004282 return FAIL;
4283 return OK;
4284 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004285 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004286 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004287 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004288}
4289
4290/*
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004291 * Give the "white on both sides" error, taking the operator from "p[len]".
4292 */
4293 void
4294error_white_both(char_u *op, int len)
4295{
4296 char_u buf[10];
4297
4298 vim_strncpy(buf, op, len);
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004299 semsg(_(e_white_space_required_before_and_after_str_at_str), buf, op);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004300}
4301
4302/*
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004303 * <type>expr7: runtime type check / conversion
4304 */
4305 static int
4306compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
4307{
4308 type_T *want_type = NULL;
4309
4310 // Recognize <type>
4311 if (**arg == '<' && eval_isnamec1((*arg)[1]))
4312 {
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004313 ++*arg;
Bram Moolenaar9e68c322020-12-25 12:38:04 +01004314 want_type = parse_type(arg, cctx->ctx_type_list, TRUE);
4315 if (want_type == NULL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004316 return FAIL;
4317
4318 if (**arg != '>')
4319 {
4320 if (*skipwhite(*arg) == '>')
Bram Moolenaarba98fb52021-02-07 18:06:29 +01004321 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004322 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004323 emsg(_(e_missing_gt));
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004324 return FAIL;
4325 }
4326 ++*arg;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004327 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004328 return FAIL;
4329 }
4330
4331 if (compile_expr7(arg, cctx, ppconst) == FAIL)
4332 return FAIL;
4333
4334 if (want_type != NULL)
4335 {
4336 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaard1103582020-08-14 22:44:25 +02004337 type_T *actual;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004338 where_T where;
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004339
Bram Moolenaard1103582020-08-14 22:44:25 +02004340 generate_ppconst(cctx, ppconst);
4341 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004342 where.wt_index = 0;
4343 where.wt_variable = FALSE;
4344 if (check_type(want_type, actual, FALSE, where) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004345 {
Bram Moolenaar351ead02021-01-16 16:07:01 +01004346 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004347 return FAIL;
4348 }
4349 }
4350
4351 return OK;
4352}
4353
4354/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004355 * * number multiplication
4356 * / number division
4357 * % number modulo
4358 */
4359 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004360compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004361{
4362 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004363 char_u *next;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004364 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004365
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004366 // get the first expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004367 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004368 return FAIL;
4369
4370 /*
4371 * Repeat computing, until no "*", "/" or "%" is following.
4372 */
4373 for (;;)
4374 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004375 op = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004376 if (*op != '*' && *op != '/' && *op != '%')
4377 break;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004378 if (next != NULL)
4379 {
4380 *arg = next_line_from_context(cctx, TRUE);
4381 op = skipwhite(*arg);
4382 }
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004383
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004384 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004385 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004386 error_white_both(op, 1);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004387 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004388 }
Bram Moolenaar918a4242020-12-06 14:37:08 +01004389 if (may_get_next_line_error(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004390 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004391
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004392 // get the second expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004393 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004394 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004395
4396 if (ppconst->pp_used == ppconst_used + 2
4397 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4398 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004399 {
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004400 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4401 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
4402 varnumber_T res = 0;
4403 int failed = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004404
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004405 // both are numbers: compute the result
4406 switch (*op)
4407 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004408 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004409 break;
Bram Moolenaare64f83c2021-01-19 22:16:41 +01004410 case '/': res = num_divide(tv1->vval.v_number,
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004411 tv2->vval.v_number, &failed);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004412 break;
Bram Moolenaare64f83c2021-01-19 22:16:41 +01004413 case '%': res = num_modulus(tv1->vval.v_number,
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004414 tv2->vval.v_number, &failed);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004415 break;
4416 }
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004417 if (failed)
4418 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004419 tv1->vval.v_number = res;
4420 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004421 }
4422 else
4423 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004424 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004425 generate_two_op(cctx, op);
4426 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004427 }
4428
4429 return OK;
4430}
4431
4432/*
4433 * + number addition
4434 * - number subtraction
4435 * .. string concatenation
4436 */
4437 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004438compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004439{
4440 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004441 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004442 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004443 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004444
4445 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004446 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004447 return FAIL;
4448
4449 /*
4450 * Repeat computing, until no "+", "-" or ".." is following.
4451 */
4452 for (;;)
4453 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004454 op = may_peek_next_line(cctx, *arg, &next);
4455 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004456 break;
4457 oplen = (*op == '.' ? 2 : 1);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004458 if (next != NULL)
4459 {
4460 *arg = next_line_from_context(cctx, TRUE);
4461 op = skipwhite(*arg);
4462 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004463
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004464 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004465 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004466 error_white_both(op, oplen);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004467 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004468 }
4469
Bram Moolenaare0de1712020-12-02 17:36:54 +01004470 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004471 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004472
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004473 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004474 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004475 return FAIL;
4476
Bram Moolenaara5565e42020-05-09 15:44:01 +02004477 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004478 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02004479 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
4480 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
4481 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4482 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004483 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004484 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4485 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004486
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004487 // concat/subtract/add constant numbers
4488 if (*op == '+')
4489 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
4490 else if (*op == '-')
4491 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
4492 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004493 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004494 // concatenate constant strings
4495 char_u *s1 = tv1->vval.v_string;
4496 char_u *s2 = tv2->vval.v_string;
4497 size_t len1 = STRLEN(s1);
4498
4499 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
4500 if (tv1->vval.v_string == NULL)
4501 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004502 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004503 return FAIL;
4504 }
4505 mch_memmove(tv1->vval.v_string, s1, len1);
4506 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004507 vim_free(s1);
4508 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004509 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004510 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004511 }
4512 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004513 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004514 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004515 if (*op == '.')
4516 {
4517 if (may_generate_2STRING(-2, cctx) == FAIL
4518 || may_generate_2STRING(-1, cctx) == FAIL)
4519 return FAIL;
4520 generate_instr_drop(cctx, ISN_CONCAT, 1);
4521 }
4522 else
4523 generate_two_op(cctx, op);
4524 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004525 }
4526
4527 return OK;
4528}
4529
4530/*
4531 * expr5a == expr5b
4532 * expr5a =~ expr5b
4533 * expr5a != expr5b
4534 * expr5a !~ expr5b
4535 * expr5a > expr5b
4536 * expr5a >= expr5b
4537 * expr5a < expr5b
4538 * expr5a <= expr5b
4539 * expr5a is expr5b
4540 * expr5a isnot expr5b
4541 *
4542 * Produces instructions:
4543 * EVAL expr5a Push result of "expr5a"
4544 * EVAL expr5b Push result of "expr5b"
4545 * COMPARE one of the compare instructions
4546 */
4547 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004548compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004549{
Bram Moolenaar657137c2021-01-09 15:45:23 +01004550 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004551 char_u *p;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004552 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004553 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004554 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004555 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004556
4557 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004558 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004559 return FAIL;
4560
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004561 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004562 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004563
4564 /*
4565 * If there is a comparative operator, use it.
4566 */
4567 if (type != EXPR_UNKNOWN)
4568 {
4569 int ic = FALSE; // Default: do not ignore case
4570
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004571 if (next != NULL)
4572 {
4573 *arg = next_line_from_context(cctx, TRUE);
4574 p = skipwhite(*arg);
4575 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004576 if (type_is && (p[len] == '?' || p[len] == '#'))
4577 {
4578 semsg(_(e_invexpr2), *arg);
4579 return FAIL;
4580 }
4581 // extra question mark appended: ignore case
4582 if (p[len] == '?')
4583 {
4584 ic = TRUE;
4585 ++len;
4586 }
4587 // extra '#' appended: match case (ignored)
4588 else if (p[len] == '#')
4589 ++len;
4590 // nothing appended: match case
4591
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004592 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004593 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004594 error_white_both(p, len);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004595 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004596 }
4597
4598 // get the second variable
Bram Moolenaar918a4242020-12-06 14:37:08 +01004599 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004600 return FAIL;
4601
Bram Moolenaara5565e42020-05-09 15:44:01 +02004602 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004603 return FAIL;
4604
Bram Moolenaara5565e42020-05-09 15:44:01 +02004605 if (ppconst->pp_used == ppconst_used + 2)
4606 {
4607 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4608 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4609 int ret;
4610
4611 // Both sides are a constant, compute the result now.
4612 // First check for a valid combination of types, this is more
4613 // strict than typval_compare().
Bram Moolenaar543e6f32020-07-10 22:45:38 +02004614 if (check_compare_types(type, tv1, tv2) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004615 ret = FAIL;
4616 else
4617 {
4618 ret = typval_compare(tv1, tv2, type, ic);
4619 tv1->v_type = VAR_BOOL;
4620 tv1->vval.v_number = tv1->vval.v_number
4621 ? VVAL_TRUE : VVAL_FALSE;
4622 clear_tv(tv2);
4623 --ppconst->pp_used;
4624 }
4625 return ret;
4626 }
4627
4628 generate_ppconst(cctx, ppconst);
4629 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004630 }
4631
4632 return OK;
4633}
4634
Bram Moolenaar7f141552020-05-09 17:35:53 +02004635static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4636
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004637/*
4638 * Compile || or &&.
4639 */
4640 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004641compile_and_or(
4642 char_u **arg,
4643 cctx_T *cctx,
4644 char *op,
4645 ppconst_T *ppconst,
4646 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004647{
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004648 char_u *next;
4649 char_u *p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004650 int opchar = *op;
4651
4652 if (p[0] == opchar && p[1] == opchar)
4653 {
4654 garray_T *instr = &cctx->ctx_instr;
4655 garray_T end_ga;
4656
4657 /*
4658 * Repeat until there is no following "||" or "&&"
4659 */
4660 ga_init2(&end_ga, sizeof(int), 10);
4661 while (p[0] == opchar && p[1] == opchar)
4662 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004663 if (next != NULL)
4664 {
4665 *arg = next_line_from_context(cctx, TRUE);
4666 p = skipwhite(*arg);
4667 }
4668
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004669 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4670 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004671 semsg(_(e_white_space_required_before_and_after_str_at_str),
4672 op, *arg);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004673 return FAIL;
4674 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004675
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004676 // TODO: use ppconst if the value is a constant and check
4677 // evaluating to bool
Bram Moolenaara5565e42020-05-09 15:44:01 +02004678 generate_ppconst(cctx, ppconst);
4679
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004680 // Every part must evaluate to a bool.
4681 if (bool_on_stack(cctx) == FAIL)
4682 {
4683 ga_clear(&end_ga);
4684 return FAIL;
4685 }
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004686
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004687 if (ga_grow(&end_ga, 1) == FAIL)
4688 {
4689 ga_clear(&end_ga);
4690 return FAIL;
4691 }
4692 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4693 ++end_ga.ga_len;
4694 generate_JUMP(cctx, opchar == '|'
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004695 ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE, 0);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004696
4697 // eval the next expression
Bram Moolenaar918a4242020-12-06 14:37:08 +01004698 if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
Bram Moolenaar8bb0f542020-12-06 16:03:55 +01004699 {
4700 ga_clear(&end_ga);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004701 return FAIL;
Bram Moolenaar8bb0f542020-12-06 16:03:55 +01004702 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004703
Bram Moolenaara5565e42020-05-09 15:44:01 +02004704 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4705 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004706 {
4707 ga_clear(&end_ga);
4708 return FAIL;
4709 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004710
4711 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004712 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004713 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004714
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004715 // Every part must evaluate to a bool.
4716 if (bool_on_stack(cctx) == FAIL)
4717 {
4718 ga_clear(&end_ga);
4719 return FAIL;
4720 }
4721
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004722 // Fill in the end label in all jumps.
4723 while (end_ga.ga_len > 0)
4724 {
4725 isn_T *isn;
4726
4727 --end_ga.ga_len;
4728 isn = ((isn_T *)instr->ga_data)
4729 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4730 isn->isn_arg.jump.jump_where = instr->ga_len;
4731 }
4732 ga_clear(&end_ga);
4733 }
4734
4735 return OK;
4736}
4737
4738/*
4739 * expr4a && expr4a && expr4a logical AND
4740 *
4741 * Produces instructions:
4742 * EVAL expr4a Push result of "expr4a"
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004743 * COND2BOOL convert to bool if needed
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004744 * JUMP_IF_COND_FALSE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004745 * EVAL expr4b Push result of "expr4b"
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004746 * JUMP_IF_COND_FALSE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004747 * EVAL expr4c Push result of "expr4c"
4748 * end:
4749 */
4750 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004751compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004752{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004753 int ppconst_used = ppconst->pp_used;
4754
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004755 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004756 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004757 return FAIL;
4758
4759 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004760 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004761}
4762
4763/*
4764 * expr3a || expr3b || expr3c logical OR
4765 *
4766 * Produces instructions:
4767 * EVAL expr3a Push result of "expr3a"
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004768 * COND2BOOL convert to bool if needed
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004769 * JUMP_IF_COND_TRUE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004770 * EVAL expr3b Push result of "expr3b"
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004771 * JUMP_IF_COND_TRUE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004772 * EVAL expr3c Push result of "expr3c"
4773 * end:
4774 */
4775 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004776compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004777{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004778 int ppconst_used = ppconst->pp_used;
4779
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004780 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004781 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004782 return FAIL;
4783
4784 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004785 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004786}
4787
4788/*
4789 * Toplevel expression: expr2 ? expr1a : expr1b
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004790 * Produces instructions:
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004791 * EVAL expr2 Push result of "expr2"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004792 * JUMP_IF_FALSE alt jump if false
4793 * EVAL expr1a
4794 * JUMP_ALWAYS end
4795 * alt: EVAL expr1b
4796 * end:
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004797 *
4798 * Toplevel expression: expr2 ?? expr1
4799 * Produces instructions:
4800 * EVAL expr2 Push result of "expr2"
4801 * JUMP_AND_KEEP_IF_TRUE end jump if true
4802 * EVAL expr1
4803 * end:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004804 */
4805 static int
Bram Moolenaar7e368202020-12-25 21:56:57 +01004806compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004807{
4808 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004809 int ppconst_used = ppconst->pp_used;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004810 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004811
Bram Moolenaar3988f642020-08-27 22:43:03 +02004812 // Ignore all kinds of errors when not producing code.
4813 if (cctx->ctx_skip == SKIP_YES)
4814 {
Bram Moolenaar7e368202020-12-25 21:56:57 +01004815 skip_expr_cctx(arg, cctx);
Bram Moolenaar3988f642020-08-27 22:43:03 +02004816 return OK;
4817 }
4818
Bram Moolenaar61a89812020-05-07 16:58:17 +02004819 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004820 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004821 return FAIL;
4822
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004823 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004824 if (*p == '?')
4825 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004826 int op_falsy = p[1] == '?';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004827 garray_T *instr = &cctx->ctx_instr;
4828 garray_T *stack = &cctx->ctx_type_stack;
4829 int alt_idx = instr->ga_len;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004830 int end_idx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004831 isn_T *isn;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004832 type_T *type1 = NULL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004833 int has_const_expr = FALSE;
4834 int const_value = FALSE;
4835 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004836
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004837 if (next != NULL)
4838 {
4839 *arg = next_line_from_context(cctx, TRUE);
4840 p = skipwhite(*arg);
4841 }
4842
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004843 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004844 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004845 semsg(_(e_white_space_required_before_and_after_str_at_str),
4846 op_falsy ? "??" : "?", *arg);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004847 return FAIL;
4848 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004849
Bram Moolenaara5565e42020-05-09 15:44:01 +02004850 if (ppconst->pp_used == ppconst_used + 1)
4851 {
4852 // the condition is a constant, we know whether the ? or the :
4853 // expression is to be evaluated.
4854 has_const_expr = TRUE;
Bram Moolenaar13106602020-10-04 16:06:05 +02004855 if (op_falsy)
4856 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4857 else
4858 {
4859 int error = FALSE;
4860
4861 const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
4862 &error);
4863 if (error)
4864 return FAIL;
4865 }
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004866 cctx->ctx_skip = save_skip == SKIP_YES ||
4867 (op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
4868
4869 if (op_falsy && cctx->ctx_skip == SKIP_YES)
4870 // "left ?? right" and "left" is truthy: produce "left"
4871 generate_ppconst(cctx, ppconst);
4872 else
4873 {
4874 clear_tv(&ppconst->pp_tv[ppconst_used]);
4875 --ppconst->pp_used;
4876 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004877 }
4878 else
4879 {
4880 generate_ppconst(cctx, ppconst);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004881 if (op_falsy)
4882 end_idx = instr->ga_len;
4883 generate_JUMP(cctx, op_falsy
4884 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
4885 if (op_falsy)
4886 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaara5565e42020-05-09 15:44:01 +02004887 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004888
4889 // evaluate the second expression; any type is accepted
Bram Moolenaar918a4242020-12-06 14:37:08 +01004890 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004891 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004892 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004893 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004894
Bram Moolenaara5565e42020-05-09 15:44:01 +02004895 if (!has_const_expr)
4896 {
4897 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004898
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004899 if (!op_falsy)
4900 {
4901 // remember the type and drop it
4902 --stack->ga_len;
4903 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004904
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004905 end_idx = instr->ga_len;
4906 generate_JUMP(cctx, JUMP_ALWAYS, 0);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004907
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004908 // jump here from JUMP_IF_FALSE
4909 isn = ((isn_T *)instr->ga_data) + alt_idx;
4910 isn->isn_arg.jump.jump_where = instr->ga_len;
4911 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004912 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004913
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004914 if (!op_falsy)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004915 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004916 // Check for the ":".
4917 p = may_peek_next_line(cctx, *arg, &next);
4918 if (*p != ':')
4919 {
4920 emsg(_(e_missing_colon));
4921 return FAIL;
4922 }
4923 if (next != NULL)
4924 {
4925 *arg = next_line_from_context(cctx, TRUE);
4926 p = skipwhite(*arg);
4927 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004928
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004929 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4930 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004931 semsg(_(e_white_space_required_before_and_after_str_at_str),
4932 ":", p);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004933 return FAIL;
4934 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004935
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004936 // evaluate the third expression
4937 if (has_const_expr)
4938 cctx->ctx_skip = save_skip == SKIP_YES || const_value
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004939 ? SKIP_YES : SKIP_NOT;
Bram Moolenaar918a4242020-12-06 14:37:08 +01004940 if (may_get_next_line_error(p + 1, arg, cctx) == FAIL)
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004941 return FAIL;
4942 if (compile_expr1(arg, cctx, ppconst) == FAIL)
4943 return FAIL;
4944 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004945
Bram Moolenaara5565e42020-05-09 15:44:01 +02004946 if (!has_const_expr)
4947 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004948 type_T **typep;
4949
Bram Moolenaara5565e42020-05-09 15:44:01 +02004950 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004951
Bram Moolenaara5565e42020-05-09 15:44:01 +02004952 // If the types differ, the result has a more generic type.
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004953 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
4954 common_type(type1, *typep, typep, cctx->ctx_type_list);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004955
Bram Moolenaar92f26c22020-10-03 20:17:30 +02004956 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
Bram Moolenaara5565e42020-05-09 15:44:01 +02004957 isn = ((isn_T *)instr->ga_data) + end_idx;
4958 isn->isn_arg.jump.jump_where = instr->ga_len;
4959 }
4960
4961 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004962 }
4963 return OK;
4964}
4965
4966/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004967 * Toplevel expression.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004968 * Sets "is_const" (if not NULL) to indicate the value is a constant.
4969 * Returns OK or FAIL.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004970 */
4971 static int
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004972compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004973{
4974 ppconst_T ppconst;
4975
4976 CLEAR_FIELD(ppconst);
4977 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4978 {
4979 clear_ppconst(&ppconst);
4980 return FAIL;
4981 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004982 if (is_const != NULL)
4983 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004984 if (generate_ppconst(cctx, &ppconst) == FAIL)
4985 return FAIL;
4986 return OK;
4987}
4988
4989/*
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004990 * Toplevel expression.
4991 */
4992 static int
4993compile_expr0(char_u **arg, cctx_T *cctx)
4994{
4995 return compile_expr0_ext(arg, cctx, NULL);
4996}
4997
4998/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004999 * compile "return [expr]"
5000 */
5001 static char_u *
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005002compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005003{
5004 char_u *p = arg;
5005 garray_T *stack = &cctx->ctx_type_stack;
5006 type_T *stack_type;
5007
5008 if (*p != NUL && *p != '|' && *p != '\n')
5009 {
5010 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02005011 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005012 return NULL;
5013
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005014 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar05a55512020-07-05 15:52:19 +02005015 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005016 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar6b553772020-12-31 13:31:23 +01005017 if (check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar328eac22021-01-07 19:23:08 +01005018 || cctx->ctx_ufunc->uf_ret_type == &t_unknown
5019 || cctx->ctx_ufunc->uf_ret_type == &t_any))
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005020 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005021 cctx->ctx_ufunc->uf_ret_type = stack_type;
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005022 }
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005023 else
Bram Moolenaar05a55512020-07-05 15:52:19 +02005024 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005025 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
5026 && stack_type->tt_type != VAR_VOID
5027 && stack_type->tt_type != VAR_UNKNOWN)
5028 {
5029 emsg(_(e_returning_value_in_function_without_return_type));
5030 return NULL;
5031 }
5032 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
Bram Moolenaar351ead02021-01-16 16:07:01 +01005033 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005034 return NULL;
5035 }
Bram Moolenaar05a55512020-07-05 15:52:19 +02005036 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005037 }
5038 else
5039 {
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005040 // "check_return_type" cannot be TRUE, only used for a lambda which
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02005041 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02005042 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
5043 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005044 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005045 emsg(_(e_missing_return_value));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005046 return NULL;
5047 }
5048
5049 // No argument, return zero.
5050 generate_PUSHNR(cctx, 0);
5051 }
Bram Moolenaar7cd24222021-01-12 18:58:39 +01005052
5053 // Undo any command modifiers.
5054 generate_undo_cmdmods(cctx);
5055
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005056 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005057 return NULL;
5058
5059 // "return val | endif" is possible
5060 return skipwhite(p);
5061}
5062
5063/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02005064 * Get a line from the compilation context, compatible with exarg_T getline().
5065 * Return a pointer to the line in allocated memory.
5066 * Return NULL for end-of-file or some error.
5067 */
5068 static char_u *
5069exarg_getline(
5070 int c UNUSED,
5071 void *cookie,
5072 int indent UNUSED,
Bram Moolenaar66250c92020-08-20 15:02:42 +02005073 getline_opt_T options UNUSED)
Bram Moolenaar04b12692020-05-04 23:24:44 +02005074{
5075 cctx_T *cctx = (cctx_T *)cookie;
Bram Moolenaar66250c92020-08-20 15:02:42 +02005076 char_u *p;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005077
Bram Moolenaar66250c92020-08-20 15:02:42 +02005078 for (;;)
Bram Moolenaar04b12692020-05-04 23:24:44 +02005079 {
Bram Moolenaar2914a202020-09-27 18:24:03 +02005080 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len - 1)
Bram Moolenaar66250c92020-08-20 15:02:42 +02005081 return NULL;
5082 ++cctx->ctx_lnum;
5083 p = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
5084 // Comment lines result in NULL pointers, skip them.
5085 if (p != NULL)
5086 return vim_strsave(p);
Bram Moolenaar04b12692020-05-04 23:24:44 +02005087 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02005088}
5089
5090/*
5091 * Compile a nested :def command.
5092 */
5093 static char_u *
5094compile_nested_function(exarg_T *eap, cctx_T *cctx)
5095{
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005096 int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
Bram Moolenaar04b12692020-05-04 23:24:44 +02005097 char_u *name_start = eap->arg;
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005098 char_u *name_end = to_name_end(eap->arg, TRUE);
Bram Moolenaareef21022020-08-01 22:16:43 +02005099 char_u *lambda_name;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005100 ufunc_T *ufunc;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005101 int r = FAIL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005102
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02005103 if (eap->forceit)
Bram Moolenaar8b848ca2020-09-10 22:28:01 +02005104 {
5105 emsg(_(e_cannot_use_bang_with_nested_def));
5106 return NULL;
5107 }
5108
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01005109 if (*name_start == '/')
5110 {
5111 name_end = skip_regexp(name_start + 1, '/', TRUE);
5112 if (*name_end == '/')
5113 ++name_end;
5114 eap->nextcmd = check_nextcmd(name_end);
5115 }
5116 if (name_end == name_start || *skipwhite(name_end) != '(')
5117 {
5118 if (!ends_excmd2(name_start, name_end))
5119 {
5120 semsg(_(e_invalid_command_str), eap->cmd);
5121 return NULL;
5122 }
5123
5124 // "def" or "def Name": list functions
5125 if (generate_DEF(cctx, name_start, name_end - name_start) == FAIL)
5126 return NULL;
5127 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5128 }
5129
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005130 // Only g:Func() can use a namespace.
5131 if (name_start[1] == ':' && !is_global)
5132 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005133 semsg(_(e_namespace_not_supported_str), name_start);
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005134 return NULL;
5135 }
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005136 if (check_defined(name_start, name_end - name_start, cctx, FALSE) == FAIL)
Bram Moolenaareef21022020-08-01 22:16:43 +02005137 return NULL;
5138
Bram Moolenaar04b12692020-05-04 23:24:44 +02005139 eap->arg = name_end;
5140 eap->getline = exarg_getline;
5141 eap->cookie = cctx;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005142 eap->skip = cctx->ctx_skip == SKIP_YES;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005143 eap->forceit = FALSE;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005144 lambda_name = vim_strsave(get_lambda_name());
5145 if (lambda_name == NULL)
5146 return NULL;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02005147 ufunc = define_function(eap, lambda_name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02005148
Bram Moolenaar822ba242020-05-24 23:00:18 +02005149 if (ufunc == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005150 {
5151 r = eap->skip ? OK : FAIL;
5152 goto theend;
5153 }
Bram Moolenaare5ea3462021-01-25 21:01:48 +01005154 if (func_needs_compiling(ufunc, PROFILING(ufunc))
5155 && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx)
Bram Moolenaarb2049902021-01-24 12:53:53 +01005156 == FAIL)
Bram Moolenaar4ee711f2020-09-23 18:51:11 +02005157 {
5158 func_ptr_unref(ufunc);
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005159 goto theend;
Bram Moolenaar4ee711f2020-09-23 18:51:11 +02005160 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02005161
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005162 if (is_global)
5163 {
5164 char_u *func_name = vim_strnsave(name_start + 2,
5165 name_end - name_start - 2);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02005166
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005167 if (func_name == NULL)
5168 r = FAIL;
5169 else
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005170 {
Bram Moolenaareef21022020-08-01 22:16:43 +02005171 r = generate_NEWFUNC(cctx, lambda_name, func_name);
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005172 lambda_name = NULL;
5173 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005174 }
5175 else
5176 {
5177 // Define a local variable for the function reference.
Bram Moolenaare8211a32020-10-09 22:04:29 +02005178 lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start,
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005179 TRUE, ufunc->uf_func_type);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02005180 int block_depth = cctx->ctx_ufunc->uf_block_depth;
Bram Moolenaare8211a32020-10-09 22:04:29 +02005181
Bram Moolenaareef21022020-08-01 22:16:43 +02005182 if (lvar == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005183 goto theend;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02005184 if (generate_FUNCREF(cctx, ufunc) == FAIL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005185 goto theend;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005186 r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02005187
5188 // copy over the block scope IDs
5189 if (block_depth > 0)
5190 {
5191 ufunc->uf_block_ids = ALLOC_MULT(int, block_depth);
5192 if (ufunc->uf_block_ids != NULL)
5193 {
5194 mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids,
5195 sizeof(int) * block_depth);
5196 ufunc->uf_block_depth = block_depth;
5197 }
5198 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005199 }
Bram Moolenaar61a89812020-05-07 16:58:17 +02005200 // TODO: warning for trailing text?
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005201
5202theend:
5203 vim_free(lambda_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005204 return r == FAIL ? NULL : (char_u *)"";
Bram Moolenaar04b12692020-05-04 23:24:44 +02005205}
5206
5207/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005208 * Return the length of an assignment operator, or zero if there isn't one.
5209 */
5210 int
5211assignment_len(char_u *p, int *heredoc)
5212{
5213 if (*p == '=')
5214 {
5215 if (p[1] == '<' && p[2] == '<')
5216 {
5217 *heredoc = TRUE;
5218 return 3;
5219 }
5220 return 1;
5221 }
5222 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
5223 return 2;
5224 if (STRNCMP(p, "..=", 3) == 0)
5225 return 3;
5226 return 0;
5227}
5228
5229// words that cannot be used as a variable
5230static char *reserved[] = {
5231 "true",
5232 "false",
Bram Moolenaar67977822021-01-03 21:53:53 +01005233 "null",
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005234 NULL
5235};
5236
Bram Moolenaar752fc692021-01-04 21:57:11 +01005237// Destination for an assignment or ":unlet" with an index.
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005238typedef enum {
5239 dest_local,
5240 dest_option,
5241 dest_env,
5242 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02005243 dest_buffer,
5244 dest_window,
5245 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005246 dest_vimvar,
5247 dest_script,
5248 dest_reg,
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005249 dest_expr,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005250} assign_dest_T;
5251
Bram Moolenaar752fc692021-01-04 21:57:11 +01005252// Used by compile_lhs() to store information about the LHS of an assignment
5253// and one argument of ":unlet" with an index.
5254typedef struct {
5255 assign_dest_T lhs_dest; // type of destination
5256
5257 char_u *lhs_name; // allocated name including
5258 // "[expr]" or ".name".
5259 size_t lhs_varlen; // length of the variable without
5260 // "[expr]" or ".name"
5261 char_u *lhs_dest_end; // end of the destination, including
5262 // "[expr]" or ".name".
5263
5264 int lhs_has_index; // has "[expr]" or ".name"
5265
5266 int lhs_new_local; // create new local variable
5267 int lhs_opt_flags; // for when destination is an option
5268 int lhs_vimvaridx; // for when destination is a v:var
5269
5270 lvar_T lhs_local_lvar; // used for existing local destination
5271 lvar_T lhs_arg_lvar; // used for argument destination
5272 lvar_T *lhs_lvar; // points to destination lvar
5273 int lhs_scriptvar_sid;
5274 int lhs_scriptvar_idx;
5275
5276 int lhs_has_type; // type was specified
5277 type_T *lhs_type;
5278 type_T *lhs_member_type;
5279} lhs_T;
5280
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005281/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005282 * Generate the load instruction for "name".
5283 */
5284 static void
5285generate_loadvar(
5286 cctx_T *cctx,
5287 assign_dest_T dest,
5288 char_u *name,
5289 lvar_T *lvar,
5290 type_T *type)
5291{
5292 switch (dest)
5293 {
5294 case dest_option:
5295 // TODO: check the option exists
5296 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
5297 break;
5298 case dest_global:
Bram Moolenaar03290b82020-12-19 16:30:44 +01005299 if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
5300 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
5301 else
5302 generate_LOAD(cctx, ISN_LOADAUTO, 0, name, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005303 break;
5304 case dest_buffer:
5305 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
5306 break;
5307 case dest_window:
5308 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
5309 break;
5310 case dest_tab:
5311 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
5312 break;
5313 case dest_script:
5314 compile_load_scriptvar(cctx,
5315 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
5316 break;
5317 case dest_env:
5318 // Include $ in the name here
5319 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
5320 break;
5321 case dest_reg:
5322 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
5323 break;
5324 case dest_vimvar:
5325 generate_LOADV(cctx, name + 2, TRUE);
5326 break;
5327 case dest_local:
Bram Moolenaarab360522021-01-10 14:02:28 +01005328 if (lvar->lv_from_outer > 0)
5329 generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
5330 type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005331 else
5332 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
5333 break;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005334 case dest_expr:
5335 // list or dict value should already be on the stack.
5336 break;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005337 }
5338}
5339
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005340/*
5341 * Skip over "[expr]" or ".member".
5342 * Does not check for any errors.
5343 */
5344 static char_u *
5345skip_index(char_u *start)
5346{
5347 char_u *p = start;
5348
5349 if (*p == '[')
5350 {
5351 p = skipwhite(p + 1);
5352 (void)skip_expr(&p, NULL);
5353 p = skipwhite(p);
5354 if (*p == ']')
5355 return p + 1;
5356 return p;
5357 }
5358 // if (*p == '.')
5359 return to_name_end(p + 1, TRUE);
5360}
5361
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005362 void
5363vim9_declare_error(char_u *name)
5364{
5365 char *scope = "";
5366
5367 switch (*name)
5368 {
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005369 case 'g': scope = _("global"); break;
5370 case 'b': scope = _("buffer"); break;
5371 case 'w': scope = _("window"); break;
5372 case 't': scope = _("tab"); break;
5373 case 'v': scope = "v:"; break;
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005374 case '$': semsg(_(e_cannot_declare_an_environment_variable), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005375 return;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005376 case '&': semsg(_(e_cannot_declare_an_option), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005377 return;
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02005378 case '@': semsg(_(e_cannot_declare_a_register_str), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005379 return;
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005380 default: return;
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005381 }
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005382 semsg(_(e_cannot_declare_a_scope_variable), scope, name);
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005383}
5384
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005385/*
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005386 * For one assignment figure out the type of destination. Return it in "dest".
5387 * When not recognized "dest" is not set.
5388 * For an option "opt_flags" is set.
5389 * For a v:var "vimvaridx" is set.
5390 * "type" is set to the destination type if known, unchanted otherwise.
5391 * Return FAIL if an error message was given.
5392 */
5393 static int
5394get_var_dest(
5395 char_u *name,
5396 assign_dest_T *dest,
5397 int cmdidx,
5398 int *opt_flags,
5399 int *vimvaridx,
5400 type_T **type,
5401 cctx_T *cctx)
5402{
5403 char_u *p;
5404
5405 if (*name == '&')
5406 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005407 int cc;
5408 long numval;
5409 getoption_T opt_type;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005410
5411 *dest = dest_option;
5412 if (cmdidx == CMD_final || cmdidx == CMD_const)
5413 {
5414 emsg(_(e_const_option));
5415 return FAIL;
5416 }
5417 p = name;
5418 p = find_option_end(&p, opt_flags);
5419 if (p == NULL)
5420 {
5421 // cannot happen?
5422 emsg(_(e_letunexp));
5423 return FAIL;
5424 }
5425 cc = *p;
5426 *p = NUL;
5427 opt_type = get_option_value(skip_option_env_lead(name),
5428 &numval, NULL, *opt_flags);
5429 *p = cc;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005430 switch (opt_type)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005431 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005432 case gov_unknown:
5433 semsg(_(e_unknown_option), name);
5434 return FAIL;
5435 case gov_string:
5436 case gov_hidden_string:
5437 *type = &t_string;
5438 break;
5439 case gov_bool:
5440 case gov_hidden_bool:
5441 *type = &t_bool;
5442 break;
5443 case gov_number:
5444 case gov_hidden_number:
5445 *type = &t_number;
5446 break;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005447 }
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005448 }
5449 else if (*name == '$')
5450 {
5451 *dest = dest_env;
5452 *type = &t_string;
5453 }
5454 else if (*name == '@')
5455 {
5456 if (!valid_yank_reg(name[1], FALSE) || name[1] == '.')
5457 {
5458 emsg_invreg(name[1]);
5459 return FAIL;
5460 }
5461 *dest = dest_reg;
5462 *type = &t_string;
5463 }
5464 else if (STRNCMP(name, "g:", 2) == 0)
5465 {
5466 *dest = dest_global;
5467 }
5468 else if (STRNCMP(name, "b:", 2) == 0)
5469 {
5470 *dest = dest_buffer;
5471 }
5472 else if (STRNCMP(name, "w:", 2) == 0)
5473 {
5474 *dest = dest_window;
5475 }
5476 else if (STRNCMP(name, "t:", 2) == 0)
5477 {
5478 *dest = dest_tab;
5479 }
5480 else if (STRNCMP(name, "v:", 2) == 0)
5481 {
5482 typval_T *vtv;
5483 int di_flags;
5484
5485 *vimvaridx = find_vim_var(name + 2, &di_flags);
5486 if (*vimvaridx < 0)
5487 {
5488 semsg(_(e_variable_not_found_str), name);
5489 return FAIL;
5490 }
5491 // We use the current value of "sandbox" here, is that OK?
5492 if (var_check_ro(di_flags, name, FALSE))
5493 return FAIL;
5494 *dest = dest_vimvar;
5495 vtv = get_vim_var_tv(*vimvaridx);
5496 *type = typval2type_vimvar(vtv, cctx->ctx_type_list);
5497 }
5498 return OK;
5499}
5500
5501/*
5502 * Generate a STORE instruction for "dest", not being "dest_local".
5503 * Return FAIL when out of memory.
5504 */
5505 static int
5506generate_store_var(
5507 cctx_T *cctx,
5508 assign_dest_T dest,
5509 int opt_flags,
5510 int vimvaridx,
5511 int scriptvar_idx,
5512 int scriptvar_sid,
5513 type_T *type,
5514 char_u *name)
5515{
5516 switch (dest)
5517 {
5518 case dest_option:
5519 return generate_STOREOPT(cctx, skip_option_env_lead(name),
5520 opt_flags);
5521 case dest_global:
5522 // include g: with the name, easier to execute that way
Bram Moolenaar03290b82020-12-19 16:30:44 +01005523 return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL
5524 ? ISN_STOREG : ISN_STOREAUTO, 0, name);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005525 case dest_buffer:
5526 // include b: with the name, easier to execute that way
5527 return generate_STORE(cctx, ISN_STOREB, 0, name);
5528 case dest_window:
5529 // include w: with the name, easier to execute that way
5530 return generate_STORE(cctx, ISN_STOREW, 0, name);
5531 case dest_tab:
5532 // include t: with the name, easier to execute that way
5533 return generate_STORE(cctx, ISN_STORET, 0, name);
5534 case dest_env:
5535 return generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5536 case dest_reg:
5537 return generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5538 case dest_vimvar:
5539 return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5540 case dest_script:
5541 if (scriptvar_idx < 0)
5542 {
5543 char_u *name_s = name;
Bram Moolenaar41d61962020-12-06 20:12:43 +01005544 int r;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005545
Bram Moolenaar41d61962020-12-06 20:12:43 +01005546 // "s:" is included in the name.
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005547 r = generate_OLDSCRIPT(cctx, ISN_STORES, name_s,
5548 scriptvar_sid, type);
5549 if (name_s != name)
5550 vim_free(name_s);
5551 return r;
5552 }
5553 return generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
5554 scriptvar_sid, scriptvar_idx, type);
5555 case dest_local:
5556 case dest_expr:
5557 // cannot happen
5558 break;
5559 }
5560 return FAIL;
5561}
5562
Bram Moolenaar752fc692021-01-04 21:57:11 +01005563 static int
5564is_decl_command(int cmdidx)
5565{
5566 return cmdidx == CMD_let || cmdidx == CMD_var
5567 || cmdidx == CMD_final || cmdidx == CMD_const;
5568}
5569
5570/*
5571 * Figure out the LHS type and other properties for an assignment or one item
5572 * of ":unlet" with an index.
5573 * Returns OK or FAIL.
5574 */
5575 static int
5576compile_lhs(
5577 char_u *var_start,
5578 lhs_T *lhs,
5579 int cmdidx,
5580 int heredoc,
5581 int oplen,
5582 cctx_T *cctx)
5583{
5584 char_u *var_end;
5585 int is_decl = is_decl_command(cmdidx);
5586
5587 CLEAR_POINTER(lhs);
5588 lhs->lhs_dest = dest_local;
5589 lhs->lhs_vimvaridx = -1;
5590 lhs->lhs_scriptvar_idx = -1;
5591
5592 // "dest_end" is the end of the destination, including "[expr]" or
5593 // ".name".
5594 // "var_end" is the end of the variable/option/etc. name.
5595 lhs->lhs_dest_end = skip_var_one(var_start, FALSE);
5596 if (*var_start == '@')
5597 var_end = var_start + 2;
5598 else
5599 {
5600 // skip over the leading "&", "&l:", "&g:" and "$"
5601 var_end = skip_option_env_lead(var_start);
5602 var_end = to_name_end(var_end, TRUE);
5603 }
5604
5605 // "a: type" is declaring variable "a" with a type, not dict "a:".
5606 if (is_decl && lhs->lhs_dest_end == var_start + 2
5607 && lhs->lhs_dest_end[-1] == ':')
5608 --lhs->lhs_dest_end;
5609 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
5610 --var_end;
5611
5612 // compute the length of the destination without "[expr]" or ".name"
5613 lhs->lhs_varlen = var_end - var_start;
5614 lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen);
5615 if (lhs->lhs_name == NULL)
5616 return FAIL;
Bram Moolenaar08251752021-01-11 21:20:18 +01005617
5618 if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
5619 // Something follows after the variable: "var[idx]" or "var.key".
5620 lhs->lhs_has_index = TRUE;
5621
Bram Moolenaar752fc692021-01-04 21:57:11 +01005622 if (heredoc)
5623 lhs->lhs_type = &t_list_string;
5624 else
5625 lhs->lhs_type = &t_any;
5626
5627 if (cctx->ctx_skip != SKIP_YES)
5628 {
5629 int declare_error = FALSE;
5630
5631 if (get_var_dest(lhs->lhs_name, &lhs->lhs_dest, cmdidx,
5632 &lhs->lhs_opt_flags, &lhs->lhs_vimvaridx,
5633 &lhs->lhs_type, cctx) == FAIL)
5634 return FAIL;
5635 if (lhs->lhs_dest != dest_local)
5636 {
5637 // Specific kind of variable recognized.
5638 declare_error = is_decl;
5639 }
5640 else
5641 {
5642 int idx;
5643
5644 // No specific kind of variable recognized, just a name.
5645 for (idx = 0; reserved[idx] != NULL; ++idx)
5646 if (STRCMP(reserved[idx], lhs->lhs_name) == 0)
5647 {
5648 semsg(_(e_cannot_use_reserved_name), lhs->lhs_name);
5649 return FAIL;
5650 }
5651
5652
5653 if (lookup_local(var_start, lhs->lhs_varlen,
5654 &lhs->lhs_local_lvar, cctx) == OK)
5655 lhs->lhs_lvar = &lhs->lhs_local_lvar;
5656 else
5657 {
5658 CLEAR_FIELD(lhs->lhs_arg_lvar);
5659 if (arg_exists(var_start, lhs->lhs_varlen,
5660 &lhs->lhs_arg_lvar.lv_idx, &lhs->lhs_arg_lvar.lv_type,
5661 &lhs->lhs_arg_lvar.lv_from_outer, cctx) == OK)
5662 {
5663 if (is_decl)
5664 {
5665 semsg(_(e_str_is_used_as_argument), lhs->lhs_name);
5666 return FAIL;
5667 }
5668 lhs->lhs_lvar = &lhs->lhs_arg_lvar;
5669 }
5670 }
5671 if (lhs->lhs_lvar != NULL)
5672 {
5673 if (is_decl)
5674 {
5675 semsg(_(e_variable_already_declared), lhs->lhs_name);
5676 return FAIL;
5677 }
5678 }
5679 else
5680 {
5681 int script_namespace = lhs->lhs_varlen > 1
5682 && STRNCMP(var_start, "s:", 2) == 0;
5683 int script_var = (script_namespace
5684 ? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
5685 FALSE, cctx)
5686 : script_var_exists(var_start, lhs->lhs_varlen,
5687 TRUE, cctx)) == OK;
5688 imported_T *import =
5689 find_imported(var_start, lhs->lhs_varlen, cctx);
5690
5691 if (script_namespace || script_var || import != NULL)
5692 {
5693 char_u *rawname = lhs->lhs_name
5694 + (lhs->lhs_name[1] == ':' ? 2 : 0);
5695
5696 if (is_decl)
5697 {
5698 if (script_namespace)
5699 semsg(_(e_cannot_declare_script_variable_in_function),
5700 lhs->lhs_name);
5701 else
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005702 semsg(_(e_variable_already_declared_in_script_str),
Bram Moolenaar752fc692021-01-04 21:57:11 +01005703 lhs->lhs_name);
5704 return FAIL;
5705 }
5706 else if (cctx->ctx_ufunc->uf_script_ctx_version
5707 == SCRIPT_VERSION_VIM9
5708 && script_namespace
5709 && !script_var && import == NULL)
5710 {
5711 semsg(_(e_unknown_variable_str), lhs->lhs_name);
5712 return FAIL;
5713 }
5714
5715 lhs->lhs_dest = dest_script;
5716
5717 // existing script-local variables should have a type
5718 lhs->lhs_scriptvar_sid = current_sctx.sc_sid;
5719 if (import != NULL)
5720 lhs->lhs_scriptvar_sid = import->imp_sid;
5721 if (SCRIPT_ID_VALID(lhs->lhs_scriptvar_sid))
5722 {
Bram Moolenaar08251752021-01-11 21:20:18 +01005723 // Check writable only when no index follows.
Bram Moolenaar752fc692021-01-04 21:57:11 +01005724 lhs->lhs_scriptvar_idx = get_script_item_idx(
Bram Moolenaar08251752021-01-11 21:20:18 +01005725 lhs->lhs_scriptvar_sid, rawname,
5726 lhs->lhs_has_index ? ASSIGN_FINAL : ASSIGN_CONST,
5727 cctx);
Bram Moolenaar752fc692021-01-04 21:57:11 +01005728 if (lhs->lhs_scriptvar_idx >= 0)
5729 {
5730 scriptitem_T *si = SCRIPT_ITEM(
5731 lhs->lhs_scriptvar_sid);
5732 svar_T *sv =
5733 ((svar_T *)si->sn_var_vals.ga_data)
5734 + lhs->lhs_scriptvar_idx;
5735 lhs->lhs_type = sv->sv_type;
5736 }
5737 }
5738 }
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005739 else if (check_defined(var_start, lhs->lhs_varlen, cctx, FALSE)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005740 == FAIL)
5741 return FAIL;
5742 }
5743 }
5744
5745 if (declare_error)
5746 {
5747 vim9_declare_error(lhs->lhs_name);
5748 return FAIL;
5749 }
5750 }
5751
5752 // handle "a:name" as a name, not index "name" on "a"
5753 if (lhs->lhs_varlen > 1 || var_start[lhs->lhs_varlen] != ':')
5754 var_end = lhs->lhs_dest_end;
5755
5756 if (lhs->lhs_dest != dest_option)
5757 {
5758 if (is_decl && *var_end == ':')
5759 {
5760 char_u *p;
5761
5762 // parse optional type: "let var: type = expr"
5763 if (!VIM_ISWHITE(var_end[1]))
5764 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01005765 semsg(_(e_white_space_required_after_str_str), ":", var_end);
Bram Moolenaar752fc692021-01-04 21:57:11 +01005766 return FAIL;
5767 }
5768 p = skipwhite(var_end + 1);
5769 lhs->lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
5770 if (lhs->lhs_type == NULL)
5771 return FAIL;
5772 lhs->lhs_has_type = TRUE;
5773 }
5774 else if (lhs->lhs_lvar != NULL)
5775 lhs->lhs_type = lhs->lhs_lvar->lv_type;
5776 }
5777
5778 if (oplen == 3 && !heredoc && lhs->lhs_dest != dest_global
5779 && lhs->lhs_type->tt_type != VAR_STRING
5780 && lhs->lhs_type->tt_type != VAR_ANY)
5781 {
5782 emsg(_(e_can_only_concatenate_to_string));
5783 return FAIL;
5784 }
5785
5786 if (lhs->lhs_lvar == NULL && lhs->lhs_dest == dest_local
5787 && cctx->ctx_skip != SKIP_YES)
5788 {
5789 if (oplen > 1 && !heredoc)
5790 {
5791 // +=, /=, etc. require an existing variable
5792 semsg(_(e_cannot_use_operator_on_new_variable), lhs->lhs_name);
5793 return FAIL;
5794 }
5795 if (!is_decl)
5796 {
5797 semsg(_(e_unknown_variable_str), lhs->lhs_name);
5798 return FAIL;
5799 }
5800
5801 // new local variable
5802 if ((lhs->lhs_type->tt_type == VAR_FUNC
5803 || lhs->lhs_type->tt_type == VAR_PARTIAL)
5804 && var_wrong_func_name(lhs->lhs_name, TRUE))
5805 return FAIL;
5806 lhs->lhs_lvar = reserve_local(cctx, var_start, lhs->lhs_varlen,
5807 cmdidx == CMD_final || cmdidx == CMD_const, lhs->lhs_type);
5808 if (lhs->lhs_lvar == NULL)
5809 return FAIL;
5810 lhs->lhs_new_local = TRUE;
5811 }
5812
5813 lhs->lhs_member_type = lhs->lhs_type;
Bram Moolenaar08251752021-01-11 21:20:18 +01005814 if (lhs->lhs_has_index)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005815 {
5816 // Something follows after the variable: "var[idx]" or "var.key".
5817 // TODO: should we also handle "->func()" here?
5818 if (is_decl)
5819 {
5820 emsg(_(e_cannot_use_index_when_declaring_variable));
5821 return FAIL;
5822 }
5823
5824 if (var_start[lhs->lhs_varlen] == '['
5825 || var_start[lhs->lhs_varlen] == '.')
5826 {
5827 char_u *after = var_start + lhs->lhs_varlen;
5828 char_u *p;
5829
5830 // Only the last index is used below, if there are others
5831 // before it generate code for the expression. Thus for
5832 // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index.
5833 for (;;)
5834 {
5835 p = skip_index(after);
5836 if (*p != '[' && *p != '.')
5837 break;
5838 after = p;
5839 }
5840 if (after > var_start + lhs->lhs_varlen)
5841 {
5842 lhs->lhs_varlen = after - var_start;
5843 lhs->lhs_dest = dest_expr;
5844 // We don't know the type before evaluating the expression,
5845 // use "any" until then.
5846 lhs->lhs_type = &t_any;
5847 }
5848
Bram Moolenaar752fc692021-01-04 21:57:11 +01005849 if (lhs->lhs_type->tt_member == NULL)
5850 lhs->lhs_member_type = &t_any;
5851 else
5852 lhs->lhs_member_type = lhs->lhs_type->tt_member;
5853 }
5854 else
5855 {
5856 semsg("Not supported yet: %s", var_start);
5857 return FAIL;
5858 }
5859 }
5860 return OK;
5861}
5862
5863/*
5864 * Assignment to a list or dict member, or ":unlet" for the item, using the
5865 * information in "lhs".
5866 * Returns OK or FAIL.
5867 */
5868 static int
5869compile_assign_unlet(
5870 char_u *var_start,
5871 lhs_T *lhs,
5872 int is_assign,
5873 type_T *rhs_type,
5874 cctx_T *cctx)
5875{
5876 char_u *p;
5877 int r;
5878 vartype_T dest_type;
5879 size_t varlen = lhs->lhs_varlen;
5880 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005881 int range = FALSE;
Bram Moolenaar752fc692021-01-04 21:57:11 +01005882
5883 // Compile the "idx" in "var[idx]" or "key" in "var.key".
5884 p = var_start + varlen;
5885 if (*p == '[')
5886 {
5887 p = skipwhite(p + 1);
5888 r = compile_expr0(&p, cctx);
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005889
5890 if (r == OK && *skipwhite(p) == ':')
5891 {
5892 // unlet var[idx : idx]
5893 if (is_assign)
5894 {
5895 semsg(_(e_cannot_use_range_with_assignment_str), p);
5896 return FAIL;
5897 }
5898 range = TRUE;
5899 p = skipwhite(p);
5900 if (!IS_WHITE_OR_NUL(p[-1]) || !IS_WHITE_OR_NUL(p[1]))
5901 {
5902 semsg(_(e_white_space_required_before_and_after_str_at_str),
5903 ":", p);
5904 return FAIL;
5905 }
5906 p = skipwhite(p + 1);
5907 r = compile_expr0(&p, cctx);
5908 }
5909
Bram Moolenaar752fc692021-01-04 21:57:11 +01005910 if (r == OK && *skipwhite(p) != ']')
5911 {
5912 // this should not happen
5913 emsg(_(e_missbrac));
5914 r = FAIL;
5915 }
5916 }
5917 else // if (*p == '.')
5918 {
5919 char_u *key_end = to_name_end(p + 1, TRUE);
5920 char_u *key = vim_strnsave(p + 1, key_end - p - 1);
5921
5922 r = generate_PUSHS(cctx, key);
5923 }
5924 if (r == FAIL)
5925 return FAIL;
5926
5927 if (lhs->lhs_type == &t_any)
5928 {
5929 // Index on variable of unknown type: check at runtime.
5930 dest_type = VAR_ANY;
5931 }
5932 else
5933 {
5934 dest_type = lhs->lhs_type->tt_type;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005935 if (dest_type == VAR_DICT && range)
5936 {
5937 emsg(e_cannot_use_range_with_dictionary);
5938 return FAIL;
5939 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01005940 if (dest_type == VAR_DICT && may_generate_2STRING(-1, cctx) == FAIL)
5941 return FAIL;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005942 if (dest_type == VAR_LIST)
5943 {
5944 if (range
5945 && need_type(((type_T **)stack->ga_data)[stack->ga_len - 2],
Bram Moolenaarf30a14d2021-01-17 21:51:24 +01005946 &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005947 return FAIL;
5948 if (need_type(((type_T **)stack->ga_data)[stack->ga_len - 1],
5949 &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
5950 return FAIL;
5951 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01005952 }
5953
5954 // Load the dict or list. On the stack we then have:
5955 // - value (for assignment, not for :unlet)
5956 // - index
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005957 // - for [a : b] second index
Bram Moolenaar752fc692021-01-04 21:57:11 +01005958 // - variable
5959 if (lhs->lhs_dest == dest_expr)
5960 {
5961 int c = var_start[varlen];
5962
5963 // Evaluate "ll[expr]" of "ll[expr][idx]"
5964 p = var_start;
5965 var_start[varlen] = NUL;
5966 if (compile_expr0(&p, cctx) == OK && p != var_start + varlen)
5967 {
5968 // this should not happen
5969 emsg(_(e_missbrac));
5970 return FAIL;
5971 }
5972 var_start[varlen] = c;
5973
5974 lhs->lhs_type = stack->ga_len == 0 ? &t_void
5975 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
5976 // now we can properly check the type
5977 if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void
Bram Moolenaar351ead02021-01-16 16:07:01 +01005978 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx,
Bram Moolenaar752fc692021-01-04 21:57:11 +01005979 FALSE, FALSE) == FAIL)
5980 return FAIL;
5981 }
5982 else
5983 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name,
5984 lhs->lhs_lvar, lhs->lhs_type);
5985
5986 if (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY)
5987 {
5988 if (is_assign)
5989 {
5990 isn_T *isn = generate_instr_drop(cctx, ISN_STOREINDEX, 3);
5991
5992 if (isn == NULL)
5993 return FAIL;
5994 isn->isn_arg.vartype = dest_type;
5995 }
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01005996 else if (range)
5997 {
5998 if (generate_instr_drop(cctx, ISN_UNLETRANGE, 3) == NULL)
5999 return FAIL;
6000 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006001 else
6002 {
6003 if (generate_instr_drop(cctx, ISN_UNLETINDEX, 2) == NULL)
6004 return FAIL;
6005 }
6006 }
6007 else
6008 {
6009 emsg(_(e_indexable_type_required));
6010 return FAIL;
6011 }
6012
6013 return OK;
6014}
6015
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006016/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006017 * Compile declaration and assignment:
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006018 * "let name"
6019 * "var name = expr"
6020 * "final name = expr"
6021 * "const name = expr"
6022 * "name = expr"
6023 * "arg" points to "name".
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006024 * Return NULL for an error.
6025 * Return "arg" if it does not look like a variable list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006026 */
6027 static char_u *
6028compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
6029{
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006030 char_u *var_start;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006031 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006032 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006033 char_u *ret = NULL;
6034 int var_count = 0;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006035 int var_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006036 int semicolon = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006037 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006038 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006039 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006040 int oplen = 0;
6041 int heredoc = FALSE;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006042 type_T *rhs_type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006043 char_u *sp;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006044 int is_decl = is_decl_command(cmdidx);
6045 lhs_T lhs;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006046
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006047 // Skip over the "var" or "[var, var]" to get to any "=".
6048 p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
6049 if (p == NULL)
6050 return *arg == '[' ? arg : NULL;
6051
6052 if (var_count > 0 && is_decl)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006053 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02006054 // TODO: should we allow this, and figure out type inference from list
6055 // members?
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006056 emsg(_(e_cannot_use_list_for_declaration));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006057 return NULL;
6058 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006059 lhs.lhs_name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006060
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006061 sp = p;
6062 p = skipwhite(p);
6063 op = p;
6064 oplen = assignment_len(p, &heredoc);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006065
6066 if (var_count > 0 && oplen == 0)
6067 // can be something like "[1, 2]->func()"
6068 return arg;
6069
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006070 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !IS_WHITE_OR_NUL(op[oplen])))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006071 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02006072 error_white_both(op, oplen);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006073 return NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006074 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006075
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006076 if (heredoc)
6077 {
6078 list_T *l;
6079 listitem_T *li;
6080
6081 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02006082 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006083 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02006084 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaarc0e29012020-09-27 14:22:48 +02006085 if (l == NULL)
6086 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006087
Bram Moolenaar078269b2020-09-21 20:35:55 +02006088 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006089 {
Bram Moolenaar078269b2020-09-21 20:35:55 +02006090 // Push each line and the create the list.
6091 FOR_ALL_LIST_ITEMS(l, li)
6092 {
6093 generate_PUSHS(cctx, li->li_tv.vval.v_string);
6094 li->li_tv.vval.v_string = NULL;
6095 }
6096 generate_NEWLIST(cctx, l->lv_len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006097 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006098 list_free(l);
6099 p += STRLEN(p);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006100 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006101 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006102 else if (var_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006103 {
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006104 char_u *wp;
6105
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006106 // for "[var, var] = expr" evaluate the expression here, loop over the
6107 // list of variables below.
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006108 // A line break may follow the "=".
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02006109
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006110 wp = op + oplen;
Bram Moolenaar8ff16e02020-12-07 21:49:52 +01006111 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006112 return FAIL;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006113 if (compile_expr0(&p, cctx) == FAIL)
6114 return NULL;
6115 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006116
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006117 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006118 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006119 type_T *stacktype;
6120
Bram Moolenaarec5929d2020-04-07 20:53:39 +02006121 stacktype = stack->ga_len == 0 ? &t_void
6122 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006123 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006124 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006125 emsg(_(e_cannot_use_void_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006126 goto theend;
6127 }
Bram Moolenaar351ead02021-01-16 16:07:01 +01006128 if (need_type(stacktype, &t_list_any, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006129 FALSE, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006130 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02006131 // TODO: check the length of a constant list here
Bram Moolenaar9af78762020-06-16 11:34:42 +02006132 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
6133 semicolon);
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006134 if (stacktype->tt_member != NULL)
6135 rhs_type = stacktype->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006136 }
6137 }
6138
6139 /*
6140 * Loop over variables in "[var, var] = expr".
6141 * For "var = expr" and "let var: type" this is done only once.
6142 */
6143 if (var_count > 0)
6144 var_start = skipwhite(arg + 1); // skip over the "["
6145 else
6146 var_start = arg;
6147 for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
6148 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006149 int instr_count = -1;
6150
Bram Moolenaar752fc692021-01-04 21:57:11 +01006151 vim_free(lhs.lhs_name);
6152
6153 /*
6154 * Figure out the LHS type and other properties.
6155 */
6156 if (compile_lhs(var_start, &lhs, cmdidx, heredoc, oplen, cctx) == FAIL)
6157 goto theend;
6158
6159 if (!lhs.lhs_has_index && lhs.lhs_lvar == &lhs.lhs_arg_lvar)
Bram Moolenaar65821722020-08-02 18:58:54 +02006160 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006161 semsg(_(e_cannot_assign_to_argument), lhs.lhs_name);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006162 goto theend;
6163 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006164 if (!is_decl && lhs.lhs_lvar != NULL
6165 && lhs.lhs_lvar->lv_const && !lhs.lhs_has_index)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006166 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006167 semsg(_(e_cannot_assign_to_constant), lhs.lhs_name);
Bram Moolenaardbeecb22020-09-14 18:15:09 +02006168 goto theend;
6169 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006170
6171 if (!heredoc)
6172 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006173 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006174 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006175 if (oplen > 0 && var_count == 0)
6176 {
6177 // skip over the "=" and the expression
6178 p = skipwhite(op + oplen);
6179 compile_expr0(&p, cctx);
6180 }
6181 }
6182 else if (oplen > 0)
6183 {
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006184 int is_const = FALSE;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006185 char_u *wp;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006186
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006187 // For "var = expr" evaluate the expression.
6188 if (var_count == 0)
6189 {
6190 int r;
6191
6192 // for "+=", "*=", "..=" etc. first load the current value
6193 if (*op != '=')
6194 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006195 generate_loadvar(cctx, lhs.lhs_dest, lhs.lhs_name,
6196 lhs.lhs_lvar, lhs.lhs_type);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006197
Bram Moolenaar752fc692021-01-04 21:57:11 +01006198 if (lhs.lhs_has_index)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006199 {
6200 // TODO: get member from list or dict
6201 emsg("Index with operation not supported yet");
6202 goto theend;
6203 }
6204 }
6205
6206 // Compile the expression. Temporarily hide the new local
6207 // variable here, it is not available to this expression.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006208 if (lhs.lhs_new_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006209 --cctx->ctx_locals.ga_len;
6210 instr_count = instr->ga_len;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006211 wp = op + oplen;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006212 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
Bram Moolenaar21e51222020-12-04 12:43:29 +01006213 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006214 if (lhs.lhs_new_local)
Bram Moolenaar21e51222020-12-04 12:43:29 +01006215 ++cctx->ctx_locals.ga_len;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006216 goto theend;
Bram Moolenaar21e51222020-12-04 12:43:29 +01006217 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006218 r = compile_expr0_ext(&p, cctx, &is_const);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006219 if (lhs.lhs_new_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006220 ++cctx->ctx_locals.ga_len;
6221 if (r == FAIL)
6222 goto theend;
6223 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02006224 else if (semicolon && var_idx == var_count - 1)
6225 {
6226 // For "[var; var] = expr" get the rest of the list
6227 if (generate_SLICE(cctx, var_count - 1) == FAIL)
6228 goto theend;
6229 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006230 else
6231 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006232 // For "[var, var] = expr" get the "var_idx" item from the
6233 // list.
6234 if (generate_GETITEM(cctx, var_idx) == FAIL)
Bram Moolenaar7f764942020-12-02 15:11:18 +01006235 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006236 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006237
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006238 rhs_type = stack->ga_len == 0 ? &t_void
Bram Moolenaar6802cce2020-07-19 15:49:49 +02006239 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar752fc692021-01-04 21:57:11 +01006240 if (lhs.lhs_lvar != NULL && (is_decl || !lhs.lhs_has_type))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006241 {
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006242 if ((rhs_type->tt_type == VAR_FUNC
6243 || rhs_type->tt_type == VAR_PARTIAL)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006244 && var_wrong_func_name(lhs.lhs_name, TRUE))
Bram Moolenaar0f769812020-09-12 18:32:34 +02006245 goto theend;
6246
Bram Moolenaar752fc692021-01-04 21:57:11 +01006247 if (lhs.lhs_new_local && !lhs.lhs_has_type)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006248 {
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006249 if (rhs_type->tt_type == VAR_VOID)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006250 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006251 emsg(_(e_cannot_use_void_value));
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006252 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006253 }
6254 else
6255 {
Bram Moolenaar04bdd572020-09-23 13:25:32 +02006256 // An empty list or dict has a &t_unknown member,
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006257 // for a variable that implies &t_any.
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006258 if (rhs_type == &t_list_empty)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006259 lhs.lhs_lvar->lv_type = &t_list_any;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006260 else if (rhs_type == &t_dict_empty)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006261 lhs.lhs_lvar->lv_type = &t_dict_any;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006262 else if (rhs_type == &t_unknown)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006263 lhs.lhs_lvar->lv_type = &t_any;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006264 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006265 lhs.lhs_lvar->lv_type = rhs_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006266 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006267 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006268 else if (*op == '=')
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006269 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006270 type_T *use_type = lhs.lhs_lvar->lv_type;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006271
Bram Moolenaar71abe482020-09-14 22:28:30 +02006272 // without operator check type here, otherwise below
Bram Moolenaar752fc692021-01-04 21:57:11 +01006273 if (lhs.lhs_has_index)
6274 use_type = lhs.lhs_member_type;
Bram Moolenaar351ead02021-01-16 16:07:01 +01006275 if (need_type(rhs_type, use_type, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006276 FALSE, is_const) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006277 goto theend;
6278 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006279 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006280 else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type,
Bram Moolenaar351ead02021-01-16 16:07:01 +01006281 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006282 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006283 }
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006284 else if (cmdidx == CMD_final)
6285 {
6286 emsg(_(e_final_requires_a_value));
6287 goto theend;
6288 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006289 else if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006290 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02006291 emsg(_(e_const_requires_a_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006292 goto theend;
6293 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006294 else if (!lhs.lhs_has_type || lhs.lhs_dest == dest_option)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006295 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02006296 emsg(_(e_type_or_initialization_required));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006297 goto theend;
6298 }
6299 else
6300 {
6301 // variables are always initialized
6302 if (ga_grow(instr, 1) == FAIL)
6303 goto theend;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006304 switch (lhs.lhs_member_type->tt_type)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006305 {
6306 case VAR_BOOL:
6307 generate_PUSHBOOL(cctx, VVAL_FALSE);
6308 break;
6309 case VAR_FLOAT:
6310#ifdef FEAT_FLOAT
6311 generate_PUSHF(cctx, 0.0);
6312#endif
6313 break;
6314 case VAR_STRING:
6315 generate_PUSHS(cctx, NULL);
6316 break;
6317 case VAR_BLOB:
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02006318 generate_PUSHBLOB(cctx, blob_alloc());
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006319 break;
6320 case VAR_FUNC:
6321 generate_PUSHFUNC(cctx, NULL, &t_func_void);
6322 break;
6323 case VAR_LIST:
6324 generate_NEWLIST(cctx, 0);
6325 break;
6326 case VAR_DICT:
6327 generate_NEWDICT(cctx, 0);
6328 break;
6329 case VAR_JOB:
6330 generate_PUSHJOB(cctx, NULL);
6331 break;
6332 case VAR_CHANNEL:
6333 generate_PUSHCHANNEL(cctx, NULL);
6334 break;
6335 case VAR_NUMBER:
6336 case VAR_UNKNOWN:
6337 case VAR_ANY:
6338 case VAR_PARTIAL:
6339 case VAR_VOID:
6340 case VAR_SPECIAL: // cannot happen
6341 generate_PUSHNR(cctx, 0);
6342 break;
6343 }
6344 }
6345 if (var_count == 0)
6346 end = p;
6347 }
6348
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006349 // no need to parse more when skipping
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006350 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006351 break;
6352
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006353 if (oplen > 0 && *op != '=')
6354 {
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006355 type_T *expected;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006356 type_T *stacktype;
6357
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006358 if (*op == '.')
6359 expected = &t_string;
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006360 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006361 expected = lhs.lhs_member_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006362 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006363 if (
6364#ifdef FEAT_FLOAT
6365 // If variable is float operation with number is OK.
6366 !(expected == &t_float && stacktype == &t_number) &&
6367#endif
Bram Moolenaar351ead02021-01-16 16:07:01 +01006368 need_type(stacktype, expected, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006369 FALSE, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006370 goto theend;
6371
6372 if (*op == '.')
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02006373 {
6374 if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL)
6375 goto theend;
6376 }
6377 else if (*op == '+')
6378 {
6379 if (generate_add_instr(cctx,
Bram Moolenaar752fc692021-01-04 21:57:11 +01006380 operator_type(lhs.lhs_member_type, stacktype),
6381 lhs.lhs_member_type, stacktype) == FAIL)
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02006382 goto theend;
6383 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006384 else if (generate_two_op(cctx, op) == FAIL)
6385 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006386 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006387
Bram Moolenaar752fc692021-01-04 21:57:11 +01006388 if (lhs.lhs_has_index)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006389 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006390 // Use the info in "lhs" to store the value at the index in the
6391 // list or dict.
6392 if (compile_assign_unlet(var_start, &lhs, TRUE, rhs_type, cctx)
6393 == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006394 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006395 }
6396 else
6397 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006398 if (is_decl && cmdidx == CMD_const && (lhs.lhs_dest == dest_script
6399 || lhs.lhs_dest == dest_local))
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006400 // ":const var": lock the value, but not referenced variables
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02006401 generate_LOCKCONST(cctx);
6402
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006403 if (is_decl
Bram Moolenaar752fc692021-01-04 21:57:11 +01006404 && (lhs.lhs_type->tt_type == VAR_DICT
6405 || lhs.lhs_type->tt_type == VAR_LIST)
6406 && lhs.lhs_type->tt_member != NULL
6407 && lhs.lhs_type->tt_member != &t_any
6408 && lhs.lhs_type->tt_member != &t_unknown)
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006409 // Set the type in the list or dict, so that it can be checked,
6410 // also in legacy script.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006411 generate_SETTYPE(cctx, lhs.lhs_type);
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006412
Bram Moolenaar752fc692021-01-04 21:57:11 +01006413 if (lhs.lhs_dest != dest_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006414 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006415 if (generate_store_var(cctx, lhs.lhs_dest,
6416 lhs.lhs_opt_flags, lhs.lhs_vimvaridx,
6417 lhs.lhs_scriptvar_idx, lhs.lhs_scriptvar_sid,
6418 lhs.lhs_type, lhs.lhs_name) == FAIL)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006419 goto theend;
6420 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006421 else if (lhs.lhs_lvar != NULL)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006422 {
6423 isn_T *isn = ((isn_T *)instr->ga_data)
6424 + instr->ga_len - 1;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006425
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006426 // optimization: turn "var = 123" from ISN_PUSHNR +
6427 // ISN_STORE into ISN_STORENR
Bram Moolenaarab360522021-01-10 14:02:28 +01006428 if (lhs.lhs_lvar->lv_from_outer == 0
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006429 && instr->ga_len == instr_count + 1
6430 && isn->isn_type == ISN_PUSHNR)
6431 {
6432 varnumber_T val = isn->isn_arg.number;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006433
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006434 isn->isn_type = ISN_STORENR;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006435 isn->isn_arg.storenr.stnr_idx = lhs.lhs_lvar->lv_idx;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006436 isn->isn_arg.storenr.stnr_val = val;
6437 if (stack->ga_len > 0)
6438 --stack->ga_len;
6439 }
Bram Moolenaarab360522021-01-10 14:02:28 +01006440 else if (lhs.lhs_lvar->lv_from_outer > 0)
6441 generate_STOREOUTER(cctx, lhs.lhs_lvar->lv_idx,
6442 lhs.lhs_lvar->lv_from_outer);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006443 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006444 generate_STORE(cctx, ISN_STORE, lhs.lhs_lvar->lv_idx, NULL);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006445 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006446 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006447
6448 if (var_idx + 1 < var_count)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006449 var_start = skipwhite(lhs.lhs_dest_end + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006450 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006451
6452 // for "[var, var] = expr" drop the "expr" value
Bram Moolenaar9af78762020-06-16 11:34:42 +02006453 if (var_count > 0 && !semicolon)
6454 {
Bram Moolenaarec792292020-12-13 21:26:56 +01006455 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
Bram Moolenaar9af78762020-06-16 11:34:42 +02006456 goto theend;
6457 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006458
Bram Moolenaarb2097502020-07-19 17:17:02 +02006459 ret = skipwhite(end);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006460
6461theend:
Bram Moolenaar752fc692021-01-04 21:57:11 +01006462 vim_free(lhs.lhs_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006463 return ret;
6464}
6465
6466/*
Bram Moolenaar17126b12021-01-07 22:03:02 +01006467 * Check for an assignment at "eap->cmd", compile it if found.
6468 * Return NOTDONE if there is none, FAIL for failure, OK if done.
6469 */
6470 static int
6471may_compile_assignment(exarg_T *eap, char_u **line, cctx_T *cctx)
6472{
6473 char_u *pskip;
6474 char_u *p;
6475
6476 // Assuming the command starts with a variable or function name,
6477 // find what follows.
6478 // Skip over "var.member", "var[idx]" and the like.
6479 // Also "&opt = val", "$ENV = val" and "@r = val".
6480 pskip = (*eap->cmd == '&' || *eap->cmd == '$' || *eap->cmd == '@')
6481 ? eap->cmd + 1 : eap->cmd;
6482 p = to_name_end(pskip, TRUE);
6483 if (p > eap->cmd && *p != NUL)
6484 {
6485 char_u *var_end;
6486 int oplen;
6487 int heredoc;
6488
6489 if (eap->cmd[0] == '@')
6490 var_end = eap->cmd + 2;
6491 else
6492 var_end = find_name_end(pskip, NULL, NULL,
6493 FNE_CHECK_START | FNE_INCL_BR);
6494 oplen = assignment_len(skipwhite(var_end), &heredoc);
6495 if (oplen > 0)
6496 {
6497 size_t len = p - eap->cmd;
6498
6499 // Recognize an assignment if we recognize the variable
6500 // name:
6501 // "g:var = expr"
6502 // "local = expr" where "local" is a local var.
6503 // "script = expr" where "script" is a script-local var.
6504 // "import = expr" where "import" is an imported var
6505 // "&opt = expr"
6506 // "$ENV = expr"
6507 // "@r = expr"
6508 if (*eap->cmd == '&'
6509 || *eap->cmd == '$'
6510 || *eap->cmd == '@'
6511 || ((len) > 2 && eap->cmd[1] == ':')
Bram Moolenaare0890d62021-02-17 14:52:14 +01006512 || variable_exists(eap->cmd, len, cctx))
Bram Moolenaar17126b12021-01-07 22:03:02 +01006513 {
6514 *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
6515 if (*line == NULL || *line == eap->cmd)
6516 return FAIL;
6517 return OK;
6518 }
6519 }
6520 }
6521
6522 if (*eap->cmd == '[')
6523 {
6524 // [var, var] = expr
6525 *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
6526 if (*line == NULL)
6527 return FAIL;
6528 if (*line != eap->cmd)
6529 return OK;
6530 }
6531 return NOTDONE;
6532}
6533
6534/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006535 * Check if "name" can be "unlet".
6536 */
6537 int
6538check_vim9_unlet(char_u *name)
6539{
6540 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
6541 {
Bram Moolenaar84367732020-08-23 15:21:55 +02006542 // "unlet s:var" is allowed in legacy script.
6543 if (*name == 's' && !script_is_vim9())
6544 return OK;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006545 semsg(_(e_cannot_unlet_str), name);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006546 return FAIL;
6547 }
6548 return OK;
6549}
6550
6551/*
6552 * Callback passed to ex_unletlock().
6553 */
6554 static int
6555compile_unlet(
6556 lval_T *lvp,
6557 char_u *name_end,
6558 exarg_T *eap,
6559 int deep UNUSED,
6560 void *coookie)
6561{
Bram Moolenaar752fc692021-01-04 21:57:11 +01006562 cctx_T *cctx = coookie;
6563 char_u *p = lvp->ll_name;
6564 int cc = *name_end;
6565 int ret = OK;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006566
Bram Moolenaar752fc692021-01-04 21:57:11 +01006567 if (cctx->ctx_skip == SKIP_YES)
6568 return OK;
6569
6570 *name_end = NUL;
6571 if (*p == '$')
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006572 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006573 // :unlet $ENV_VAR
6574 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
6575 }
6576 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
6577 {
6578 lhs_T lhs;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006579
Bram Moolenaar752fc692021-01-04 21:57:11 +01006580 // This is similar to assigning: lookup the list/dict, compile the
6581 // idx/key. Then instead of storing the value unlet the item.
6582 // unlet {list}[idx]
6583 // unlet {dict}[key] dict.key
6584 //
6585 // Figure out the LHS type and other properties.
6586 //
6587 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, 0, cctx);
6588
6589 // : unlet an indexed item
6590 if (!lhs.lhs_has_index)
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006591 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006592 iemsg("called compile_lhs() without an index");
6593 ret = FAIL;
6594 }
6595 else
6596 {
6597 // Use the info in "lhs" to unlet the item at the index in the
6598 // list or dict.
6599 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006600 }
6601
Bram Moolenaar752fc692021-01-04 21:57:11 +01006602 vim_free(lhs.lhs_name);
6603 }
6604 else if (check_vim9_unlet(p) == FAIL)
6605 {
6606 ret = FAIL;
6607 }
6608 else
6609 {
6610 // Normal name. Only supports g:, w:, t: and b: namespaces.
6611 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006612 }
6613
Bram Moolenaar752fc692021-01-04 21:57:11 +01006614 *name_end = cc;
6615 return ret;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006616}
6617
6618/*
6619 * compile "unlet var", "lock var" and "unlock var"
6620 * "arg" points to "var".
6621 */
6622 static char_u *
6623compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
6624{
6625 char_u *p = arg;
6626
6627 if (eap->cmdidx != CMD_unlet)
6628 {
6629 emsg("Sorry, :lock and unlock not implemented yet");
6630 return NULL;
6631 }
6632
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006633 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
6634 compile_unlet, cctx);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006635 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
6636}
6637
6638/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006639 * Compile an :import command.
6640 */
6641 static char_u *
6642compile_import(char_u *arg, cctx_T *cctx)
6643{
Bram Moolenaar1c991142020-07-04 13:15:31 +02006644 return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006645}
6646
6647/*
6648 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
6649 */
6650 static int
6651compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
6652{
6653 garray_T *instr = &cctx->ctx_instr;
6654 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
6655
6656 if (endlabel == NULL)
6657 return FAIL;
6658 endlabel->el_next = *el;
6659 *el = endlabel;
6660 endlabel->el_end_label = instr->ga_len;
6661
6662 generate_JUMP(cctx, when, 0);
6663 return OK;
6664}
6665
6666 static void
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01006667compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006668{
6669 garray_T *instr = &cctx->ctx_instr;
6670
6671 while (*el != NULL)
6672 {
6673 endlabel_T *cur = (*el);
6674 isn_T *isn;
6675
6676 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01006677 isn->isn_arg.jump.jump_where = jump_where;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006678 *el = cur->el_next;
6679 vim_free(cur);
6680 }
6681}
6682
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006683 static void
6684compile_free_jump_to_end(endlabel_T **el)
6685{
6686 while (*el != NULL)
6687 {
6688 endlabel_T *cur = (*el);
6689
6690 *el = cur->el_next;
6691 vim_free(cur);
6692 }
6693}
6694
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006695/*
6696 * Create a new scope and set up the generic items.
6697 */
6698 static scope_T *
6699new_scope(cctx_T *cctx, scopetype_T type)
6700{
6701 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
6702
6703 if (scope == NULL)
6704 return NULL;
6705 scope->se_outer = cctx->ctx_scope;
6706 cctx->ctx_scope = scope;
6707 scope->se_type = type;
6708 scope->se_local_count = cctx->ctx_locals.ga_len;
6709 return scope;
6710}
6711
6712/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006713 * Free the current scope and go back to the outer scope.
6714 */
6715 static void
6716drop_scope(cctx_T *cctx)
6717{
6718 scope_T *scope = cctx->ctx_scope;
6719
6720 if (scope == NULL)
6721 {
6722 iemsg("calling drop_scope() without a scope");
6723 return;
6724 }
6725 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006726 switch (scope->se_type)
6727 {
6728 case IF_SCOPE:
6729 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
6730 case FOR_SCOPE:
6731 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
6732 case WHILE_SCOPE:
6733 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
6734 case TRY_SCOPE:
6735 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
6736 case NO_SCOPE:
6737 case BLOCK_SCOPE:
6738 break;
6739 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006740 vim_free(scope);
6741}
6742
6743/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006744 * compile "if expr"
6745 *
6746 * "if expr" Produces instructions:
6747 * EVAL expr Push result of "expr"
6748 * JUMP_IF_FALSE end
6749 * ... body ...
6750 * end:
6751 *
6752 * "if expr | else" Produces instructions:
6753 * EVAL expr Push result of "expr"
6754 * JUMP_IF_FALSE else
6755 * ... body ...
6756 * JUMP_ALWAYS end
6757 * else:
6758 * ... body ...
6759 * end:
6760 *
6761 * "if expr1 | elseif expr2 | else" Produces instructions:
6762 * EVAL expr Push result of "expr"
6763 * JUMP_IF_FALSE elseif
6764 * ... body ...
6765 * JUMP_ALWAYS end
6766 * elseif:
6767 * EVAL expr Push result of "expr"
6768 * JUMP_IF_FALSE else
6769 * ... body ...
6770 * JUMP_ALWAYS end
6771 * else:
6772 * ... body ...
6773 * end:
6774 */
6775 static char_u *
6776compile_if(char_u *arg, cctx_T *cctx)
6777{
6778 char_u *p = arg;
6779 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006780 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006781 scope_T *scope;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006782 skip_T skip_save = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006783 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006784
Bram Moolenaara5565e42020-05-09 15:44:01 +02006785 CLEAR_FIELD(ppconst);
6786 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006787 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006788 clear_ppconst(&ppconst);
6789 return NULL;
6790 }
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01006791 if (!ends_excmd2(arg, skipwhite(p)))
6792 {
6793 semsg(_(e_trailing_arg), p);
6794 return NULL;
6795 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02006796 if (cctx->ctx_skip == SKIP_YES)
6797 clear_ppconst(&ppconst);
6798 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaara5565e42020-05-09 15:44:01 +02006799 {
Bram Moolenaar13106602020-10-04 16:06:05 +02006800 int error = FALSE;
6801 int v;
6802
Bram Moolenaara5565e42020-05-09 15:44:01 +02006803 // The expression results in a constant.
Bram Moolenaar13106602020-10-04 16:06:05 +02006804 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
Bram Moolenaardda749c2020-10-04 17:24:29 +02006805 clear_ppconst(&ppconst);
Bram Moolenaar13106602020-10-04 16:06:05 +02006806 if (error)
6807 return NULL;
6808 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006809 }
6810 else
6811 {
6812 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006813 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006814 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006815 return NULL;
Bram Moolenaar13106602020-10-04 16:06:05 +02006816 if (bool_on_stack(cctx) == FAIL)
6817 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006818 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006819
6820 scope = new_scope(cctx, IF_SCOPE);
6821 if (scope == NULL)
6822 return NULL;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006823 scope->se_skip_save = skip_save;
6824 // "is_had_return" will be reset if any block does not end in :return
6825 scope->se_u.se_if.is_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006826
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006827 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006828 {
6829 // "where" is set when ":elseif", "else" or ":endif" is found
6830 scope->se_u.se_if.is_if_label = instr->ga_len;
6831 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
6832 }
6833 else
6834 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006835
Bram Moolenaarced68a02021-01-24 17:53:47 +01006836#ifdef FEAT_PROFILE
6837 if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
6838 && skip_save != SKIP_YES)
6839 {
6840 // generated a profile start, need to generate a profile end, since it
6841 // won't be done after returning
6842 cctx->ctx_skip = SKIP_NOT;
6843 generate_instr(cctx, ISN_PROF_END);
6844 cctx->ctx_skip = SKIP_YES;
6845 }
6846#endif
6847
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006848 return p;
6849}
6850
6851 static char_u *
6852compile_elseif(char_u *arg, cctx_T *cctx)
6853{
6854 char_u *p = arg;
6855 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006856 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006857 isn_T *isn;
6858 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006859 ppconst_T ppconst;
Bram Moolenaar749639e2020-08-27 23:08:47 +02006860 skip_T save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006861
6862 if (scope == NULL || scope->se_type != IF_SCOPE)
6863 {
6864 emsg(_(e_elseif_without_if));
6865 return NULL;
6866 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01006867 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006868 if (!cctx->ctx_had_return)
6869 scope->se_u.se_if.is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006870
Bram Moolenaarced68a02021-01-24 17:53:47 +01006871 if (cctx->ctx_skip == SKIP_NOT)
6872 {
6873 // previous block was executed, this one and following will not
6874 cctx->ctx_skip = SKIP_YES;
6875 scope->se_u.se_if.is_seen_skip_not = TRUE;
6876 }
6877 if (scope->se_u.se_if.is_seen_skip_not)
6878 {
6879 // A previous block was executed, skip over expression and bail out.
6880 // Do not count the "elseif" for profiling.
6881#ifdef FEAT_PROFILE
6882 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
6883 .isn_type == ISN_PROF_START)
6884 --instr->ga_len;
6885#endif
6886 skip_expr_cctx(&p, cctx);
6887 return p;
6888 }
6889
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006890 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006891 {
6892 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006893 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006894 return NULL;
6895 // previous "if" or "elseif" jumps here
6896 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6897 isn->isn_arg.jump.jump_where = instr->ga_len;
6898 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006899
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006900 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02006901 CLEAR_FIELD(ppconst);
Bram Moolenaar749639e2020-08-27 23:08:47 +02006902 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarced68a02021-01-24 17:53:47 +01006903 {
Bram Moolenaar749639e2020-08-27 23:08:47 +02006904 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaarced68a02021-01-24 17:53:47 +01006905#ifdef FEAT_PROFILE
6906 if (cctx->ctx_profiling)
6907 {
6908 // the previous block was skipped, need to profile this line
6909 generate_instr(cctx, ISN_PROF_START);
6910 instr_count = instr->ga_len;
6911 }
6912#endif
6913 }
Bram Moolenaar7f141552020-05-09 17:35:53 +02006914 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006915 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02006916 clear_ppconst(&ppconst);
6917 return NULL;
6918 }
Bram Moolenaar749639e2020-08-27 23:08:47 +02006919 cctx->ctx_skip = save_skip;
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01006920 if (!ends_excmd2(arg, skipwhite(p)))
6921 {
6922 semsg(_(e_trailing_arg), p);
6923 return NULL;
6924 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02006925 if (scope->se_skip_save == SKIP_YES)
6926 clear_ppconst(&ppconst);
6927 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaar7f141552020-05-09 17:35:53 +02006928 {
Bram Moolenaar13106602020-10-04 16:06:05 +02006929 int error = FALSE;
6930 int v;
6931
Bram Moolenaar7f141552020-05-09 17:35:53 +02006932 // The expression results in a constant.
6933 // TODO: how about nesting?
Bram Moolenaar13106602020-10-04 16:06:05 +02006934 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
6935 if (error)
6936 return NULL;
6937 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006938 clear_ppconst(&ppconst);
6939 scope->se_u.se_if.is_if_label = -1;
6940 }
6941 else
6942 {
6943 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006944 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006945 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006946 return NULL;
Bram Moolenaar13106602020-10-04 16:06:05 +02006947 if (bool_on_stack(cctx) == FAIL)
6948 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006949
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006950 // "where" is set when ":elseif", "else" or ":endif" is found
6951 scope->se_u.se_if.is_if_label = instr->ga_len;
6952 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
6953 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006954
6955 return p;
6956}
6957
6958 static char_u *
6959compile_else(char_u *arg, cctx_T *cctx)
6960{
6961 char_u *p = arg;
6962 garray_T *instr = &cctx->ctx_instr;
6963 isn_T *isn;
6964 scope_T *scope = cctx->ctx_scope;
6965
6966 if (scope == NULL || scope->se_type != IF_SCOPE)
6967 {
6968 emsg(_(e_else_without_if));
6969 return NULL;
6970 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01006971 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006972 if (!cctx->ctx_had_return)
6973 scope->se_u.se_if.is_had_return = FALSE;
6974 scope->se_u.se_if.is_seen_else = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006975
Bram Moolenaarced68a02021-01-24 17:53:47 +01006976#ifdef FEAT_PROFILE
6977 if (cctx->ctx_profiling)
6978 {
6979 if (cctx->ctx_skip == SKIP_NOT
6980 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
6981 .isn_type == ISN_PROF_START)
6982 // the previous block was executed, do not count "else" for profiling
6983 --instr->ga_len;
6984 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
6985 {
6986 // the previous block was not executed, this one will, do count the
6987 // "else" for profiling
6988 cctx->ctx_skip = SKIP_NOT;
6989 generate_instr(cctx, ISN_PROF_END);
6990 generate_instr(cctx, ISN_PROF_START);
6991 cctx->ctx_skip = SKIP_YES;
6992 }
6993 }
6994#endif
6995
6996 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006997 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02006998 // jump from previous block to the end, unless the else block is empty
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006999 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007000 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02007001 if (!cctx->ctx_had_return
7002 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
7003 JUMP_ALWAYS, cctx) == FAIL)
7004 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007005 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007006
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007007 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02007008 {
7009 if (scope->se_u.se_if.is_if_label >= 0)
7010 {
7011 // previous "if" or "elseif" jumps here
7012 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7013 isn->isn_arg.jump.jump_where = instr->ga_len;
7014 scope->se_u.se_if.is_if_label = -1;
7015 }
7016 }
7017
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007018 if (cctx->ctx_skip != SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02007019 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
7020 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007021
7022 return p;
7023}
7024
7025 static char_u *
7026compile_endif(char_u *arg, cctx_T *cctx)
7027{
7028 scope_T *scope = cctx->ctx_scope;
7029 ifscope_T *ifscope;
7030 garray_T *instr = &cctx->ctx_instr;
7031 isn_T *isn;
7032
7033 if (scope == NULL || scope->se_type != IF_SCOPE)
7034 {
7035 emsg(_(e_endif_without_if));
7036 return NULL;
7037 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007038 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007039 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007040 if (!cctx->ctx_had_return)
7041 ifscope->is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007042
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007043 if (scope->se_u.se_if.is_if_label >= 0)
7044 {
7045 // previous "if" or "elseif" jumps here
7046 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7047 isn->isn_arg.jump.jump_where = instr->ga_len;
7048 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007049 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007050 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
Bram Moolenaarced68a02021-01-24 17:53:47 +01007051
7052#ifdef FEAT_PROFILE
7053 // even when skipping we count the endif as executed, unless the block it's
7054 // in is skipped
7055 if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
7056 && scope->se_skip_save != SKIP_YES)
7057 {
7058 cctx->ctx_skip = SKIP_NOT;
7059 generate_instr(cctx, ISN_PROF_START);
7060 }
7061#endif
Bram Moolenaarefd88552020-06-18 20:50:10 +02007062 cctx->ctx_skip = scope->se_skip_save;
7063
7064 // If all the blocks end in :return and there is an :else then the
7065 // had_return flag is set.
7066 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007067
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007068 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007069 return arg;
7070}
7071
7072/*
Bram Moolenaar792f7862020-11-23 08:31:18 +01007073 * Compile "for var in expr":
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007074 *
7075 * Produces instructions:
7076 * PUSHNR -1
7077 * STORE loop-idx Set index to -1
Bram Moolenaar792f7862020-11-23 08:31:18 +01007078 * EVAL expr result of "expr" on top of stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007079 * top: FOR loop-idx, end Increment index, use list on bottom of stack
7080 * - if beyond end, jump to "end"
7081 * - otherwise get item from list and push it
7082 * STORE var Store item in "var"
7083 * ... body ...
7084 * JUMP top Jump back to repeat
7085 * end: DROP Drop the result of "expr"
7086 *
Bram Moolenaar792f7862020-11-23 08:31:18 +01007087 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
7088 * UNPACK 2 Split item in 2
7089 * STORE var1 Store item in "var1"
7090 * STORE var2 Store item in "var2"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007091 */
7092 static char_u *
Bram Moolenaar792f7862020-11-23 08:31:18 +01007093compile_for(char_u *arg_start, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007094{
Bram Moolenaar792f7862020-11-23 08:31:18 +01007095 char_u *arg;
7096 char_u *arg_end;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007097 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007098 char_u *p;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007099 char_u *wp;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007100 int var_count = 0;
7101 int semicolon = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007102 size_t varlen;
7103 garray_T *instr = &cctx->ctx_instr;
7104 garray_T *stack = &cctx->ctx_type_stack;
7105 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007106 lvar_T *loop_lvar; // loop iteration variable
7107 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007108 type_T *vartype;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007109 type_T *item_type = &t_any;
7110 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007111
Bram Moolenaar792f7862020-11-23 08:31:18 +01007112 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
Bram Moolenaar036d0712021-01-17 20:23:38 +01007113 if (p == NULL)
7114 return NULL;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007115 if (var_count == 0)
7116 var_count = 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007117
7118 // consume "in"
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007119 wp = p;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007120 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
7121 return NULL;
7122 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007123 {
7124 emsg(_(e_missing_in));
7125 return NULL;
7126 }
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007127 wp = p + 2;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007128 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
7129 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007130
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007131 scope = new_scope(cctx, FOR_SCOPE);
7132 if (scope == NULL)
7133 return NULL;
7134
Bram Moolenaar792f7862020-11-23 08:31:18 +01007135 // Reserve a variable to store the loop iteration counter and initialize it
7136 // to -1.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007137 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
7138 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007139 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007140 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007141 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007142 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007143 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007144 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007145
7146 // compile "expr", it remains on the stack until "endfor"
7147 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007148 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007149 {
7150 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007151 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007152 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007153 arg_end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007154
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02007155 // Now that we know the type of "var", check that it is a list, now or at
7156 // runtime.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007157 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar351ead02021-01-16 16:07:01 +01007158 if (need_type(vartype, &t_list_any, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007159 {
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007160 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007161 return NULL;
7162 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007163
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02007164 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar792f7862020-11-23 08:31:18 +01007165 {
7166 if (var_count == 1)
7167 item_type = vartype->tt_member;
7168 else if (vartype->tt_member->tt_type == VAR_LIST
7169 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
7170 item_type = vartype->tt_member->tt_member;
7171 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007172
7173 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007174 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007175 generate_FOR(cctx, loop_lvar->lv_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007176
Bram Moolenaar792f7862020-11-23 08:31:18 +01007177 arg = arg_start;
7178 if (var_count > 1)
7179 {
7180 generate_UNPACK(cctx, var_count, semicolon);
7181 arg = skipwhite(arg + 1); // skip white after '['
7182
7183 // the list item is replaced by a number of items
7184 if (ga_grow(stack, var_count - 1) == FAIL)
7185 {
7186 drop_scope(cctx);
7187 return NULL;
7188 }
7189 --stack->ga_len;
7190 for (idx = 0; idx < var_count; ++idx)
7191 {
7192 ((type_T **)stack->ga_data)[stack->ga_len] =
7193 (semicolon && idx == 0) ? vartype : item_type;
7194 ++stack->ga_len;
7195 }
7196 }
7197
7198 for (idx = 0; idx < var_count; ++idx)
7199 {
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007200 assign_dest_T dest = dest_local;
7201 int opt_flags = 0;
7202 int vimvaridx = -1;
7203 type_T *type = &t_any;
7204
7205 p = skip_var_one(arg, FALSE);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007206 varlen = p - arg;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007207 name = vim_strnsave(arg, varlen);
7208 if (name == NULL)
7209 goto failed;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007210
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007211 // TODO: script var not supported?
7212 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
7213 &vimvaridx, &type, cctx) == FAIL)
7214 goto failed;
7215 if (dest != dest_local)
Bram Moolenaar792f7862020-11-23 08:31:18 +01007216 {
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007217 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
7218 0, 0, type, name) == FAIL)
7219 goto failed;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007220 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007221 else
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007222 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01007223 if (lookup_local(arg, varlen, NULL, cctx) == OK)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007224 {
7225 semsg(_(e_variable_already_declared), arg);
7226 goto failed;
7227 }
7228
Bram Moolenaarea870692020-12-02 14:24:30 +01007229 if (STRNCMP(name, "s:", 2) == 0)
7230 {
7231 semsg(_(e_cannot_declare_script_variable_in_function), name);
7232 goto failed;
7233 }
7234
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007235 // Reserve a variable to store "var".
7236 // TODO: check for type
7237 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
7238 if (var_lvar == NULL)
7239 // out of memory or used as an argument
7240 goto failed;
7241
7242 if (semicolon && idx == var_count - 1)
7243 var_lvar->lv_type = vartype;
7244 else
7245 var_lvar->lv_type = item_type;
7246 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
7247 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007248
Bram Moolenaar036d0712021-01-17 20:23:38 +01007249 if (*p == ':')
7250 p = skip_type(skipwhite(p + 1), FALSE);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007251 if (*p == ',' || *p == ';')
7252 ++p;
7253 arg = skipwhite(p);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007254 vim_free(name);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007255 }
7256
7257 return arg_end;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007258
7259failed:
7260 vim_free(name);
7261 drop_scope(cctx);
7262 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007263}
7264
7265/*
7266 * compile "endfor"
7267 */
7268 static char_u *
7269compile_endfor(char_u *arg, cctx_T *cctx)
7270{
7271 garray_T *instr = &cctx->ctx_instr;
7272 scope_T *scope = cctx->ctx_scope;
7273 forscope_T *forscope;
7274 isn_T *isn;
7275
7276 if (scope == NULL || scope->se_type != FOR_SCOPE)
7277 {
7278 emsg(_(e_for));
7279 return NULL;
7280 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007281 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007282 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007283 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007284
7285 // At end of ":for" scope jump back to the FOR instruction.
7286 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
7287
7288 // Fill in the "end" label in the FOR statement so it can jump here
7289 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
7290 isn->isn_arg.forloop.for_end = instr->ga_len;
7291
7292 // Fill in the "end" label any BREAK statements
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007293 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007294
7295 // Below the ":for" scope drop the "expr" list from the stack.
7296 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
7297 return NULL;
7298
7299 vim_free(scope);
7300
7301 return arg;
7302}
7303
7304/*
7305 * compile "while expr"
7306 *
7307 * Produces instructions:
7308 * top: EVAL expr Push result of "expr"
7309 * JUMP_IF_FALSE end jump if false
7310 * ... body ...
7311 * JUMP top Jump back to repeat
7312 * end:
7313 *
7314 */
7315 static char_u *
7316compile_while(char_u *arg, cctx_T *cctx)
7317{
7318 char_u *p = arg;
7319 garray_T *instr = &cctx->ctx_instr;
7320 scope_T *scope;
7321
7322 scope = new_scope(cctx, WHILE_SCOPE);
7323 if (scope == NULL)
7324 return NULL;
7325
Bram Moolenaarb2049902021-01-24 12:53:53 +01007326 // "endwhile" jumps back here, one before when profiling
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007327 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaarf002a412021-01-24 13:34:18 +01007328#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01007329 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
7330 .isn_type == ISN_PROF_START)
7331 --scope->se_u.se_while.ws_top_label;
Bram Moolenaarf002a412021-01-24 13:34:18 +01007332#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007333
7334 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02007335 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007336 return NULL;
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007337 if (!ends_excmd2(arg, skipwhite(p)))
7338 {
7339 semsg(_(e_trailing_arg), p);
7340 return NULL;
7341 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007342
Bram Moolenaar13106602020-10-04 16:06:05 +02007343 if (bool_on_stack(cctx) == FAIL)
7344 return FAIL;
7345
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007346 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007347 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007348 JUMP_IF_FALSE, cctx) == FAIL)
7349 return FAIL;
7350
7351 return p;
7352}
7353
7354/*
7355 * compile "endwhile"
7356 */
7357 static char_u *
7358compile_endwhile(char_u *arg, cctx_T *cctx)
7359{
7360 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007361 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007362
7363 if (scope == NULL || scope->se_type != WHILE_SCOPE)
7364 {
7365 emsg(_(e_while));
7366 return NULL;
7367 }
7368 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007369 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007370
Bram Moolenaarf002a412021-01-24 13:34:18 +01007371#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01007372 // count the endwhile before jumping
7373 may_generate_prof_end(cctx, cctx->ctx_lnum);
Bram Moolenaarf002a412021-01-24 13:34:18 +01007374#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01007375
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007376 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007377 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007378
7379 // Fill in the "end" label in the WHILE statement so it can jump here.
7380 // And in any jumps for ":break"
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007381 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
7382 instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007383
7384 vim_free(scope);
7385
7386 return arg;
7387}
7388
7389/*
7390 * compile "continue"
7391 */
7392 static char_u *
7393compile_continue(char_u *arg, cctx_T *cctx)
7394{
7395 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007396 int try_scopes = 0;
7397 int loop_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007398
7399 for (;;)
7400 {
7401 if (scope == NULL)
7402 {
7403 emsg(_(e_continue));
7404 return NULL;
7405 }
Bram Moolenaarc150c092021-02-13 15:02:46 +01007406 if (scope->se_type == FOR_SCOPE)
7407 {
7408 loop_label = scope->se_u.se_for.fs_top_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007409 break;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007410 }
7411 if (scope->se_type == WHILE_SCOPE)
7412 {
7413 loop_label = scope->se_u.se_while.ws_top_label;
7414 break;
7415 }
7416 if (scope->se_type == TRY_SCOPE)
7417 ++try_scopes;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007418 scope = scope->se_outer;
7419 }
7420
Bram Moolenaarc150c092021-02-13 15:02:46 +01007421 if (try_scopes > 0)
7422 // Inside one or more try/catch blocks we first need to jump to the
7423 // "finally" or "endtry" to cleanup.
7424 generate_TRYCONT(cctx, try_scopes, loop_label);
7425 else
7426 // Jump back to the FOR or WHILE instruction.
7427 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
7428
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007429 return arg;
7430}
7431
7432/*
7433 * compile "break"
7434 */
7435 static char_u *
7436compile_break(char_u *arg, cctx_T *cctx)
7437{
7438 scope_T *scope = cctx->ctx_scope;
7439 endlabel_T **el;
7440
7441 for (;;)
7442 {
7443 if (scope == NULL)
7444 {
7445 emsg(_(e_break));
7446 return NULL;
7447 }
7448 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
7449 break;
7450 scope = scope->se_outer;
7451 }
7452
7453 // Jump to the end of the FOR or WHILE loop.
7454 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007455 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007456 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007457 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007458 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
7459 return FAIL;
7460
7461 return arg;
7462}
7463
7464/*
7465 * compile "{" start of block
7466 */
7467 static char_u *
7468compile_block(char_u *arg, cctx_T *cctx)
7469{
7470 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
7471 return NULL;
7472 return skipwhite(arg + 1);
7473}
7474
7475/*
7476 * compile end of block: drop one scope
7477 */
7478 static void
7479compile_endblock(cctx_T *cctx)
7480{
7481 scope_T *scope = cctx->ctx_scope;
7482
7483 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007484 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007485 vim_free(scope);
7486}
7487
7488/*
7489 * compile "try"
7490 * Creates a new scope for the try-endtry, pointing to the first catch and
7491 * finally.
7492 * Creates another scope for the "try" block itself.
7493 * TRY instruction sets up exception handling at runtime.
7494 *
7495 * "try"
7496 * TRY -> catch1, -> finally push trystack entry
7497 * ... try block
7498 * "throw {exception}"
7499 * EVAL {exception}
7500 * THROW create exception
7501 * ... try block
7502 * " catch {expr}"
7503 * JUMP -> finally
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01007504 * catch1: PUSH exception
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007505 * EVAL {expr}
7506 * MATCH
7507 * JUMP nomatch -> catch2
7508 * CATCH remove exception
7509 * ... catch block
7510 * " catch"
7511 * JUMP -> finally
7512 * catch2: CATCH remove exception
7513 * ... catch block
7514 * " finally"
7515 * finally:
7516 * ... finally block
7517 * " endtry"
7518 * ENDTRY pop trystack entry, may rethrow
7519 */
7520 static char_u *
7521compile_try(char_u *arg, cctx_T *cctx)
7522{
7523 garray_T *instr = &cctx->ctx_instr;
7524 scope_T *try_scope;
7525 scope_T *scope;
7526
7527 // scope that holds the jumps that go to catch/finally/endtry
7528 try_scope = new_scope(cctx, TRY_SCOPE);
7529 if (try_scope == NULL)
7530 return NULL;
7531
Bram Moolenaar69f70502021-01-01 16:10:46 +01007532 if (cctx->ctx_skip != SKIP_YES)
7533 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007534 isn_T *isn;
7535
7536 // "try_catch" is set when the first ":catch" is found or when no catch
7537 // is found and ":finally" is found.
7538 // "try_finally" is set when ":finally" is found
7539 // "try_endtry" is set when ":endtry" is found
Bram Moolenaar69f70502021-01-01 16:10:46 +01007540 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007541 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
7542 return NULL;
7543 isn->isn_arg.try.try_ref = ALLOC_CLEAR_ONE(tryref_T);
7544 if (isn->isn_arg.try.try_ref == NULL)
Bram Moolenaar69f70502021-01-01 16:10:46 +01007545 return NULL;
7546 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007547
7548 // scope for the try block itself
7549 scope = new_scope(cctx, BLOCK_SCOPE);
7550 if (scope == NULL)
7551 return NULL;
7552
7553 return arg;
7554}
7555
7556/*
7557 * compile "catch {expr}"
7558 */
7559 static char_u *
7560compile_catch(char_u *arg, cctx_T *cctx UNUSED)
7561{
7562 scope_T *scope = cctx->ctx_scope;
7563 garray_T *instr = &cctx->ctx_instr;
7564 char_u *p;
7565 isn_T *isn;
7566
7567 // end block scope from :try or :catch
7568 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
7569 compile_endblock(cctx);
7570 scope = cctx->ctx_scope;
7571
7572 // Error if not in a :try scope
7573 if (scope == NULL || scope->se_type != TRY_SCOPE)
7574 {
7575 emsg(_(e_catch));
7576 return NULL;
7577 }
7578
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007579 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007580 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02007581 emsg(_(e_catch_unreachable_after_catch_all));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007582 return NULL;
7583 }
7584
Bram Moolenaar69f70502021-01-01 16:10:46 +01007585 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007586 {
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007587#ifdef FEAT_PROFILE
7588 // the profile-start should be after the jump
7589 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
7590 .isn_type == ISN_PROF_START)
7591 --instr->ga_len;
7592#endif
Bram Moolenaar69f70502021-01-01 16:10:46 +01007593 // Jump from end of previous block to :finally or :endtry
7594 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
7595 JUMP_ALWAYS, cctx) == FAIL)
7596 return NULL;
7597
7598 // End :try or :catch scope: set value in ISN_TRY instruction
7599 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007600 if (isn->isn_arg.try.try_ref->try_catch == 0)
7601 isn->isn_arg.try.try_ref->try_catch = instr->ga_len;
Bram Moolenaar69f70502021-01-01 16:10:46 +01007602 if (scope->se_u.se_try.ts_catch_label != 0)
7603 {
7604 // Previous catch without match jumps here
7605 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
7606 isn->isn_arg.jump.jump_where = instr->ga_len;
7607 }
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007608#ifdef FEAT_PROFILE
7609 if (cctx->ctx_profiling)
7610 {
7611 // a "throw" that jumps here needs to be counted
7612 generate_instr(cctx, ISN_PROF_END);
7613 // the "catch" is also counted
7614 generate_instr(cctx, ISN_PROF_START);
7615 }
7616#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007617 }
7618
7619 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02007620 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007621 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007622 scope->se_u.se_try.ts_caught_all = TRUE;
7623 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007624 }
7625 else
7626 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007627 char_u *end;
7628 char_u *pat;
7629 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02007630 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01007631 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007632
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007633 // Push v:exception, push {expr} and MATCH
7634 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
7635
Bram Moolenaard93a7fc2021-01-04 12:42:13 +01007636 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007637 if (*end != *p)
7638 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02007639 semsg(_(e_separator_mismatch_str), p);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007640 vim_free(tofree);
7641 return FAIL;
7642 }
7643 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01007644 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007645 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02007646 len = (int)(end - tofree);
7647 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007648 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02007649 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01007650 if (pat == NULL)
7651 return FAIL;
7652 if (generate_PUSHS(cctx, pat) == FAIL)
7653 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007654
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007655 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
7656 return NULL;
7657
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007658 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007659 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
7660 return NULL;
7661 }
7662
Bram Moolenaar69f70502021-01-01 16:10:46 +01007663 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007664 return NULL;
7665
7666 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
7667 return NULL;
7668 return p;
7669}
7670
7671 static char_u *
7672compile_finally(char_u *arg, cctx_T *cctx)
7673{
7674 scope_T *scope = cctx->ctx_scope;
7675 garray_T *instr = &cctx->ctx_instr;
7676 isn_T *isn;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007677 int this_instr;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007678
7679 // end block scope from :try or :catch
7680 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
7681 compile_endblock(cctx);
7682 scope = cctx->ctx_scope;
7683
7684 // Error if not in a :try scope
7685 if (scope == NULL || scope->se_type != TRY_SCOPE)
7686 {
7687 emsg(_(e_finally));
7688 return NULL;
7689 }
7690
7691 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007692 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007693 if (isn->isn_arg.try.try_ref->try_finally != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007694 {
7695 emsg(_(e_finally_dup));
7696 return NULL;
7697 }
7698
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007699 this_instr = instr->ga_len;
7700#ifdef FEAT_PROFILE
7701 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
7702 .isn_type == ISN_PROF_START)
7703 // jump to the profile start of the "finally"
7704 --this_instr;
7705#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007706
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007707 // Fill in the "end" label in jumps at the end of the blocks.
7708 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
7709 this_instr, cctx);
7710
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007711 // If there is no :catch then an exception jumps to :finally.
7712 if (isn->isn_arg.try.try_ref->try_catch == 0)
7713 isn->isn_arg.try.try_ref->try_catch = this_instr;
7714 isn->isn_arg.try.try_ref->try_finally = this_instr;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007715 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007716 {
7717 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007718 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007719 isn->isn_arg.jump.jump_where = this_instr;
Bram Moolenaare8593122020-07-18 15:17:02 +02007720 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007721 }
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007722 if (generate_instr(cctx, ISN_FINALLY) == NULL)
7723 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007724
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007725 // TODO: set index in ts_finally_label jumps
7726
7727 return arg;
7728}
7729
7730 static char_u *
7731compile_endtry(char_u *arg, cctx_T *cctx)
7732{
7733 scope_T *scope = cctx->ctx_scope;
7734 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007735 isn_T *try_isn;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007736
7737 // end block scope from :catch or :finally
7738 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
7739 compile_endblock(cctx);
7740 scope = cctx->ctx_scope;
7741
7742 // Error if not in a :try scope
7743 if (scope == NULL || scope->se_type != TRY_SCOPE)
7744 {
7745 if (scope == NULL)
7746 emsg(_(e_no_endtry));
7747 else if (scope->se_type == WHILE_SCOPE)
7748 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01007749 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007750 emsg(_(e_endfor));
7751 else
7752 emsg(_(e_endif));
7753 return NULL;
7754 }
7755
Bram Moolenaarc150c092021-02-13 15:02:46 +01007756 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar69f70502021-01-01 16:10:46 +01007757 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007758 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007759 if (try_isn->isn_arg.try.try_ref->try_catch == 0
7760 && try_isn->isn_arg.try.try_ref->try_finally == 0)
Bram Moolenaar69f70502021-01-01 16:10:46 +01007761 {
7762 emsg(_(e_missing_catch_or_finally));
7763 return NULL;
7764 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007765
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007766#ifdef FEAT_PROFILE
7767 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
7768 .isn_type == ISN_PROF_START)
7769 // move the profile start after "endtry" so that it's not counted when
7770 // the exception is rethrown.
7771 --instr->ga_len;
7772#endif
7773
Bram Moolenaar69f70502021-01-01 16:10:46 +01007774 // Fill in the "end" label in jumps at the end of the blocks, if not
7775 // done by ":finally".
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007776 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
7777 instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007778
Bram Moolenaar69f70502021-01-01 16:10:46 +01007779 if (scope->se_u.se_try.ts_catch_label != 0)
7780 {
7781 // Last catch without match jumps here
Bram Moolenaarc150c092021-02-13 15:02:46 +01007782 isn_T *isn = ((isn_T *)instr->ga_data)
7783 + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar69f70502021-01-01 16:10:46 +01007784 isn->isn_arg.jump.jump_where = instr->ga_len;
7785 }
Bram Moolenaare8593122020-07-18 15:17:02 +02007786 }
7787
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007788 compile_endblock(cctx);
7789
Bram Moolenaar4afa7742021-02-14 16:34:59 +01007790 if (cctx->ctx_skip != SKIP_YES)
7791 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007792 // End :catch or :finally scope: set instruction index in ISN_TRY
7793 // instruction
7794 try_isn->isn_arg.try.try_ref->try_endtry = instr->ga_len;
Bram Moolenaar4afa7742021-02-14 16:34:59 +01007795 if (cctx->ctx_skip != SKIP_YES
7796 && generate_instr(cctx, ISN_ENDTRY) == NULL)
7797 return NULL;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007798#ifdef FEAT_PROFILE
7799 if (cctx->ctx_profiling)
7800 generate_instr(cctx, ISN_PROF_START);
7801#endif
Bram Moolenaar4afa7742021-02-14 16:34:59 +01007802 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007803 return arg;
7804}
7805
7806/*
7807 * compile "throw {expr}"
7808 */
7809 static char_u *
7810compile_throw(char_u *arg, cctx_T *cctx UNUSED)
7811{
7812 char_u *p = skipwhite(arg);
7813
Bram Moolenaara5565e42020-05-09 15:44:01 +02007814 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007815 return NULL;
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +01007816 if (cctx->ctx_skip == SKIP_YES)
7817 return p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007818 if (may_generate_2STRING(-1, cctx) == FAIL)
7819 return NULL;
7820 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
7821 return NULL;
7822
7823 return p;
7824}
7825
7826/*
7827 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007828 * compile "echomsg expr"
7829 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01007830 * compile "execute expr"
7831 */
7832 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007833compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01007834{
7835 char_u *p = arg;
Bram Moolenaare4984292020-12-13 14:19:25 +01007836 char_u *prev = arg;
Bram Moolenaarad39c092020-02-26 18:23:43 +01007837 int count = 0;
7838
7839 for (;;)
7840 {
Bram Moolenaare4984292020-12-13 14:19:25 +01007841 if (ends_excmd2(prev, p))
7842 break;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007843 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01007844 return NULL;
7845 ++count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02007846 prev = p;
Bram Moolenaarad39c092020-02-26 18:23:43 +01007847 p = skipwhite(p);
Bram Moolenaarad39c092020-02-26 18:23:43 +01007848 }
7849
Bram Moolenaare4984292020-12-13 14:19:25 +01007850 if (count > 0)
7851 {
7852 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
7853 generate_ECHO(cctx, cmdidx == CMD_echo, count);
7854 else if (cmdidx == CMD_execute)
7855 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
7856 else if (cmdidx == CMD_echomsg)
7857 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
7858 else
7859 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
7860 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007861 return p;
7862}
7863
7864/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01007865 * If "eap" has a range that is not a constant generate an ISN_RANGE
Bram Moolenaar08597872020-12-10 19:43:40 +01007866 * instruction to compute it and return OK.
7867 * Otherwise return FAIL, the caller must deal with any range.
7868 */
7869 static int
7870compile_variable_range(exarg_T *eap, cctx_T *cctx)
7871{
7872 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
7873 char_u *p = skipdigits(eap->cmd);
7874
7875 if (p == range_end)
7876 return FAIL;
7877 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
7878}
7879
7880/*
Bram Moolenaarc3516f72020-09-08 22:45:35 +02007881 * :put r
7882 * :put ={expr}
7883 */
7884 static char_u *
7885compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
7886{
7887 char_u *line = arg;
7888 linenr_T lnum;
7889 char *errormsg;
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02007890 int above = eap->forceit;
Bram Moolenaarc3516f72020-09-08 22:45:35 +02007891
Bram Moolenaarc3516f72020-09-08 22:45:35 +02007892 eap->regname = *line;
7893
7894 if (eap->regname == '=')
7895 {
7896 char_u *p = line + 1;
7897
7898 if (compile_expr0(&p, cctx) == FAIL)
7899 return NULL;
7900 line = p;
7901 }
7902 else if (eap->regname != NUL)
7903 ++line;
7904
Bram Moolenaar08597872020-12-10 19:43:40 +01007905 if (compile_variable_range(eap, cctx) == OK)
7906 {
7907 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
7908 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02007909 else
Bram Moolenaar08597872020-12-10 19:43:40 +01007910 {
7911 // Either no range or a number.
7912 // "errormsg" will not be set because the range is ADDR_LINES.
7913 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
Bram Moolenaar399ea812020-12-15 21:28:57 +01007914 // cannot happen
Bram Moolenaar08597872020-12-10 19:43:40 +01007915 return NULL;
7916 if (eap->addr_count == 0)
7917 lnum = -1;
7918 else
7919 lnum = eap->line2;
7920 if (above)
7921 --lnum;
7922 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02007923
7924 generate_PUT(cctx, eap->regname, lnum);
7925 return line;
7926}
7927
7928/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007929 * A command that is not compiled, execute with legacy code.
7930 */
7931 static char_u *
7932compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
7933{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02007934 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02007935 int has_expr = FALSE;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02007936 char_u *nextcmd = (char_u *)"";
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007937
Bram Moolenaar9b68c822020-06-18 19:31:08 +02007938 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007939 goto theend;
7940
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02007941 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
Bram Moolenaare9f262b2020-07-05 14:57:51 +02007942 {
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02007943 long argt = eap->argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02007944 int usefilter = FALSE;
7945
7946 has_expr = argt & (EX_XFILE | EX_EXPAND);
7947
7948 // If the command can be followed by a bar, find the bar and truncate
7949 // it, so that the following command can be compiled.
7950 // The '|' is overwritten with a NUL, it is put back below.
7951 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
7952 && *eap->arg == '!')
7953 // :w !filter or :r !filter or :r! filter
7954 usefilter = TRUE;
7955 if ((argt & EX_TRLBAR) && !usefilter)
7956 {
Bram Moolenaarb8a92962020-08-20 18:02:47 +02007957 eap->argt = argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02007958 separate_nextcmd(eap);
7959 if (eap->nextcmd != NULL)
7960 nextcmd = eap->nextcmd;
7961 }
Bram Moolenaara11919f2021-01-02 19:44:56 +01007962 else if (eap->cmdidx == CMD_wincmd)
7963 {
7964 p = eap->arg;
7965 if (*p != NUL)
7966 ++p;
7967 if (*p == 'g' || *p == Ctrl_G)
7968 ++p;
7969 p = skipwhite(p);
7970 if (*p == '|')
7971 {
7972 *p = NUL;
7973 nextcmd = p + 1;
7974 }
7975 }
Bram Moolenaare9f262b2020-07-05 14:57:51 +02007976 }
7977
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02007978 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
7979 {
7980 // expand filename in "syntax include [@group] filename"
7981 has_expr = TRUE;
7982 eap->arg = skipwhite(eap->arg + 7);
7983 if (*eap->arg == '@')
7984 eap->arg = skiptowhite(eap->arg);
7985 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007986
Bram Moolenaar56ce9ea2020-12-25 18:35:29 +01007987 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
7988 && STRLEN(eap->arg) > 4)
7989 {
7990 int delim = *eap->arg;
7991
Bram Moolenaard93a7fc2021-01-04 12:42:13 +01007992 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
Bram Moolenaar56ce9ea2020-12-25 18:35:29 +01007993 if (*p == delim)
7994 {
7995 eap->arg = p + 1;
7996 has_expr = TRUE;
7997 }
7998 }
7999
Bram Moolenaarecac5912021-01-05 19:23:28 +01008000 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
8001 {
8002 // TODO: should only expand when appropriate for the command
8003 eap->arg = skiptowhite(eap->arg);
8004 has_expr = TRUE;
8005 }
8006
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008007 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008008 {
8009 int count = 0;
8010 char_u *start = skipwhite(line);
8011
8012 // :cmd xxx`=expr1`yyy`=expr2`zzz
8013 // PUSHS ":cmd xxx"
8014 // eval expr1
8015 // PUSHS "yyy"
8016 // eval expr2
8017 // PUSHS "zzz"
8018 // EXECCONCAT 5
8019 for (;;)
8020 {
8021 if (p > start)
8022 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02008023 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008024 ++count;
8025 }
8026 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02008027 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008028 return NULL;
8029 may_generate_2STRING(-1, cctx);
8030 ++count;
8031 p = skipwhite(p);
8032 if (*p != '`')
8033 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008034 emsg(_(e_missing_backtick));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008035 return NULL;
8036 }
8037 start = p + 1;
8038
8039 p = (char_u *)strstr((char *)start, "`=");
8040 if (p == NULL)
8041 {
8042 if (*skipwhite(start) != NUL)
8043 {
8044 generate_PUSHS(cctx, vim_strsave(start));
8045 ++count;
8046 }
8047 break;
8048 }
8049 }
8050 generate_EXECCONCAT(cctx, count);
8051 }
8052 else
8053 generate_EXEC(cctx, line);
8054
8055theend:
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008056 if (*nextcmd != NUL)
8057 {
8058 // the parser expects a pointer to the bar, put it back
8059 --nextcmd;
8060 *nextcmd = '|';
8061 }
8062
8063 return nextcmd;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008064}
8065
8066/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02008067 * Add a function to the list of :def functions.
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008068 * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
Bram Moolenaar09689a02020-05-09 22:50:08 +02008069 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02008070 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02008071add_def_function(ufunc_T *ufunc)
8072{
8073 dfunc_T *dfunc;
8074
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008075 if (def_functions.ga_len == 0)
8076 {
8077 // The first position is not used, so that a zero uf_dfunc_idx means it
8078 // wasn't set.
8079 if (ga_grow(&def_functions, 1) == FAIL)
8080 return FAIL;
8081 ++def_functions.ga_len;
8082 }
8083
Bram Moolenaar09689a02020-05-09 22:50:08 +02008084 // Add the function to "def_functions".
8085 if (ga_grow(&def_functions, 1) == FAIL)
8086 return FAIL;
8087 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
8088 CLEAR_POINTER(dfunc);
8089 dfunc->df_idx = def_functions.ga_len;
8090 ufunc->uf_dfunc_idx = dfunc->df_idx;
8091 dfunc->df_ufunc = ufunc;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01008092 dfunc->df_name = vim_strsave(ufunc->uf_name);
8093 ++dfunc->df_refcount;
Bram Moolenaar09689a02020-05-09 22:50:08 +02008094 ++def_functions.ga_len;
8095 return OK;
8096}
8097
8098/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008099 * After ex_function() has collected all the function lines: parse and compile
8100 * the lines into instructions.
8101 * Adds the function to "def_functions".
Bram Moolenaar9e68c322020-12-25 12:38:04 +01008102 * When "check_return_type" is set then set ufunc->uf_ret_type to the type of
8103 * the return statement (used for lambda). When uf_ret_type is already set
8104 * then check that it matches.
Bram Moolenaarb2049902021-01-24 12:53:53 +01008105 * When "profiling" is true add ISN_PROF_START instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008106 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02008107 * This can be used recursively through compile_lambda(), which may reallocate
8108 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02008109 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008110 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02008111 int
Bram Moolenaarb2049902021-01-24 12:53:53 +01008112compile_def_function(
8113 ufunc_T *ufunc,
8114 int check_return_type,
Bram Moolenaarf002a412021-01-24 13:34:18 +01008115 int profiling UNUSED,
Bram Moolenaarb2049902021-01-24 12:53:53 +01008116 cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008117{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008118 char_u *line = NULL;
8119 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008120 char *errormsg = NULL; // error message
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008121 cctx_T cctx;
8122 garray_T *instr;
Bram Moolenaard66960b2020-10-30 20:46:26 +01008123 int did_emsg_before = did_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008124 int ret = FAIL;
8125 sctx_T save_current_sctx = current_sctx;
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008126 int save_estack_compiling = estack_compiling;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008127 int do_estack_push;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008128 int new_def_function = FALSE;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008129#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008130 int prof_lnum = -1;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008131#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008132
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008133 // When using a function that was compiled before: Free old instructions.
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008134 // The index is reused. Otherwise add a new entry in "def_functions".
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008135 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008136 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02008137 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8138 + ufunc->uf_dfunc_idx;
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008139 delete_def_function_contents(dfunc, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008140 }
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008141 else
8142 {
8143 if (add_def_function(ufunc) == FAIL)
8144 return FAIL;
8145 new_def_function = TRUE;
8146 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008147
Bram Moolenaar985116a2020-07-12 17:31:09 +02008148 ufunc->uf_def_status = UF_COMPILING;
8149
Bram Moolenaara80faa82020-04-12 19:37:17 +02008150 CLEAR_FIELD(cctx);
Bram Moolenaarb2049902021-01-24 12:53:53 +01008151
Bram Moolenaarf002a412021-01-24 13:34:18 +01008152#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008153 cctx.ctx_profiling = profiling;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008154#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008155 cctx.ctx_ufunc = ufunc;
8156 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008157 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008158 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
8159 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
8160 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
8161 cctx.ctx_type_list = &ufunc->uf_type_list;
8162 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
8163 instr = &cctx.ctx_instr;
8164
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008165 // Set the context to the function, it may be compiled when called from
8166 // another script. Set the script version to the most modern one.
8167 // The line number will be set in next_line_from_context().
8168 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008169 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
8170
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008171 // Make sure error messages are OK.
8172 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
8173 if (do_estack_push)
8174 estack_push_ufunc(ufunc, 1);
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008175 estack_compiling = TRUE;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008176
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008177 if (ufunc->uf_def_args.ga_len > 0)
8178 {
8179 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008180 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008181 int i;
8182 char_u *arg;
8183 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008184 int did_set_arg_type = FALSE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008185
8186 // Produce instructions for the default values of optional arguments.
8187 // Store the instruction index in uf_def_arg_idx[] so that we know
8188 // where to start when the function is called, depending on the number
8189 // of arguments.
8190 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
8191 if (ufunc->uf_def_arg_idx == NULL)
8192 goto erret;
8193 for (i = 0; i < count; ++i)
8194 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008195 garray_T *stack = &cctx.ctx_type_stack;
8196 type_T *val_type;
8197 int arg_idx = first_def_arg + i;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008198 where_T where;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008199
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008200 ufunc->uf_def_arg_idx[i] = instr->ga_len;
8201 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02008202 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008203 goto erret;
8204
8205 // If no type specified use the type of the default value.
8206 // Otherwise check that the default value type matches the
8207 // specified type.
8208 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008209 where.wt_index = arg_idx + 1;
8210 where.wt_variable = FALSE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008211 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008212 {
8213 did_set_arg_type = TRUE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008214 ufunc->uf_arg_types[arg_idx] = val_type;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008215 }
Bram Moolenaar8b565c22020-08-30 23:24:20 +02008216 else if (check_type(ufunc->uf_arg_types[arg_idx], val_type,
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008217 TRUE, where) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008218 goto erret;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008219
8220 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008221 goto erret;
8222 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008223 ufunc->uf_def_arg_idx[count] = instr->ga_len;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008224
8225 if (did_set_arg_type)
8226 set_function_type(ufunc);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008227 }
8228
8229 /*
8230 * Loop over all the lines of the function and generate instructions.
8231 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008232 for (;;)
8233 {
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02008234 exarg_T ea;
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02008235 int starts_with_colon = FALSE;
8236 char_u *cmd;
Bram Moolenaar02194d22020-10-24 23:08:38 +02008237 cmdmod_T local_cmdmod;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01008238
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008239 // Bail out on the first error to avoid a flood of errors and report
8240 // the right line number when inside try/catch.
Bram Moolenaard66960b2020-10-30 20:46:26 +01008241 if (did_emsg_before != did_emsg)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008242 goto erret;
8243
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008244 if (line != NULL && *line == '|')
8245 // the line continues after a '|'
8246 ++line;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02008247 else if (line != NULL && *skipwhite(line) != NUL
Bram Moolenaar7a092242020-04-16 22:10:49 +02008248 && !(*line == '#' && (line == cctx.ctx_line_start
8249 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008250 {
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02008251 semsg(_(e_trailing_arg), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008252 goto erret;
8253 }
8254 else
8255 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02008256 line = next_line_from_context(&cctx, FALSE);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02008257 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarb2049902021-01-24 12:53:53 +01008258 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008259 // beyond the last line
Bram Moolenaarf002a412021-01-24 13:34:18 +01008260#ifdef FEAT_PROFILE
Bram Moolenaarced68a02021-01-24 17:53:47 +01008261 if (cctx.ctx_skip != SKIP_YES)
8262 may_generate_prof_end(&cctx, prof_lnum);
Bram Moolenaarf002a412021-01-24 13:34:18 +01008263#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008264 break;
Bram Moolenaarb2049902021-01-24 12:53:53 +01008265 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008266 }
8267
Bram Moolenaara80faa82020-04-12 19:37:17 +02008268 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008269 ea.cmdlinep = &line;
8270 ea.cmd = skipwhite(line);
8271
Bram Moolenaarb2049902021-01-24 12:53:53 +01008272 if (*ea.cmd == '#')
8273 {
8274 // "#" starts a comment
8275 line = (char_u *)"";
8276 continue;
8277 }
8278
Bram Moolenaarf002a412021-01-24 13:34:18 +01008279#ifdef FEAT_PROFILE
Bram Moolenaarced68a02021-01-24 17:53:47 +01008280 if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum &&
8281 cctx.ctx_skip != SKIP_YES)
Bram Moolenaarb2049902021-01-24 12:53:53 +01008282 {
8283 may_generate_prof_end(&cctx, prof_lnum);
8284
8285 prof_lnum = cctx.ctx_lnum;
8286 generate_instr(&cctx, ISN_PROF_START);
8287 }
Bram Moolenaarf002a412021-01-24 13:34:18 +01008288#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01008289
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008290 // Some things can be recognized by the first character.
8291 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008292 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008293 case '}':
8294 {
8295 // "}" ends a block scope
8296 scopetype_T stype = cctx.ctx_scope == NULL
8297 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008298
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008299 if (stype == BLOCK_SCOPE)
8300 {
8301 compile_endblock(&cctx);
8302 line = ea.cmd;
8303 }
8304 else
8305 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008306 emsg(_(e_using_rcurly_outside_if_block_scope));
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008307 goto erret;
8308 }
8309 if (line != NULL)
8310 line = skipwhite(ea.cmd + 1);
8311 continue;
8312 }
8313
8314 case '{':
8315 // "{" starts a block scope
8316 // "{'a': 1}->func() is something else
8317 if (ends_excmd(*skipwhite(ea.cmd + 1)))
8318 {
8319 line = compile_block(ea.cmd, &cctx);
8320 continue;
8321 }
8322 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008323 }
8324
8325 /*
8326 * COMMAND MODIFIERS
8327 */
Bram Moolenaar02194d22020-10-24 23:08:38 +02008328 cctx.ctx_has_cmdmod = FALSE;
Bram Moolenaare1004402020-10-24 20:49:43 +02008329 if (parse_command_modifiers(&ea, &errormsg, &local_cmdmod, FALSE)
8330 == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008331 {
8332 if (errormsg != NULL)
8333 goto erret;
8334 // empty line or comment
8335 line = (char_u *)"";
8336 continue;
8337 }
Bram Moolenaare1004402020-10-24 20:49:43 +02008338 generate_cmdmods(&cctx, &local_cmdmod);
8339 undo_cmdmod(&local_cmdmod);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008340
Bram Moolenaare88c8e82020-11-01 17:03:37 +01008341 // Check if there was a colon after the last command modifier or before
8342 // the current position.
8343 for (p = ea.cmd; p >= line; --p)
8344 {
8345 if (*p == ':')
8346 starts_with_colon = TRUE;
8347 if (p < ea.cmd && !VIM_ISWHITE(*p))
8348 break;
8349 }
8350
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008351 // Skip ":call" to get to the function name.
Bram Moolenaar575f24b2020-08-12 14:21:11 +02008352 p = ea.cmd;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008353 if (checkforcmd(&ea.cmd, "call", 3))
Bram Moolenaar575f24b2020-08-12 14:21:11 +02008354 {
8355 if (*ea.cmd == '(')
8356 // not for "call()"
8357 ea.cmd = p;
8358 else
8359 ea.cmd = skipwhite(ea.cmd);
8360 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008361
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008362 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008363 {
Bram Moolenaar17126b12021-01-07 22:03:02 +01008364 int assign;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008365
Bram Moolenaar17126b12021-01-07 22:03:02 +01008366 // Check for assignment after command modifiers.
8367 assign = may_compile_assignment(&ea, &line, &cctx);
8368 if (assign == OK)
8369 goto nextline;
8370 if (assign == FAIL)
8371 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008372 }
8373
8374 /*
8375 * COMMAND after range
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008376 * 'text'->func() should not be confused with 'a mark
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008377 */
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008378 cmd = ea.cmd;
Bram Moolenaar7c5ad342020-08-12 15:48:55 +02008379 if (*cmd != '\'' || starts_with_colon)
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008380 {
Bram Moolenaar3bd8de42020-09-14 16:37:34 +02008381 ea.cmd = skip_range(ea.cmd, TRUE, NULL);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008382 if (ea.cmd > cmd)
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008383 {
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008384 if (!starts_with_colon)
8385 {
Bram Moolenaar6e2c2c52020-12-25 19:25:45 +01008386 semsg(_(e_colon_required_before_range_str), cmd);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008387 goto erret;
8388 }
Bram Moolenaarada1d872021-02-20 08:16:51 +01008389 ea.addr_count = 1;
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008390 if (ends_excmd2(line, ea.cmd))
8391 {
8392 // A range without a command: jump to the line.
8393 // TODO: compile to a more efficient command, possibly
8394 // calling parse_cmd_address().
8395 ea.cmdidx = CMD_SIZE;
8396 line = compile_exec(line, &ea, &cctx);
8397 goto nextline;
8398 }
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008399 }
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008400 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008401 p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
Bram Moolenaare0890d62021-02-17 14:52:14 +01008402 : (int (*)(char_u *, size_t, cctx_T *))variable_exists,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01008403 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008404
Bram Moolenaard1510ee2021-01-04 16:15:58 +01008405 if (p == NULL)
8406 {
8407 if (cctx.ctx_skip != SKIP_YES)
8408 emsg(_(e_ambiguous_use_of_user_defined_command));
8409 goto erret;
8410 }
8411
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008412 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
8413 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02008414 if (cctx.ctx_skip == SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01008415 {
8416 line += STRLEN(line);
Bram Moolenaarf665e972020-12-05 19:17:16 +01008417 goto nextline;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01008418 }
8419
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008420 // Expression or function call.
Bram Moolenaar007f9d62020-07-06 23:04:49 +02008421 if (ea.cmdidx != CMD_eval)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008422 {
Bram Moolenaar52c124d2020-12-20 21:43:35 +01008423 // CMD_var cannot happen, compile_assignment() above would be
8424 // used. Most likely an assignment to a non-existing variable.
8425 semsg(_(e_command_not_recognized_str), ea.cmd);
Bram Moolenaar007f9d62020-07-06 23:04:49 +02008426 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008427 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008428 }
8429
Bram Moolenaar3988f642020-08-27 22:43:03 +02008430 if (cctx.ctx_had_return
Bram Moolenaara259d8d2020-01-31 20:10:50 +01008431 && ea.cmdidx != CMD_elseif
8432 && ea.cmdidx != CMD_else
Bram Moolenaarefd88552020-06-18 20:50:10 +02008433 && ea.cmdidx != CMD_endif
8434 && ea.cmdidx != CMD_endfor
8435 && ea.cmdidx != CMD_endwhile
8436 && ea.cmdidx != CMD_catch
8437 && ea.cmdidx != CMD_finally
8438 && ea.cmdidx != CMD_endtry)
8439 {
Bram Moolenaar3988f642020-08-27 22:43:03 +02008440 emsg(_(e_unreachable_code_after_return));
8441 goto erret;
Bram Moolenaarefd88552020-06-18 20:50:10 +02008442 }
8443
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008444 p = skipwhite(p);
8445 if (ea.cmdidx != CMD_SIZE
8446 && ea.cmdidx != CMD_write && ea.cmdidx != CMD_read)
8447 {
Bram Moolenaar9b123d82020-09-14 22:39:11 +02008448 if (ea.cmdidx >= 0)
8449 ea.argt = excmd_get_argt(ea.cmdidx);
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008450 if ((ea.argt & EX_BANG) && *p == '!')
8451 {
8452 ea.forceit = TRUE;
8453 p = skipwhite(p + 1);
8454 }
8455 }
8456
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008457 switch (ea.cmdidx)
8458 {
8459 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02008460 ea.arg = p;
8461 line = compile_nested_function(&ea, &cctx);
8462 break;
8463
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008464 case CMD_function:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008465 // TODO: should we allow this, e.g. to declare a global
8466 // function?
8467 emsg(_(e_cannot_use_function_inside_def));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008468 goto erret;
8469
8470 case CMD_return:
Bram Moolenaar9e68c322020-12-25 12:38:04 +01008471 line = compile_return(p, check_return_type, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008472 cctx.ctx_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008473 break;
8474
8475 case CMD_let:
Bram Moolenaarc58f5452020-10-21 20:58:52 +02008476 emsg(_(e_cannot_use_let_in_vim9_script));
8477 break;
Bram Moolenaar30fd8202020-09-26 15:09:30 +02008478 case CMD_var:
8479 case CMD_final:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008480 case CMD_const:
8481 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02008482 if (line == p)
8483 line = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008484 break;
8485
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02008486 case CMD_unlet:
8487 case CMD_unlockvar:
8488 case CMD_lockvar:
8489 line = compile_unletlock(p, &ea, &cctx);
8490 break;
8491
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008492 case CMD_import:
8493 line = compile_import(p, &cctx);
8494 break;
8495
8496 case CMD_if:
8497 line = compile_if(p, &cctx);
8498 break;
8499 case CMD_elseif:
8500 line = compile_elseif(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008501 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008502 break;
8503 case CMD_else:
8504 line = compile_else(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008505 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008506 break;
8507 case CMD_endif:
8508 line = compile_endif(p, &cctx);
8509 break;
8510
8511 case CMD_while:
8512 line = compile_while(p, &cctx);
8513 break;
8514 case CMD_endwhile:
8515 line = compile_endwhile(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008516 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008517 break;
8518
8519 case CMD_for:
8520 line = compile_for(p, &cctx);
8521 break;
8522 case CMD_endfor:
8523 line = compile_endfor(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008524 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008525 break;
8526 case CMD_continue:
8527 line = compile_continue(p, &cctx);
8528 break;
8529 case CMD_break:
8530 line = compile_break(p, &cctx);
8531 break;
8532
8533 case CMD_try:
8534 line = compile_try(p, &cctx);
8535 break;
8536 case CMD_catch:
8537 line = compile_catch(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008538 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008539 break;
8540 case CMD_finally:
8541 line = compile_finally(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008542 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008543 break;
8544 case CMD_endtry:
8545 line = compile_endtry(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02008546 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008547 break;
8548 case CMD_throw:
8549 line = compile_throw(p, &cctx);
8550 break;
8551
Bram Moolenaar007f9d62020-07-06 23:04:49 +02008552 case CMD_eval:
8553 if (compile_expr0(&p, &cctx) == FAIL)
8554 goto erret;
8555
Bram Moolenaar3988f642020-08-27 22:43:03 +02008556 // drop the result
Bram Moolenaar007f9d62020-07-06 23:04:49 +02008557 generate_instr_drop(&cctx, ISN_DROP, 1);
8558
8559 line = skipwhite(p);
8560 break;
8561
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008562 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008563 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01008564 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02008565 case CMD_echomsg:
8566 case CMD_echoerr:
8567 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01008568 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008569
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008570 case CMD_put:
8571 ea.cmd = cmd;
8572 line = compile_put(p, &ea, &cctx);
8573 break;
8574
Bram Moolenaar3988f642020-08-27 22:43:03 +02008575 // TODO: any other commands with an expression argument?
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008576
Bram Moolenaarae616492020-07-28 20:07:27 +02008577 case CMD_append:
8578 case CMD_change:
8579 case CMD_insert:
Bram Moolenaar10b94212021-02-19 21:42:57 +01008580 case CMD_k:
Bram Moolenaarf5a48012020-08-01 17:00:03 +02008581 case CMD_t:
Bram Moolenaarae616492020-07-28 20:07:27 +02008582 case CMD_xit:
8583 not_in_vim9(&ea);
8584 goto erret;
8585
Bram Moolenaar002262f2020-07-08 17:47:57 +02008586 case CMD_SIZE:
Bram Moolenaar3988f642020-08-27 22:43:03 +02008587 if (cctx.ctx_skip != SKIP_YES)
8588 {
8589 semsg(_(e_invalid_command_str), ea.cmd);
8590 goto erret;
8591 }
8592 // We don't check for a next command here.
8593 line = (char_u *)"";
8594 break;
Bram Moolenaar002262f2020-07-08 17:47:57 +02008595
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008596 default:
Bram Moolenaar5163fcc2020-08-27 23:37:09 +02008597 if (cctx.ctx_skip == SKIP_YES)
8598 {
8599 // We don't check for a next command here.
8600 line = (char_u *)"";
8601 }
8602 else
8603 {
8604 // Not recognized, execute with do_cmdline_cmd().
8605 ea.arg = p;
8606 line = compile_exec(line, &ea, &cctx);
8607 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008608 break;
8609 }
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008610nextline:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008611 if (line == NULL)
8612 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02008613 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008614
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02008615 // Undo any command modifiers.
Bram Moolenaar02194d22020-10-24 23:08:38 +02008616 generate_undo_cmdmods(&cctx);
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02008617
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008618 if (cctx.ctx_type_stack.ga_len < 0)
8619 {
8620 iemsg("Type stack underflow");
8621 goto erret;
8622 }
8623 }
8624
8625 if (cctx.ctx_scope != NULL)
8626 {
8627 if (cctx.ctx_scope->se_type == IF_SCOPE)
8628 emsg(_(e_endif));
8629 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
8630 emsg(_(e_endwhile));
8631 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
8632 emsg(_(e_endfor));
8633 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008634 emsg(_(e_missing_rcurly));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008635 goto erret;
8636 }
8637
Bram Moolenaarefd88552020-06-18 20:50:10 +02008638 if (!cctx.ctx_had_return)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008639 {
8640 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
8641 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008642 emsg(_(e_missing_return_statement));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008643 goto erret;
8644 }
8645
8646 // Return zero if there is no return at the end.
Bram Moolenaar299f3032021-01-08 20:53:09 +01008647 generate_instr(&cctx, ISN_RETURN_ZERO);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008648 }
8649
Bram Moolenaar05afcee2020-03-31 23:32:31 +02008650 {
8651 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8652 + ufunc->uf_dfunc_idx;
8653 dfunc->df_deleted = FALSE;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01008654 dfunc->df_script_seq = current_sctx.sc_seq;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008655#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008656 if (cctx.ctx_profiling)
8657 {
8658 dfunc->df_instr_prof = instr->ga_data;
8659 dfunc->df_instr_prof_count = instr->ga_len;
8660 }
8661 else
Bram Moolenaarf002a412021-01-24 13:34:18 +01008662#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01008663 {
8664 dfunc->df_instr = instr->ga_data;
8665 dfunc->df_instr_count = instr->ga_len;
8666 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02008667 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02008668 dfunc->df_has_closure = cctx.ctx_has_closure;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008669 if (cctx.ctx_outer_used)
8670 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008671 ufunc->uf_def_status = UF_COMPILED;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02008672 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008673
8674 ret = OK;
8675
8676erret:
8677 if (ret == FAIL)
8678 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01008679 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02008680 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8681 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01008682
8683 for (idx = 0; idx < instr->ga_len; ++idx)
8684 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008685 ga_clear(instr);
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01008686 VIM_CLEAR(dfunc->df_name);
Bram Moolenaar20431c92020-03-20 18:39:46 +01008687
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008688 // If using the last entry in the table and it was added above, we
8689 // might as well remove it.
8690 if (!dfunc->df_deleted && new_def_function
Bram Moolenaar45a15082020-05-25 00:28:33 +02008691 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008692 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01008693 --def_functions.ga_len;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008694 ufunc->uf_dfunc_idx = 0;
8695 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008696 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01008697
Bram Moolenaar3cca2992020-04-02 22:57:36 +02008698 while (cctx.ctx_scope != NULL)
8699 drop_scope(&cctx);
8700
Bram Moolenaar20431c92020-03-20 18:39:46 +01008701 // Don't execute this function body.
8702 ga_clear_strings(&ufunc->uf_lines);
8703
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008704 if (errormsg != NULL)
8705 emsg(errormsg);
Bram Moolenaard66960b2020-10-30 20:46:26 +01008706 else if (did_emsg == did_emsg_before)
Bram Moolenaare13bdec2020-10-16 23:16:47 +02008707 emsg(_(e_compiling_def_function_failed));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008708 }
8709
8710 current_sctx = save_current_sctx;
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008711 estack_compiling = save_estack_compiling;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008712 if (do_estack_push)
8713 estack_pop();
8714
Bram Moolenaar20431c92020-03-20 18:39:46 +01008715 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02008716 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008717 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02008718 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008719}
8720
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02008721 void
8722set_function_type(ufunc_T *ufunc)
8723{
8724 int varargs = ufunc->uf_va_name != NULL;
8725 int argcount = ufunc->uf_args.ga_len;
8726
8727 // Create a type for the function, with the return type and any
8728 // argument types.
8729 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
8730 // The type is included in "tt_args".
8731 if (argcount > 0 || varargs)
8732 {
Bram Moolenaar18062fc2021-03-05 21:35:47 +01008733 if (ufunc->uf_type_list.ga_itemsize == 0)
8734 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02008735 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
8736 argcount, &ufunc->uf_type_list);
8737 // Add argument types to the function type.
8738 if (func_type_add_arg_types(ufunc->uf_func_type,
8739 argcount + varargs,
8740 &ufunc->uf_type_list) == FAIL)
8741 return;
8742 ufunc->uf_func_type->tt_argcount = argcount + varargs;
8743 ufunc->uf_func_type->tt_min_argcount =
8744 argcount - ufunc->uf_def_args.ga_len;
8745 if (ufunc->uf_arg_types == NULL)
8746 {
8747 int i;
8748
8749 // lambda does not have argument types.
8750 for (i = 0; i < argcount; ++i)
8751 ufunc->uf_func_type->tt_args[i] = &t_any;
8752 }
8753 else
8754 mch_memmove(ufunc->uf_func_type->tt_args,
8755 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
8756 if (varargs)
8757 {
8758 ufunc->uf_func_type->tt_args[argcount] =
8759 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
8760 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
8761 }
8762 }
8763 else
8764 // No arguments, can use a predefined type.
8765 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
8766 argcount, &ufunc->uf_type_list);
8767}
8768
8769
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008770/*
8771 * Delete an instruction, free what it contains.
8772 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01008773 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008774delete_instr(isn_T *isn)
8775{
8776 switch (isn->isn_type)
8777 {
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01008778 case ISN_DEF:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008779 case ISN_EXEC:
Bram Moolenaar03290b82020-12-19 16:30:44 +01008780 case ISN_LOADAUTO:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01008781 case ISN_LOADB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008782 case ISN_LOADENV:
8783 case ISN_LOADG:
8784 case ISN_LOADOPT:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01008785 case ISN_LOADT:
8786 case ISN_LOADW:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008787 case ISN_PUSHEXC:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01008788 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008789 case ISN_PUSHS:
Bram Moolenaar08597872020-12-10 19:43:40 +01008790 case ISN_RANGE:
Bram Moolenaar03290b82020-12-19 16:30:44 +01008791 case ISN_STOREAUTO:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01008792 case ISN_STOREB:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01008793 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008794 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02008795 case ISN_STORET:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01008796 case ISN_STOREW:
8797 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008798 vim_free(isn->isn_arg.string);
8799 break;
8800
8801 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01008802 case ISN_STORES:
8803 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008804 break;
8805
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02008806 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02008807 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02008808 vim_free(isn->isn_arg.unlet.ul_name);
8809 break;
8810
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008811 case ISN_STOREOPT:
8812 vim_free(isn->isn_arg.storeopt.so_name);
8813 break;
8814
8815 case ISN_PUSHBLOB: // push blob isn_arg.blob
8816 blob_unref(isn->isn_arg.blob);
8817 break;
8818
Bram Moolenaar42a480b2020-02-29 23:23:47 +01008819 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01008820#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01008821 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01008822#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01008823 break;
8824
8825 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01008826#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01008827 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01008828#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01008829 break;
8830
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008831 case ISN_UCALL:
8832 vim_free(isn->isn_arg.ufunc.cuf_name);
8833 break;
8834
Bram Moolenaar221fcc72020-05-05 19:46:20 +02008835 case ISN_FUNCREF:
8836 {
8837 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8838 + isn->isn_arg.funcref.fr_func;
Bram Moolenaar077a4232020-12-22 18:33:27 +01008839 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaara05e5242020-09-19 18:19:19 +02008840
Bram Moolenaar077a4232020-12-22 18:33:27 +01008841 if (ufunc != NULL && func_name_refcount(ufunc->uf_name))
8842 func_ptr_unref(ufunc);
Bram Moolenaara05e5242020-09-19 18:19:19 +02008843 }
8844 break;
8845
8846 case ISN_DCALL:
8847 {
8848 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8849 + isn->isn_arg.dfunc.cdf_idx;
8850
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02008851 if (dfunc->df_ufunc != NULL
8852 && func_name_refcount(dfunc->df_ufunc->uf_name))
Bram Moolenaara05e5242020-09-19 18:19:19 +02008853 func_ptr_unref(dfunc->df_ufunc);
Bram Moolenaar221fcc72020-05-05 19:46:20 +02008854 }
8855 break;
8856
Bram Moolenaar38ddf332020-07-31 22:05:04 +02008857 case ISN_NEWFUNC:
Bram Moolenaarce658352020-07-31 23:47:12 +02008858 {
8859 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
8860 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
8861
8862 if (ufunc != NULL)
8863 {
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01008864 unlink_def_function(ufunc);
Bram Moolenaarce658352020-07-31 23:47:12 +02008865 func_ptr_unref(ufunc);
8866 }
8867
8868 vim_free(lambda);
8869 vim_free(isn->isn_arg.newfunc.nf_global);
8870 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02008871 break;
8872
Bram Moolenaar5e654232020-09-16 15:22:00 +02008873 case ISN_CHECKTYPE:
Bram Moolenaaraa210a32021-01-02 15:41:03 +01008874 case ISN_SETTYPE:
Bram Moolenaar5e654232020-09-16 15:22:00 +02008875 free_type(isn->isn_arg.type.ct_type);
8876 break;
8877
Bram Moolenaar02194d22020-10-24 23:08:38 +02008878 case ISN_CMDMOD:
8879 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
8880 ->cmod_filter_regmatch.regprog);
8881 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
8882 break;
8883
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01008884 case ISN_LOADSCRIPT:
8885 case ISN_STORESCRIPT:
8886 vim_free(isn->isn_arg.script.scriptref);
8887 break;
8888
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008889 case ISN_TRY:
8890 vim_free(isn->isn_arg.try.try_ref);
8891 break;
8892
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008893 case ISN_2BOOL:
8894 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02008895 case ISN_2STRING_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008896 case ISN_ADDBLOB:
8897 case ISN_ADDLIST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008898 case ISN_ANYINDEX:
8899 case ISN_ANYSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008900 case ISN_BCALL:
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02008901 case ISN_BLOBAPPEND:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008902 case ISN_CATCH:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008903 case ISN_CHECKLEN:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008904 case ISN_CHECKNR:
Bram Moolenaar02194d22020-10-24 23:08:38 +02008905 case ISN_CMDMOD_REV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008906 case ISN_COMPAREANY:
8907 case ISN_COMPAREBLOB:
8908 case ISN_COMPAREBOOL:
8909 case ISN_COMPAREDICT:
8910 case ISN_COMPAREFLOAT:
8911 case ISN_COMPAREFUNC:
8912 case ISN_COMPARELIST:
8913 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008914 case ISN_COMPARESPECIAL:
8915 case ISN_COMPARESTRING:
8916 case ISN_CONCAT:
Bram Moolenaar2bb26582020-10-03 22:52:39 +02008917 case ISN_COND2BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008918 case ISN_DROP:
8919 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02008920 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008921 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008922 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008923 case ISN_EXECCONCAT:
8924 case ISN_EXECUTE:
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008925 case ISN_FINALLY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008926 case ISN_FOR:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008927 case ISN_GETITEM:
8928 case ISN_JUMP:
Bram Moolenaar1dcae592020-10-19 19:02:42 +02008929 case ISN_LISTAPPEND:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02008930 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02008931 case ISN_LISTSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008932 case ISN_LOAD:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02008933 case ISN_LOADBDICT:
8934 case ISN_LOADGDICT:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008935 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008936 case ISN_LOADREG:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02008937 case ISN_LOADTDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008938 case ISN_LOADV:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02008939 case ISN_LOADWDICT:
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008940 case ISN_LOCKCONST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008941 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008942 case ISN_NEGATENR:
8943 case ISN_NEWDICT:
8944 case ISN_NEWLIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008945 case ISN_OPANY:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008946 case ISN_OPFLOAT:
8947 case ISN_OPNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008948 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02008949 case ISN_PCALL_END:
Bram Moolenaarb2049902021-01-24 12:53:53 +01008950 case ISN_PROF_END:
8951 case ISN_PROF_START:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008952 case ISN_PUSHBOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008953 case ISN_PUSHF:
8954 case ISN_PUSHNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008955 case ISN_PUSHSPEC:
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008956 case ISN_PUT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008957 case ISN_RETURN:
Bram Moolenaar299f3032021-01-08 20:53:09 +01008958 case ISN_RETURN_ZERO:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008959 case ISN_SHUFFLE:
8960 case ISN_SLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008961 case ISN_STORE:
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01008962 case ISN_STOREINDEX:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008963 case ISN_STORENR:
8964 case ISN_STOREOUTER:
8965 case ISN_STOREREG:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02008966 case ISN_STOREV:
8967 case ISN_STRINDEX:
8968 case ISN_STRSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008969 case ISN_THROW:
Bram Moolenaarc150c092021-02-13 15:02:46 +01008970 case ISN_TRYCONT:
Bram Moolenaar752fc692021-01-04 21:57:11 +01008971 case ISN_UNLETINDEX:
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01008972 case ISN_UNLETRANGE:
Bram Moolenaar792f7862020-11-23 08:31:18 +01008973 case ISN_UNPACK:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008974 // nothing allocated
8975 break;
8976 }
8977}
8978
8979/*
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01008980 * Free all instructions for "dfunc" except df_name.
Bram Moolenaar20431c92020-03-20 18:39:46 +01008981 */
8982 static void
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008983delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
Bram Moolenaar20431c92020-03-20 18:39:46 +01008984{
8985 int idx;
8986
8987 ga_clear(&dfunc->df_def_args_isn);
8988
8989 if (dfunc->df_instr != NULL)
8990 {
8991 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
8992 delete_instr(dfunc->df_instr + idx);
8993 VIM_CLEAR(dfunc->df_instr);
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008994 dfunc->df_instr = NULL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01008995 }
Bram Moolenaarc05fe072021-01-24 21:30:48 +01008996#ifdef FEAT_PROFILE
8997 if (dfunc->df_instr_prof != NULL)
8998 {
8999 for (idx = 0; idx < dfunc->df_instr_prof_count; ++idx)
9000 delete_instr(dfunc->df_instr_prof + idx);
9001 VIM_CLEAR(dfunc->df_instr_prof);
9002 dfunc->df_instr_prof = NULL;
9003 }
9004#endif
Bram Moolenaar20431c92020-03-20 18:39:46 +01009005
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009006 if (mark_deleted)
9007 dfunc->df_deleted = TRUE;
9008 if (dfunc->df_ufunc != NULL)
9009 dfunc->df_ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009010}
9011
9012/*
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009013 * When a user function is deleted, clear the contents of any associated def
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009014 * function, unless another user function still uses it.
9015 * The position in def_functions can be re-used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009016 */
9017 void
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009018unlink_def_function(ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009019{
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009020 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009021 {
9022 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9023 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009024
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009025 if (--dfunc->df_refcount <= 0)
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009026 delete_def_function_contents(dfunc, TRUE);
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009027 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009028 ufunc->uf_dfunc_idx = 0;
9029 if (dfunc->df_ufunc == ufunc)
9030 dfunc->df_ufunc = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009031 }
9032}
9033
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009034/*
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009035 * Used when a user function refers to an existing dfunc.
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009036 */
9037 void
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009038link_def_function(ufunc_T *ufunc)
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009039{
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009040 if (ufunc->uf_dfunc_idx > 0)
9041 {
9042 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9043 + ufunc->uf_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009044
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009045 ++dfunc->df_refcount;
9046 }
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009047}
9048
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009049#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01009050/*
9051 * Free all functions defined with ":def".
9052 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009053 void
9054free_def_functions(void)
9055{
Bram Moolenaar20431c92020-03-20 18:39:46 +01009056 int idx;
9057
9058 for (idx = 0; idx < def_functions.ga_len; ++idx)
9059 {
9060 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
9061
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009062 delete_def_function_contents(dfunc, TRUE);
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009063 vim_free(dfunc->df_name);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009064 }
9065
9066 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009067}
9068#endif
9069
9070
9071#endif // FEAT_EVAL