blob: a276d532378b4a4941c331da5fe2d0c133c68d62 [file] [log] [blame]
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9cmds.c: Dealing with commands of a compiled function
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19// When not generating protos this is included in proto.h
20#ifdef PROTO
21# include "vim9.h"
22#endif
23
24/*
25 * Get the index of the current instruction.
26 * This compensates for a preceding ISN_CMDMOD and ISN_PROF_START.
27 */
28 static int
29current_instr_idx(cctx_T *cctx)
30{
31 garray_T *instr = &cctx->ctx_instr;
32 int idx = instr->ga_len;
33
34 while (idx > 0)
35 {
36 if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[idx - 1]
37 .isn_type == ISN_CMDMOD)
38 {
39 --idx;
40 continue;
41 }
42#ifdef FEAT_PROFILE
43 if (((isn_T *)instr->ga_data)[idx - 1].isn_type == ISN_PROF_START)
44 {
45 --idx;
46 continue;
47 }
48#endif
49 if (((isn_T *)instr->ga_data)[idx - 1].isn_type == ISN_DEBUG)
50 {
51 --idx;
52 continue;
53 }
54 break;
55 }
56 return idx;
57}
58/*
59 * Remove local variables above "new_top".
Bram Moolenaara275f2c2022-10-11 20:04:09 +010060 * Do this by clearing the name. If "keep" is TRUE do not reset the length, a
61 * closure may still need location of the variable.
Bram Moolenaardc7c3662021-12-20 15:04:29 +000062 */
63 static void
Bram Moolenaara275f2c2022-10-11 20:04:09 +010064unwind_locals(cctx_T *cctx, int new_top, int keep)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000065{
66 if (cctx->ctx_locals.ga_len > new_top)
Bram Moolenaara275f2c2022-10-11 20:04:09 +010067 for (int idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000068 {
Bram Moolenaara275f2c2022-10-11 20:04:09 +010069 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
70 VIM_CLEAR(lvar->lv_name);
Bram Moolenaardc7c3662021-12-20 15:04:29 +000071 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +010072 if (!keep)
73 cctx->ctx_locals.ga_len = new_top;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000074}
75
76/*
77 * Free all local variables.
78 */
79 void
80free_locals(cctx_T *cctx)
81{
Bram Moolenaara275f2c2022-10-11 20:04:09 +010082 unwind_locals(cctx, 0, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +000083 ga_clear(&cctx->ctx_locals);
84}
85
86
87/*
88 * Check if "name" can be "unlet".
89 */
90 int
91check_vim9_unlet(char_u *name)
92{
Bram Moolenaardbdd16b2022-08-14 21:46:07 +010093 if (*name == NUL)
94 {
95 semsg(_(e_argument_required_for_str), "unlet");
96 return FAIL;
97 }
98
Bram Moolenaardc7c3662021-12-20 15:04:29 +000099 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
100 {
101 // "unlet s:var" is allowed in legacy script.
102 if (*name == 's' && !script_is_vim9())
103 return OK;
104 semsg(_(e_cannot_unlet_str), name);
105 return FAIL;
106 }
107 return OK;
108}
109
110/*
111 * Callback passed to ex_unletlock().
112 */
113 static int
114compile_unlet(
115 lval_T *lvp,
116 char_u *name_end,
117 exarg_T *eap,
118 int deep UNUSED,
119 void *coookie)
120{
121 cctx_T *cctx = coookie;
122 char_u *p = lvp->ll_name;
123 int cc = *name_end;
124 int ret = OK;
125
126 if (cctx->ctx_skip == SKIP_YES)
127 return OK;
128
129 *name_end = NUL;
130 if (*p == '$')
131 {
132 // :unlet $ENV_VAR
133 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
134 }
135 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
136 {
137 lhs_T lhs;
138
139 // This is similar to assigning: lookup the list/dict, compile the
140 // idx/key. Then instead of storing the value unlet the item.
141 // unlet {list}[idx]
142 // unlet {dict}[key] dict.key
143 //
144 // Figure out the LHS type and other properties.
145 //
Bram Moolenaar97f8c102022-04-02 19:43:57 +0100146 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, FALSE, 0, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000147
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000148 // Use the info in "lhs" to unlet the item at the index in the
149 // list or dict.
150 if (ret == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000151 {
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000152 if (!lhs.lhs_has_index)
153 {
154 semsg(_(e_cannot_unlet_imported_item_str), p);
155 ret = FAIL;
156 }
157 else
158 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000159 }
160
161 vim_free(lhs.lhs_name);
162 }
163 else if (check_vim9_unlet(p) == FAIL)
164 {
165 ret = FAIL;
166 }
167 else
168 {
169 // Normal name. Only supports g:, w:, t: and b: namespaces.
170 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
171 }
172
173 *name_end = cc;
174 return ret;
175}
176
177/*
178 * Callback passed to ex_unletlock().
179 */
180 static int
181compile_lock_unlock(
182 lval_T *lvp,
183 char_u *name_end,
184 exarg_T *eap,
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000185 int deep,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000186 void *coookie)
187{
188 cctx_T *cctx = coookie;
189 int cc = *name_end;
190 char_u *p = lvp->ll_name;
191 int ret = OK;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000192 char_u *buf;
193 isntype_T isn = ISN_EXEC;
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100194 char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
Ernie Raelee865f32023-09-29 19:53:55 +0200195 int is_arg = FALSE;
196
197#ifdef LOG_LOCKVAR
198 ch_log(NULL, "LKVAR: compile_lock_unlock(): cookie %p, name %s",
199 coookie, p);
200#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000201
202 if (cctx->ctx_skip == SKIP_YES)
203 return OK;
204
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100205 if (*p == NUL)
206 {
207 semsg(_(e_argument_required_for_str), cmd);
208 return FAIL;
209 }
210
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000211 // Cannot use :lockvar and :unlockvar on local variables.
212 if (p[1] != ':')
213 {
214 char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
Ernie Rael64885642023-10-04 20:16:22 +0200215
216 // The most important point is that something like
217 // name[idx].member... needs to be resolved at runtime, get_lval(),
218 // starting from the root "name".
219
220 // These checks are reminiscent of the variable_exists function.
221 // But most of the matches require special handling.
222
223 // If bare name is is locally accessible, except for local var,
Ernie Raelee865f32023-09-29 19:53:55 +0200224 // then put it on the stack to use with ISN_LOCKUNLOCK.
225 // This could be v.memb, v[idx_key]; bare class variable,
Ernie Rael64885642023-10-04 20:16:22 +0200226 // function arg. The item on the stack, will be passed
227 // to ex_lockvar() indirectly and be used as the root for get_lval.
228 // A bare script variable name needs no special handling.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000229
Ernie Raelee865f32023-09-29 19:53:55 +0200230 char_u *name = NULL;
231 int len = end - p;
232
233 if (lookup_local(p, len, NULL, cctx) == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000234 {
Ernie Raelee865f32023-09-29 19:53:55 +0200235 // Handle "this", "this.val", "anyvar[idx]"
236 if (*end != '.' && *end != '['
237 && (len != 4 || STRNCMP("this", p, len) != 0))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000238 {
239 emsg(_(e_cannot_lock_unlock_local_variable));
240 return FAIL;
241 }
Ernie Raelee865f32023-09-29 19:53:55 +0200242 // Push the local on the stack, could be "this".
243 name = p;
244#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +0200245 ch_log(NULL, "LKVAR: ... lookup_local: name %s", name);
Ernie Raelee865f32023-09-29 19:53:55 +0200246#endif
247 }
248 if (name == NULL)
249 {
250 class_T *cl;
251 if (cctx_class_member_idx(cctx, p, len, &cl) >= 0)
252 {
253 if (*end != '.' && *end != '[')
254 {
255 // Push the class of the bare class variable name
256 name = cl->class_name;
Yegappan Lakshmananb8523052023-10-08 19:07:39 +0200257 len = (int)STRLEN(name);
Ernie Raelee865f32023-09-29 19:53:55 +0200258#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +0200259 ch_log(NULL, "LKVAR: ... cctx_class_member: name %s",
Ernie Raelee865f32023-09-29 19:53:55 +0200260 name);
261#endif
262 }
263 }
264 }
265 if (name == NULL)
266 {
Ernie Raelee865f32023-09-29 19:53:55 +0200267 // Can lockvar any function arg.
Ernie Rael64885642023-10-04 20:16:22 +0200268 if (arg_exists(p, len, NULL, NULL, NULL, cctx) == OK)
Ernie Raelee865f32023-09-29 19:53:55 +0200269 {
270 name = p;
271 is_arg = TRUE;
272#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +0200273 ch_log(NULL, "LKVAR: ... arg_exists: name %s", name);
274#endif
275 }
276 }
277 if (name == NULL)
278 {
279 // No special handling for a bare script variable; but
280 // if followed by '[' or '.', it's a root for get_lval().
281 if (script_var_exists(p, len, cctx, NULL) == OK
282 && (*end == '.' || *end == '['))
283 {
284 name = p;
285#ifdef LOG_LOCKVAR
286 ch_log(NULL, "LKVAR: ... script_var_exists: name %s", name);
Ernie Raelee865f32023-09-29 19:53:55 +0200287#endif
288 }
289 }
290 if (name != NULL)
291 {
292#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +0200293 ch_log(NULL, "LKVAR: ... INS_LOCKUNLOCK %s", name);
Ernie Raelee865f32023-09-29 19:53:55 +0200294#endif
295 if (compile_load(&name, name + len, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000296 return FAIL;
297 isn = ISN_LOCKUNLOCK;
298 }
299 }
300
301 // Checking is done at runtime.
302 *name_end = NUL;
Ernie Raelee865f32023-09-29 19:53:55 +0200303 size_t len = name_end - p + 20;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000304 buf = alloc(len);
305 if (buf == NULL)
306 ret = FAIL;
307 else
308 {
Bram Moolenaare939f5e2022-01-26 21:32:59 +0000309 if (deep < 0)
310 vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
311 else
312 vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
Ernie Raelee865f32023-09-29 19:53:55 +0200313#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +0200314 ch_log(NULL, "LKVAR: ... buf %s", buf);
Ernie Raelee865f32023-09-29 19:53:55 +0200315#endif
316 if (isn == ISN_LOCKUNLOCK)
317 ret = generate_LOCKUNLOCK(cctx, buf, is_arg);
318 else
319 ret = generate_EXEC_copy(cctx, isn, buf);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000320
321 vim_free(buf);
322 *name_end = cc;
323 }
324 return ret;
325}
326
327/*
328 * compile "unlet var", "lock var" and "unlock var"
329 * "arg" points to "var".
330 */
331 char_u *
332compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
333{
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000334 int deep = 0;
335 char_u *p = arg;
336
337 if (eap->cmdidx != CMD_unlet)
338 {
339 if (eap->forceit)
340 deep = -1;
341 else if (vim_isdigit(*p))
342 {
343 deep = getdigits(&p);
344 p = skipwhite(p);
345 }
346 else
347 deep = 2;
348 }
349
350 ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000351 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
352 cctx);
353 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
354}
355
356/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100357 * Generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
358 * "funcref_idx" is used for JUMP_WHILE_FALSE
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000359 */
360 static int
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100361compile_jump_to_end(
362 endlabel_T **el,
363 jumpwhen_T when,
364 int funcref_idx,
365 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000366{
367 garray_T *instr = &cctx->ctx_instr;
368 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
369
370 if (endlabel == NULL)
371 return FAIL;
372 endlabel->el_next = *el;
373 *el = endlabel;
374 endlabel->el_end_label = instr->ga_len;
375
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100376 if (when == JUMP_WHILE_FALSE)
377 generate_WHILE(cctx, funcref_idx);
378 else
379 generate_JUMP(cctx, when, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000380 return OK;
381}
382
383 static void
384compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
385{
386 garray_T *instr = &cctx->ctx_instr;
387
388 while (*el != NULL)
389 {
390 endlabel_T *cur = (*el);
391 isn_T *isn;
392
393 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
394 isn->isn_arg.jump.jump_where = jump_where;
395 *el = cur->el_next;
396 vim_free(cur);
397 }
398}
399
400 static void
401compile_free_jump_to_end(endlabel_T **el)
402{
403 while (*el != NULL)
404 {
405 endlabel_T *cur = (*el);
406
407 *el = cur->el_next;
408 vim_free(cur);
409 }
410}
411
412/*
413 * Create a new scope and set up the generic items.
414 */
415 static scope_T *
416new_scope(cctx_T *cctx, scopetype_T type)
417{
418 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
419
420 if (scope == NULL)
421 return NULL;
422 scope->se_outer = cctx->ctx_scope;
423 cctx->ctx_scope = scope;
424 scope->se_type = type;
425 scope->se_local_count = cctx->ctx_locals.ga_len;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100426 if (scope->se_outer != NULL)
427 scope->se_loop_depth = scope->se_outer->se_loop_depth;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000428 return scope;
429}
430
431/*
432 * Free the current scope and go back to the outer scope.
433 */
434 void
435drop_scope(cctx_T *cctx)
436{
437 scope_T *scope = cctx->ctx_scope;
438
439 if (scope == NULL)
440 {
441 iemsg("calling drop_scope() without a scope");
442 return;
443 }
444 cctx->ctx_scope = scope->se_outer;
445 switch (scope->se_type)
446 {
447 case IF_SCOPE:
448 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
449 case FOR_SCOPE:
450 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
451 case WHILE_SCOPE:
452 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
453 case TRY_SCOPE:
454 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
455 case NO_SCOPE:
456 case BLOCK_SCOPE:
457 break;
458 }
459 vim_free(scope);
460}
461
462 static int
463misplaced_cmdmod(cctx_T *cctx)
464{
465 garray_T *instr = &cctx->ctx_instr;
466
467 if (cctx->ctx_has_cmdmod
468 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
469 == ISN_CMDMOD)
470 {
471 emsg(_(e_misplaced_command_modifier));
472 return TRUE;
473 }
474 return FALSE;
475}
476
477/*
478 * compile "if expr"
479 *
480 * "if expr" Produces instructions:
481 * EVAL expr Push result of "expr"
482 * JUMP_IF_FALSE end
483 * ... body ...
484 * end:
485 *
486 * "if expr | else" Produces instructions:
487 * EVAL expr Push result of "expr"
488 * JUMP_IF_FALSE else
489 * ... body ...
490 * JUMP_ALWAYS end
491 * else:
492 * ... body ...
493 * end:
494 *
495 * "if expr1 | elseif expr2 | else" Produces instructions:
496 * EVAL expr Push result of "expr"
497 * JUMP_IF_FALSE elseif
498 * ... body ...
499 * JUMP_ALWAYS end
500 * elseif:
501 * EVAL expr Push result of "expr"
502 * JUMP_IF_FALSE else
503 * ... body ...
504 * JUMP_ALWAYS end
505 * else:
506 * ... body ...
507 * end:
508 */
509 char_u *
510compile_if(char_u *arg, cctx_T *cctx)
511{
512 char_u *p = arg;
513 garray_T *instr = &cctx->ctx_instr;
514 int instr_count = instr->ga_len;
515 scope_T *scope;
516 skip_T skip_save = cctx->ctx_skip;
517 ppconst_T ppconst;
518
519 CLEAR_FIELD(ppconst);
520 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
521 {
522 clear_ppconst(&ppconst);
523 return NULL;
524 }
525 if (!ends_excmd2(arg, skipwhite(p)))
526 {
Bram Moolenaar74409f62022-01-01 15:58:22 +0000527 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000528 return NULL;
529 }
530 if (cctx->ctx_skip == SKIP_YES)
531 clear_ppconst(&ppconst);
532 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
533 {
534 int error = FALSE;
535 int v;
536
537 // The expression results in a constant.
538 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
539 clear_ppconst(&ppconst);
540 if (error)
541 return NULL;
542 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
543 }
544 else
545 {
546 // Not a constant, generate instructions for the expression.
547 cctx->ctx_skip = SKIP_UNKNOWN;
548 if (generate_ppconst(cctx, &ppconst) == FAIL)
549 return NULL;
550 if (bool_on_stack(cctx) == FAIL)
551 return NULL;
552 }
553
554 // CMDMOD_REV must come before the jump
555 generate_undo_cmdmods(cctx);
556
557 scope = new_scope(cctx, IF_SCOPE);
558 if (scope == NULL)
559 return NULL;
560 scope->se_skip_save = skip_save;
561 // "is_had_return" will be reset if any block does not end in :return
562 scope->se_u.se_if.is_had_return = TRUE;
563
564 if (cctx->ctx_skip == SKIP_UNKNOWN)
565 {
566 // "where" is set when ":elseif", "else" or ":endif" is found
567 scope->se_u.se_if.is_if_label = instr->ga_len;
568 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
569 }
570 else
571 scope->se_u.se_if.is_if_label = -1;
572
573#ifdef FEAT_PROFILE
574 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
575 && skip_save != SKIP_YES)
576 {
577 // generated a profile start, need to generate a profile end, since it
578 // won't be done after returning
579 cctx->ctx_skip = SKIP_NOT;
580 generate_instr(cctx, ISN_PROF_END);
581 cctx->ctx_skip = SKIP_YES;
582 }
583#endif
584
585 return p;
586}
587
588 char_u *
589compile_elseif(char_u *arg, cctx_T *cctx)
590{
591 char_u *p = arg;
592 garray_T *instr = &cctx->ctx_instr;
593 int instr_count;
594 isn_T *isn;
595 scope_T *scope = cctx->ctx_scope;
596 ppconst_T ppconst;
597 skip_T save_skip = cctx->ctx_skip;
598
599 if (scope == NULL || scope->se_type != IF_SCOPE)
600 {
601 emsg(_(e_elseif_without_if));
602 return NULL;
603 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100604 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000605 if (!cctx->ctx_had_return)
606 scope->se_u.se_if.is_had_return = FALSE;
607
608 if (cctx->ctx_skip == SKIP_NOT)
609 {
610 // previous block was executed, this one and following will not
611 cctx->ctx_skip = SKIP_YES;
612 scope->se_u.se_if.is_seen_skip_not = TRUE;
613 }
614 if (scope->se_u.se_if.is_seen_skip_not)
615 {
616 // A previous block was executed, skip over expression and bail out.
617 // Do not count the "elseif" for profiling and cmdmod
618 instr->ga_len = current_instr_idx(cctx);
619
620 skip_expr_cctx(&p, cctx);
621 return p;
622 }
623
624 if (cctx->ctx_skip == SKIP_UNKNOWN)
625 {
626 int moved_cmdmod = FALSE;
627 int saved_debug = FALSE;
628 isn_T debug_isn;
629
630 // Move any CMDMOD instruction to after the jump
631 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
632 {
633 if (GA_GROW_FAILS(instr, 1))
634 return NULL;
635 ((isn_T *)instr->ga_data)[instr->ga_len] =
636 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
637 --instr->ga_len;
638 moved_cmdmod = TRUE;
639 }
640
641 // Remove the already generated ISN_DEBUG, it is written below the
642 // ISN_FOR instruction.
643 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
644 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
645 .isn_type == ISN_DEBUG)
646 {
647 --instr->ga_len;
648 debug_isn = ((isn_T *)instr->ga_data)[instr->ga_len];
649 saved_debug = TRUE;
650 }
651
652 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100653 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000654 return NULL;
655 // previous "if" or "elseif" jumps here
656 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
657 isn->isn_arg.jump.jump_where = instr->ga_len;
658
659 if (moved_cmdmod)
660 ++instr->ga_len;
661
662 if (saved_debug)
663 {
664 // move the debug instruction here
665 if (GA_GROW_FAILS(instr, 1))
666 return NULL;
667 ((isn_T *)instr->ga_data)[instr->ga_len] = debug_isn;
668 ++instr->ga_len;
669 }
670 }
671
672 // compile "expr"; if we know it evaluates to FALSE skip the block
673 CLEAR_FIELD(ppconst);
674 if (cctx->ctx_skip == SKIP_YES)
675 {
676 cctx->ctx_skip = SKIP_UNKNOWN;
677#ifdef FEAT_PROFILE
678 if (cctx->ctx_compile_type == CT_PROFILE)
679 // the previous block was skipped, need to profile this line
680 generate_instr(cctx, ISN_PROF_START);
681#endif
682 if (cctx->ctx_compile_type == CT_DEBUG)
683 // the previous block was skipped, may want to debug this line
684 generate_instr_debug(cctx);
685 }
686
687 instr_count = instr->ga_len;
688 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
689 {
690 clear_ppconst(&ppconst);
691 return NULL;
692 }
693 cctx->ctx_skip = save_skip;
694 if (!ends_excmd2(arg, skipwhite(p)))
695 {
696 clear_ppconst(&ppconst);
Bram Moolenaar74409f62022-01-01 15:58:22 +0000697 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000698 return NULL;
699 }
700 if (scope->se_skip_save == SKIP_YES)
701 clear_ppconst(&ppconst);
702 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
703 {
704 int error = FALSE;
705 int v;
706
707 // The expression result is a constant.
708 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
709 if (error)
710 {
711 clear_ppconst(&ppconst);
712 return NULL;
713 }
714 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
715 clear_ppconst(&ppconst);
716 scope->se_u.se_if.is_if_label = -1;
717 }
718 else
719 {
720 // Not a constant, generate instructions for the expression.
721 cctx->ctx_skip = SKIP_UNKNOWN;
722 if (generate_ppconst(cctx, &ppconst) == FAIL)
723 return NULL;
724 if (bool_on_stack(cctx) == FAIL)
725 return NULL;
726
727 // CMDMOD_REV must come before the jump
728 generate_undo_cmdmods(cctx);
729
730 // "where" is set when ":elseif", "else" or ":endif" is found
731 scope->se_u.se_if.is_if_label = instr->ga_len;
732 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
733 }
734
735 return p;
736}
737
738 char_u *
739compile_else(char_u *arg, cctx_T *cctx)
740{
741 char_u *p = arg;
742 garray_T *instr = &cctx->ctx_instr;
743 isn_T *isn;
744 scope_T *scope = cctx->ctx_scope;
745
746 if (scope == NULL || scope->se_type != IF_SCOPE)
747 {
748 emsg(_(e_else_without_if));
749 return NULL;
750 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100751 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000752 if (!cctx->ctx_had_return)
753 scope->se_u.se_if.is_had_return = FALSE;
754 scope->se_u.se_if.is_seen_else = TRUE;
755
756#ifdef FEAT_PROFILE
757 if (cctx->ctx_compile_type == CT_PROFILE)
758 {
759 if (cctx->ctx_skip == SKIP_NOT
760 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
761 .isn_type == ISN_PROF_START)
762 // the previous block was executed, do not count "else" for
763 // profiling
764 --instr->ga_len;
765 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
766 {
767 // the previous block was not executed, this one will, do count the
768 // "else" for profiling
769 cctx->ctx_skip = SKIP_NOT;
770 generate_instr(cctx, ISN_PROF_END);
771 generate_instr(cctx, ISN_PROF_START);
772 cctx->ctx_skip = SKIP_YES;
773 }
774 }
775#endif
776
777 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
778 {
779 // jump from previous block to the end, unless the else block is empty
780 if (cctx->ctx_skip == SKIP_UNKNOWN)
781 {
782 if (!cctx->ctx_had_return
783 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100784 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000785 return NULL;
786 }
787
788 if (cctx->ctx_skip == SKIP_UNKNOWN)
789 {
790 if (scope->se_u.se_if.is_if_label >= 0)
791 {
792 // previous "if" or "elseif" jumps here
793 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
794 isn->isn_arg.jump.jump_where = instr->ga_len;
795 scope->se_u.se_if.is_if_label = -1;
796 }
797 }
798
799 if (cctx->ctx_skip != SKIP_UNKNOWN)
800 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
801 }
802
803 return p;
804}
805
806 char_u *
807compile_endif(char_u *arg, cctx_T *cctx)
808{
809 scope_T *scope = cctx->ctx_scope;
810 ifscope_T *ifscope;
811 garray_T *instr = &cctx->ctx_instr;
812 isn_T *isn;
813
814 if (misplaced_cmdmod(cctx))
815 return NULL;
816
817 if (scope == NULL || scope->se_type != IF_SCOPE)
818 {
819 emsg(_(e_endif_without_if));
820 return NULL;
821 }
822 ifscope = &scope->se_u.se_if;
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100823 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000824 if (!cctx->ctx_had_return)
825 ifscope->is_had_return = FALSE;
826
827 if (scope->se_u.se_if.is_if_label >= 0)
828 {
829 // previous "if" or "elseif" jumps here
830 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
831 isn->isn_arg.jump.jump_where = instr->ga_len;
832 }
833 // Fill in the "end" label in jumps at the end of the blocks.
834 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
835
836#ifdef FEAT_PROFILE
837 // even when skipping we count the endif as executed, unless the block it's
838 // in is skipped
839 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
840 && scope->se_skip_save != SKIP_YES)
841 {
842 cctx->ctx_skip = SKIP_NOT;
843 generate_instr(cctx, ISN_PROF_START);
844 }
845#endif
846 cctx->ctx_skip = scope->se_skip_save;
847
848 // If all the blocks end in :return and there is an :else then the
849 // had_return flag is set.
850 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
851
852 drop_scope(cctx);
853 return arg;
854}
855
856/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +0100857 * Save the info needed for ENDLOOP. Used by :for and :while.
858 */
859 static void
860compile_fill_loop_info(loop_info_T *loop_info, int funcref_idx, cctx_T *cctx)
861{
862 loop_info->li_funcref_idx = funcref_idx;
863 loop_info->li_local_count = cctx->ctx_locals.ga_len;
864 loop_info->li_closure_count = cctx->ctx_closure_count;
865}
866
867/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000868 * Compile "for var in expr":
869 *
870 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100871 * STORE -1 in loop-idx Set index to -1
872 * EVAL expr Result of "expr" on top of stack
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000873 * top: FOR loop-idx, end Increment index, use list on bottom of stack
874 * - if beyond end, jump to "end"
875 * - otherwise get item from list and push it
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100876 * - store ec_funcrefs in var "loop-idx" + 1
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000877 * STORE var Store item in "var"
878 * ... body ...
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100879 * ENDLOOP funcref-idx off count Only if closure uses local var
880 * JUMP top Jump back to repeat
881 * end: DROP Drop the result of "expr"
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000882 *
883 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
884 * UNPACK 2 Split item in 2
885 * STORE var1 Store item in "var1"
886 * STORE var2 Store item in "var2"
887 */
888 char_u *
889compile_for(char_u *arg_start, cctx_T *cctx)
890{
891 char_u *arg;
892 char_u *arg_end;
893 char_u *name = NULL;
894 char_u *p;
895 char_u *wp;
896 int var_count = 0;
897 int var_list = FALSE;
898 int semicolon = FALSE;
899 size_t varlen;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000900 garray_T *instr = &cctx->ctx_instr;
901 scope_T *scope;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100902 forscope_T *forscope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000903 lvar_T *loop_lvar; // loop iteration variable
Bram Moolenaarcc341812022-09-19 15:54:34 +0100904 int loop_lvar_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100905 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100906 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000907 lvar_T *var_lvar; // variable for "var"
908 type_T *vartype;
909 type_T *item_type = &t_any;
910 int idx;
911 int prev_lnum = cctx->ctx_prev_lnum;
912
913 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
914 if (p == NULL)
915 return NULL;
916 if (var_count == 0)
917 var_count = 1;
918 else
919 var_list = TRUE; // can also be a list of one variable
920
921 // consume "in"
922 wp = p;
923 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
924 return NULL;
925 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
926 {
927 if (*p == ':' && wp != p)
928 semsg(_(e_no_white_space_allowed_before_colon_str), p);
929 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000930 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000931 return NULL;
932 }
933 wp = p + 2;
934 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
935 return NULL;
936
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000937 // Find the already generated ISN_DEBUG to get the line number for the
938 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000939 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
940 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
941 .isn_type == ISN_DEBUG)
942 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000943 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000944 .isn_arg.debug.dbg_break_lnum;
945 }
946
947 scope = new_scope(cctx, FOR_SCOPE);
948 if (scope == NULL)
949 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100950 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
951 {
952 emsg(_(e_loop_nesting_too_deep));
953 return NULL;
954 }
955 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100956 forscope = &scope->se_u.se_for;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000957
958 // Reserve a variable to store the loop iteration counter and initialize it
959 // to -1.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100960 loop_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000961 if (loop_lvar == NULL)
962 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000963 drop_scope(cctx);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100964 return NULL; // out of memory
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000965 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100966 // get the index before a following reserve_local() makes the lval invalid
967 loop_lvar_idx = loop_lvar->lv_idx;
968 generate_STORENR(cctx, loop_lvar_idx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000969
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100970 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
971 // The variable index is always the loop var index plus one.
972 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100973 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100974 if (funcref_lvar == NULL)
975 {
976 drop_scope(cctx);
977 return NULL; // out of memory
978 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100979 // get the index before a following reserve_local() makes the lval invalid
980 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100981
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000982 // compile "expr", it remains on the stack until "endfor"
983 arg = p;
984 if (compile_expr0(&arg, cctx) == FAIL)
985 {
986 drop_scope(cctx);
987 return NULL;
988 }
989 arg_end = arg;
990
991 if (cctx->ctx_skip != SKIP_YES)
992 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000993 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000994 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000995 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000996 if (vartype->tt_type != VAR_LIST
997 && vartype->tt_type != VAR_STRING
998 && vartype->tt_type != VAR_BLOB
999 && vartype->tt_type != VAR_ANY
1000 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001001 {
1002 semsg(_(e_for_loop_on_str_not_supported),
1003 vartype_name(vartype->tt_type));
1004 drop_scope(cctx);
1005 return NULL;
1006 }
1007
1008 if (vartype->tt_type == VAR_STRING)
1009 item_type = &t_string;
1010 else if (vartype->tt_type == VAR_BLOB)
1011 item_type = &t_number;
1012 else if (vartype->tt_type == VAR_LIST
1013 && vartype->tt_member->tt_type != VAR_ANY)
1014 {
1015 if (!var_list)
1016 item_type = vartype->tt_member;
1017 else if (vartype->tt_member->tt_type == VAR_LIST
1018 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
1019 item_type = vartype->tt_member->tt_member;
1020 }
1021
1022 // CMDMOD_REV must come before the FOR instruction.
1023 generate_undo_cmdmods(cctx);
1024
1025 // "for_end" is set when ":endfor" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001026 forscope->fs_top_label = current_instr_idx(cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001027
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001028 if (cctx->ctx_compile_type == CT_DEBUG)
1029 {
1030 int save_prev_lnum = cctx->ctx_prev_lnum;
1031 isn_T *isn;
1032
1033 // Add ISN_DEBUG here, before deciding to end the loop. There will
1034 // be another ISN_DEBUG before the next instruction.
1035 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
1036 // Increment the variable count so that the loop variable can be
1037 // inspected.
1038 cctx->ctx_prev_lnum = prev_lnum;
1039 isn = generate_instr_debug(cctx);
1040 ++isn->isn_arg.debug.dbg_var_names_len;
1041 cctx->ctx_prev_lnum = save_prev_lnum;
1042 }
1043
Bram Moolenaarcc341812022-09-19 15:54:34 +01001044 generate_FOR(cctx, loop_lvar_idx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001045
1046 arg = arg_start;
1047 if (var_list)
1048 {
1049 generate_UNPACK(cctx, var_count, semicolon);
1050 arg = skipwhite(arg + 1); // skip white after '['
1051
Bram Moolenaar078a4612022-01-04 15:17:03 +00001052 // drop the list item
1053 --cctx->ctx_type_stack.ga_len;
1054
1055 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001056 for (idx = 0; idx < var_count; ++idx)
1057 {
Bram Moolenaar078a4612022-01-04 15:17:03 +00001058 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
1059
1060 if (push_type_stack(cctx, type) == FAIL)
1061 {
1062 drop_scope(cctx);
1063 return NULL;
1064 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001065 }
1066 }
1067
1068 for (idx = 0; idx < var_count; ++idx)
1069 {
1070 assign_dest_T dest = dest_local;
1071 int opt_flags = 0;
1072 int vimvaridx = -1;
1073 type_T *type = &t_any;
1074 type_T *lhs_type = &t_any;
1075 where_T where = WHERE_INIT;
1076
1077 p = skip_var_one(arg, FALSE);
1078 varlen = p - arg;
1079 name = vim_strnsave(arg, varlen);
1080 if (name == NULL)
1081 goto failed;
Bram Moolenaarce93d162023-01-30 21:12:34 +00001082 if (*skipwhite(p) == ':')
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001083 {
Bram Moolenaarce93d162023-01-30 21:12:34 +00001084 if (VIM_ISWHITE(*p))
1085 {
1086 semsg(_(e_no_white_space_allowed_before_colon_str), p);
1087 goto failed;
1088 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001089 p = skipwhite(p + 1);
1090 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
Yegappan Lakshmanan062bb6b2023-12-16 14:46:40 +01001091 if (lhs_type == NULL)
1092 goto failed;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001093 }
1094
1095 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
1096 &vimvaridx, &type, cctx) == FAIL)
1097 goto failed;
1098 if (dest != dest_local)
1099 {
1100 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
Bram Moolenaard505d172022-12-18 21:42:55 +00001101 type, name, NULL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001102 goto failed;
1103 }
1104 else if (varlen == 1 && *arg == '_')
1105 {
1106 // Assigning to "_": drop the value.
1107 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1108 goto failed;
1109 }
1110 else
1111 {
1112 // Script var is not supported.
1113 if (STRNCMP(name, "s:", 2) == 0)
1114 {
1115 emsg(_(e_cannot_use_script_variable_in_for_loop));
1116 goto failed;
1117 }
1118
1119 if (!valid_varname(arg, (int)varlen, FALSE))
1120 goto failed;
1121 if (lookup_local(arg, varlen, NULL, cctx) == OK)
1122 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001123 semsg(_(e_variable_already_declared_str), arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001124 goto failed;
1125 }
1126
1127 // Reserve a variable to store "var".
LemonBoyc5d27442023-08-19 13:02:35 +02001128 if (var_list)
1129 {
1130 where.wt_index = idx + 1;
1131 where.wt_kind = WT_VARIABLE;
1132 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001133 if (lhs_type == &t_any)
1134 lhs_type = item_type;
1135 else if (item_type != &t_unknown
Bram Moolenaarc6951a72022-12-29 20:56:24 +00001136 && need_type_where(item_type, lhs_type, FALSE, -1,
Bram Moolenaara1c51952022-02-02 16:20:26 +00001137 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001138 goto failed;
Bram Moolenaar159b2d52022-10-11 21:41:25 +01001139 var_lvar = reserve_local(cctx, arg, varlen, ASSIGN_FINAL,
Bram Moolenaar6586a012022-09-30 11:04:50 +01001140 lhs_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001141 if (var_lvar == NULL)
1142 // out of memory or used as an argument
1143 goto failed;
1144
1145 if (semicolon && idx == var_count - 1)
1146 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001147 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1148 }
1149
1150 if (*p == ',' || *p == ';')
1151 ++p;
1152 arg = skipwhite(p);
1153 vim_free(name);
1154 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001155
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001156 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001157 compile_fill_loop_info(&forscope->fs_loop_info, funcref_lvar_idx, cctx);
1158 forscope->fs_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001159 }
1160
1161 return arg_end;
1162
1163failed:
1164 vim_free(name);
1165 drop_scope(cctx);
1166 return NULL;
1167}
1168
1169/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001170 * Used when ending a loop of :for and :while: Generate an ISN_ENDLOOP
1171 * instruction if any variable was declared that could be used by a new
1172 * closure.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001173 */
1174 static int
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001175compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001176{
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001177 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1178 && cctx->ctx_closure_count > loop_info->li_closure_count)
Bram Moolenaarcc341812022-09-19 15:54:34 +01001179 return generate_ENDLOOP(cctx, loop_info);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001180 return OK;
1181}
1182
1183/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001184 * compile "endfor"
1185 */
1186 char_u *
1187compile_endfor(char_u *arg, cctx_T *cctx)
1188{
1189 garray_T *instr = &cctx->ctx_instr;
1190 scope_T *scope = cctx->ctx_scope;
1191 forscope_T *forscope;
1192 isn_T *isn;
1193
1194 if (misplaced_cmdmod(cctx))
1195 return NULL;
1196
1197 if (scope == NULL || scope->se_type != FOR_SCOPE)
1198 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001199 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001200 return NULL;
1201 }
1202 forscope = &scope->se_u.se_for;
1203 cctx->ctx_scope = scope->se_outer;
1204 if (cctx->ctx_skip != SKIP_YES)
1205 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001206 // Handle the case that any local variables were declared that might be
1207 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001208 if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001209 return NULL;
1210
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001211 unwind_locals(cctx, scope->se_local_count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001212
1213 // At end of ":for" scope jump back to the FOR instruction.
1214 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1215
1216 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001217 // In debug mode an ISN_DEBUG was inserted.
1218 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1219 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001220 isn->isn_arg.forloop.for_end = instr->ga_len;
1221
1222 // Fill in the "end" label any BREAK statements
1223 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1224
1225 // Below the ":for" scope drop the "expr" list from the stack.
1226 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1227 return NULL;
1228 }
1229
1230 vim_free(scope);
1231
1232 return arg;
1233}
1234
1235/*
1236 * compile "while expr"
1237 *
1238 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001239 * top: EVAL expr Push result of "expr"
1240 * WHILE funcref-idx end Jump if false
1241 * ... body ...
1242 * ENDLOOP funcref-idx off count only if closure uses local var
1243 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001244 * end:
1245 *
1246 */
1247 char_u *
1248compile_while(char_u *arg, cctx_T *cctx)
1249{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001250 char_u *p = arg;
1251 scope_T *scope;
1252 whilescope_T *whilescope;
1253 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001254 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001255
1256 scope = new_scope(cctx, WHILE_SCOPE);
1257 if (scope == NULL)
1258 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001259 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
1260 {
1261 emsg(_(e_loop_nesting_too_deep));
1262 return NULL;
1263 }
1264 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001265 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001266
1267 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001268 whilescope->ws_top_label = current_instr_idx(cctx);
1269
1270 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1271 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +01001272 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001273 if (funcref_lvar == NULL)
1274 {
1275 drop_scope(cctx);
1276 return NULL; // out of memory
1277 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001278 // get the index before a following reserve_local() makes the lval invalid
1279 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001280
1281 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001282 compile_fill_loop_info(&whilescope->ws_loop_info, funcref_lvar_idx, cctx);
1283 whilescope->ws_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001284
1285 // compile "expr"
1286 if (compile_expr0(&p, cctx) == FAIL)
1287 return NULL;
1288
1289 if (!ends_excmd2(arg, skipwhite(p)))
1290 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001291 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001292 return NULL;
1293 }
1294
1295 if (cctx->ctx_skip != SKIP_YES)
1296 {
1297 if (bool_on_stack(cctx) == FAIL)
1298 return FAIL;
1299
1300 // CMDMOD_REV must come before the jump
1301 generate_undo_cmdmods(cctx);
1302
1303 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001304 if (compile_jump_to_end(&whilescope->ws_end_label,
Bram Moolenaarcc341812022-09-19 15:54:34 +01001305 JUMP_WHILE_FALSE, funcref_lvar_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001306 return FAIL;
1307 }
1308
1309 return p;
1310}
1311
1312/*
1313 * compile "endwhile"
1314 */
1315 char_u *
1316compile_endwhile(char_u *arg, cctx_T *cctx)
1317{
1318 scope_T *scope = cctx->ctx_scope;
1319 garray_T *instr = &cctx->ctx_instr;
1320
1321 if (misplaced_cmdmod(cctx))
1322 return NULL;
1323 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1324 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001325 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001326 return NULL;
1327 }
1328 cctx->ctx_scope = scope->se_outer;
1329 if (cctx->ctx_skip != SKIP_YES)
1330 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001331 whilescope_T *whilescope = &scope->se_u.se_while;
1332
1333 // Handle the case that any local variables were declared that might be
1334 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001335 if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001336 return NULL;
1337
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001338 unwind_locals(cctx, scope->se_local_count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001339
1340#ifdef FEAT_PROFILE
1341 // count the endwhile before jumping
1342 may_generate_prof_end(cctx, cctx->ctx_lnum);
1343#endif
1344
1345 // At end of ":for" scope jump back to the FOR instruction.
1346 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1347
1348 // Fill in the "end" label in the WHILE statement so it can jump here.
1349 // And in any jumps for ":break"
1350 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1351 instr->ga_len, cctx);
1352 }
1353
1354 vim_free(scope);
1355
1356 return arg;
1357}
1358
1359/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001360 * Get the current information about variables declared inside a loop.
Bram Moolenaarcc341812022-09-19 15:54:34 +01001361 * Returns TRUE if there are any and fills "lvi".
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001362 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001363 int
1364get_loop_var_info(cctx_T *cctx, loopvarinfo_T *lvi)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001365{
1366 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001367 int prev_local_count = 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001368
Bram Moolenaarcc341812022-09-19 15:54:34 +01001369 CLEAR_POINTER(lvi);
1370 for (;;)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001371 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01001372 loop_info_T *loopinfo;
1373 int cur_local_last;
1374 int start_local_count;
1375
1376 while (scope != NULL && scope->se_type != WHILE_SCOPE
1377 && scope->se_type != FOR_SCOPE)
1378 scope = scope->se_outer;
1379 if (scope == NULL)
1380 break;
1381
1382 if (scope->se_type == WHILE_SCOPE)
1383 {
1384 loopinfo = &scope->se_u.se_while.ws_loop_info;
1385 // :while reserves one variable for funcref count
1386 cur_local_last = loopinfo->li_local_count - 1;
1387 }
1388 else
1389 {
1390 loopinfo = &scope->se_u.se_for.fs_loop_info;
1391 // :for reserves three variable: loop count, funcref count and loop
1392 // var
1393 cur_local_last = loopinfo->li_local_count - 3;
1394 }
1395
1396 start_local_count = loopinfo->li_local_count;
1397 if (cctx->ctx_locals.ga_len > start_local_count)
1398 {
1399 lvi->lvi_loop[loopinfo->li_depth].var_idx =
1400 (short)start_local_count;
1401 lvi->lvi_loop[loopinfo->li_depth].var_count =
1402 (short)(cctx->ctx_locals.ga_len - start_local_count
1403 - prev_local_count);
1404 if (lvi->lvi_depth == 0)
1405 lvi->lvi_depth = loopinfo->li_depth + 1;
1406 }
1407
1408 scope = scope->se_outer;
1409 prev_local_count = cctx->ctx_locals.ga_len - cur_local_last;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001410 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001411 return lvi->lvi_depth > 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001412}
1413
1414/*
Bram Moolenaarcc341812022-09-19 15:54:34 +01001415 * Get the index of the variable "idx" in a loop, if any.
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001416 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001417 void
1418get_loop_var_idx(cctx_T *cctx, int idx, lvar_T *lvar)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001419{
Bram Moolenaarcc341812022-09-19 15:54:34 +01001420 loopvarinfo_T lvi;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001421
Bram Moolenaarcc341812022-09-19 15:54:34 +01001422 lvar->lv_loop_depth = -1;
1423 lvar->lv_loop_idx = -1;
1424 if (get_loop_var_info(cctx, &lvi))
1425 {
1426 int depth;
1427
1428 for (depth = lvi.lvi_depth - 1; depth >= 0; --depth)
1429 if (idx >= lvi.lvi_loop[depth].var_idx
1430 && idx < lvi.lvi_loop[depth].var_idx
1431 + lvi.lvi_loop[depth].var_count)
1432 {
1433 lvar->lv_loop_depth = depth;
1434 lvar->lv_loop_idx = lvi.lvi_loop[depth].var_idx;
1435 return;
1436 }
1437 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001438}
1439
1440/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001441 * Common for :break, :continue and :return
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001442 */
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001443 static int
1444compile_find_scope(
1445 int *loop_label, // where to jump to or NULL
1446 endlabel_T ***el, // end label or NULL
1447 int *try_scopes, // :try scopes encountered or NULL
1448 char *error, // error to use when no scope found
1449 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001450{
1451 scope_T *scope = cctx->ctx_scope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001452
1453 for (;;)
1454 {
1455 if (scope == NULL)
1456 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001457 if (error != NULL)
1458 emsg(_(error));
1459 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001460 }
1461 if (scope->se_type == FOR_SCOPE)
1462 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001463 if (compile_loop_end(&scope->se_u.se_for.fs_loop_info, cctx)
1464 == FAIL)
1465 return FAIL;
1466 if (loop_label != NULL)
1467 *loop_label = scope->se_u.se_for.fs_top_label;
1468 if (el != NULL)
1469 *el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001470 break;
1471 }
1472 if (scope->se_type == WHILE_SCOPE)
1473 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001474 if (compile_loop_end(&scope->se_u.se_while.ws_loop_info, cctx)
1475 == FAIL)
1476 return FAIL;
1477 if (loop_label != NULL)
1478 *loop_label = scope->se_u.se_while.ws_top_label;
1479 if (el != NULL)
1480 *el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001481 break;
1482 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001483 if (try_scopes != NULL && scope->se_type == TRY_SCOPE)
1484 ++*try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001485 scope = scope->se_outer;
1486 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001487 return OK;
1488}
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001489
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001490/*
1491 * compile "continue"
1492 */
1493 char_u *
1494compile_continue(char_u *arg, cctx_T *cctx)
1495{
1496 int try_scopes = 0;
1497 int loop_label;
1498
1499 if (compile_find_scope(&loop_label, NULL, &try_scopes,
1500 e_continue_without_while_or_for, cctx) == FAIL)
1501 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001502 if (try_scopes > 0)
1503 // Inside one or more try/catch blocks we first need to jump to the
1504 // "finally" or "endtry" to cleanup.
1505 generate_TRYCONT(cctx, try_scopes, loop_label);
1506 else
1507 // Jump back to the FOR or WHILE instruction.
1508 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1509
1510 return arg;
1511}
1512
1513/*
1514 * compile "break"
1515 */
1516 char_u *
1517compile_break(char_u *arg, cctx_T *cctx)
1518{
Bram Moolenaar873f8242022-03-10 21:53:44 +00001519 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001520 endlabel_T **el;
1521
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001522 if (compile_find_scope(NULL, &el, &try_scopes,
1523 e_break_without_while_or_for, cctx) == FAIL)
1524 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001525
Bram Moolenaar3f45d672023-02-27 22:06:51 +00001526 if (cctx->ctx_skip == SKIP_YES)
1527 return arg;
1528
Bram Moolenaar873f8242022-03-10 21:53:44 +00001529 if (try_scopes > 0)
1530 // Inside one or more try/catch blocks we first need to jump to the
1531 // "finally" or "endtry" to cleanup. Then come to the next JUMP
dundargocc57b5bc2022-11-02 13:30:51 +00001532 // instruction, which we don't know the index of yet.
Bram Moolenaar873f8242022-03-10 21:53:44 +00001533 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1534
1535 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1536 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001537 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaar3f45d672023-02-27 22:06:51 +00001538 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001539
1540 return arg;
1541}
1542
1543/*
1544 * compile "{" start of block
1545 */
1546 char_u *
1547compile_block(char_u *arg, cctx_T *cctx)
1548{
1549 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1550 return NULL;
1551 return skipwhite(arg + 1);
1552}
1553
1554/*
1555 * compile end of block: drop one scope
1556 */
1557 void
1558compile_endblock(cctx_T *cctx)
1559{
1560 scope_T *scope = cctx->ctx_scope;
1561
1562 cctx->ctx_scope = scope->se_outer;
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001563 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001564 vim_free(scope);
1565}
1566
1567/*
1568 * Compile "try".
1569 * Creates a new scope for the try-endtry, pointing to the first catch and
1570 * finally.
1571 * Creates another scope for the "try" block itself.
1572 * TRY instruction sets up exception handling at runtime.
1573 *
1574 * "try"
1575 * TRY -> catch1, -> finally push trystack entry
1576 * ... try block
1577 * "throw {exception}"
1578 * EVAL {exception}
1579 * THROW create exception
1580 * ... try block
1581 * " catch {expr}"
1582 * JUMP -> finally
1583 * catch1: PUSH exception
1584 * EVAL {expr}
1585 * MATCH
1586 * JUMP nomatch -> catch2
1587 * CATCH remove exception
1588 * ... catch block
1589 * " catch"
1590 * JUMP -> finally
1591 * catch2: CATCH remove exception
1592 * ... catch block
1593 * " finally"
1594 * finally:
1595 * ... finally block
1596 * " endtry"
1597 * ENDTRY pop trystack entry, may rethrow
1598 */
1599 char_u *
1600compile_try(char_u *arg, cctx_T *cctx)
1601{
1602 garray_T *instr = &cctx->ctx_instr;
1603 scope_T *try_scope;
1604 scope_T *scope;
1605
1606 if (misplaced_cmdmod(cctx))
1607 return NULL;
1608
1609 // scope that holds the jumps that go to catch/finally/endtry
1610 try_scope = new_scope(cctx, TRY_SCOPE);
1611 if (try_scope == NULL)
1612 return NULL;
1613
1614 if (cctx->ctx_skip != SKIP_YES)
1615 {
1616 isn_T *isn;
1617
1618 // "try_catch" is set when the first ":catch" is found or when no catch
1619 // is found and ":finally" is found.
1620 // "try_finally" is set when ":finally" is found
1621 // "try_endtry" is set when ":endtry" is found
1622 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1623 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1624 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001625 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1626 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001627 return NULL;
1628 }
1629
1630 // scope for the try block itself
1631 scope = new_scope(cctx, BLOCK_SCOPE);
1632 if (scope == NULL)
1633 return NULL;
1634
1635 return arg;
1636}
1637
1638/*
1639 * Compile "catch {expr}".
1640 */
1641 char_u *
1642compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1643{
1644 scope_T *scope = cctx->ctx_scope;
1645 garray_T *instr = &cctx->ctx_instr;
1646 char_u *p;
1647 isn_T *isn;
1648
1649 if (misplaced_cmdmod(cctx))
1650 return NULL;
1651
1652 // end block scope from :try or :catch
1653 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1654 compile_endblock(cctx);
1655 scope = cctx->ctx_scope;
1656
1657 // Error if not in a :try scope
1658 if (scope == NULL || scope->se_type != TRY_SCOPE)
1659 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001660 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001661 return NULL;
1662 }
1663
Bram Moolenaar9d383f32023-05-14 21:38:12 +01001664 if (scope->se_u.se_try.ts_caught_all
1665 && !ignore_unreachable_code_for_testing)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001666 {
1667 emsg(_(e_catch_unreachable_after_catch_all));
1668 return NULL;
1669 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001670 if (!cctx->ctx_had_return)
1671 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001672
1673 if (cctx->ctx_skip != SKIP_YES)
1674 {
1675#ifdef FEAT_PROFILE
1676 // the profile-start should be after the jump
1677 if (cctx->ctx_compile_type == CT_PROFILE
1678 && instr->ga_len > 0
1679 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1680 .isn_type == ISN_PROF_START)
1681 --instr->ga_len;
1682#endif
1683 // Jump from end of previous block to :finally or :endtry
1684 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001685 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001686 return NULL;
1687
1688 // End :try or :catch scope: set value in ISN_TRY instruction
1689 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001690 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1691 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001692 if (scope->se_u.se_try.ts_catch_label != 0)
1693 {
1694 // Previous catch without match jumps here
1695 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1696 isn->isn_arg.jump.jump_where = instr->ga_len;
1697 }
1698#ifdef FEAT_PROFILE
1699 if (cctx->ctx_compile_type == CT_PROFILE)
1700 {
1701 // a "throw" that jumps here needs to be counted
1702 generate_instr(cctx, ISN_PROF_END);
1703 // the "catch" is also counted
1704 generate_instr(cctx, ISN_PROF_START);
1705 }
1706#endif
1707 if (cctx->ctx_compile_type == CT_DEBUG)
1708 generate_instr_debug(cctx);
1709 }
1710
1711 p = skipwhite(arg);
1712 if (ends_excmd2(arg, p))
1713 {
1714 scope->se_u.se_try.ts_caught_all = TRUE;
1715 scope->se_u.se_try.ts_catch_label = 0;
1716 }
1717 else
1718 {
1719 char_u *end;
1720 char_u *pat;
1721 char_u *tofree = NULL;
1722 int dropped = 0;
1723 int len;
1724
1725 // Push v:exception, push {expr} and MATCH
1726 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1727
1728 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1729 if (*end != *p)
1730 {
1731 semsg(_(e_separator_mismatch_str), p);
1732 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001733 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001734 }
1735 if (tofree == NULL)
1736 len = (int)(end - (p + 1));
1737 else
1738 len = (int)(end - tofree);
1739 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1740 vim_free(tofree);
1741 p += len + 2 + dropped;
1742 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001743 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001744 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001745 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001746
1747 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1748 return NULL;
1749
1750 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1751 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1752 return NULL;
1753 }
1754
1755 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1756 return NULL;
1757
1758 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1759 return NULL;
1760 return p;
1761}
1762
1763 char_u *
1764compile_finally(char_u *arg, cctx_T *cctx)
1765{
1766 scope_T *scope = cctx->ctx_scope;
1767 garray_T *instr = &cctx->ctx_instr;
1768 isn_T *isn;
1769 int this_instr;
1770
1771 if (misplaced_cmdmod(cctx))
1772 return NULL;
1773
1774 // end block scope from :try or :catch
1775 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1776 compile_endblock(cctx);
1777 scope = cctx->ctx_scope;
1778
1779 // Error if not in a :try scope
1780 if (scope == NULL || scope->se_type != TRY_SCOPE)
1781 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001782 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001783 return NULL;
1784 }
1785
1786 if (cctx->ctx_skip != SKIP_YES)
1787 {
1788 // End :catch or :finally scope: set value in ISN_TRY instruction
1789 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001790 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001791 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001792 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001793 return NULL;
1794 }
1795
1796 this_instr = instr->ga_len;
1797#ifdef FEAT_PROFILE
1798 if (cctx->ctx_compile_type == CT_PROFILE
1799 && ((isn_T *)instr->ga_data)[this_instr - 1]
1800 .isn_type == ISN_PROF_START)
1801 {
1802 // jump to the profile start of the "finally"
1803 --this_instr;
1804
1805 // jump to the profile end above it
1806 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1807 .isn_type == ISN_PROF_END)
1808 --this_instr;
1809 }
1810#endif
1811
1812 // Fill in the "end" label in jumps at the end of the blocks.
1813 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1814 this_instr, cctx);
1815
1816 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001817 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1818 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1819 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001820 if (scope->se_u.se_try.ts_catch_label != 0)
1821 {
1822 // Previous catch without match jumps here
1823 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1824 isn->isn_arg.jump.jump_where = this_instr;
1825 scope->se_u.se_try.ts_catch_label = 0;
1826 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001827 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001828 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1829 return NULL;
1830 }
1831
1832 return arg;
1833}
1834
1835 char_u *
1836compile_endtry(char_u *arg, cctx_T *cctx)
1837{
1838 scope_T *scope = cctx->ctx_scope;
1839 garray_T *instr = &cctx->ctx_instr;
1840 isn_T *try_isn;
1841
1842 if (misplaced_cmdmod(cctx))
1843 return NULL;
1844
1845 // end block scope from :catch or :finally
1846 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1847 compile_endblock(cctx);
1848 scope = cctx->ctx_scope;
1849
1850 // Error if not in a :try scope
1851 if (scope == NULL || scope->se_type != TRY_SCOPE)
1852 {
1853 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001854 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001855 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001856 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001857 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001858 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001859 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001860 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001861 return NULL;
1862 }
1863
1864 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1865 if (cctx->ctx_skip != SKIP_YES)
1866 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001867 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1868 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001869 {
1870 emsg(_(e_missing_catch_or_finally));
1871 return NULL;
1872 }
1873
1874#ifdef FEAT_PROFILE
1875 if (cctx->ctx_compile_type == CT_PROFILE
1876 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1877 .isn_type == ISN_PROF_START)
1878 // move the profile start after "endtry" so that it's not counted when
1879 // the exception is rethrown.
1880 --instr->ga_len;
1881#endif
1882
1883 // Fill in the "end" label in jumps at the end of the blocks, if not
1884 // done by ":finally".
1885 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1886 instr->ga_len, cctx);
1887
1888 if (scope->se_u.se_try.ts_catch_label != 0)
1889 {
1890 // Last catch without match jumps here
1891 isn_T *isn = ((isn_T *)instr->ga_data)
1892 + scope->se_u.se_try.ts_catch_label;
1893 isn->isn_arg.jump.jump_where = instr->ga_len;
1894 }
1895 }
1896
Bram Moolenaar53c29612022-01-12 16:18:18 +00001897 // If there is a finally clause that ends in return then we will return.
1898 // If one of the blocks didn't end in "return" or we did not catch all
1899 // exceptions reset the had_return flag.
1900 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1901 && (scope->se_u.se_try.ts_no_return
1902 || !scope->se_u.se_try.ts_caught_all))
1903 cctx->ctx_had_return = FALSE;
1904
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001905 compile_endblock(cctx);
1906
1907 if (cctx->ctx_skip != SKIP_YES)
1908 {
1909 // End :catch or :finally scope: set instruction index in ISN_TRY
1910 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001911 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001912 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001913 return NULL;
1914#ifdef FEAT_PROFILE
1915 if (cctx->ctx_compile_type == CT_PROFILE)
1916 generate_instr(cctx, ISN_PROF_START);
1917#endif
1918 }
1919 return arg;
1920}
1921
1922/*
1923 * compile "throw {expr}"
1924 */
1925 char_u *
1926compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1927{
1928 char_u *p = skipwhite(arg);
1929
1930 if (compile_expr0(&p, cctx) == FAIL)
1931 return NULL;
1932 if (cctx->ctx_skip == SKIP_YES)
1933 return p;
1934 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1935 return NULL;
1936 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1937 return NULL;
1938
1939 return p;
1940}
1941
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001942/*
1943 * Compile an expression or function call.
1944 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001945 char_u *
1946compile_eval(char_u *arg, cctx_T *cctx)
1947{
1948 char_u *p = arg;
1949 int name_only;
1950 long lnum = SOURCING_LNUM;
1951
1952 // find_ex_command() will consider a variable name an expression, assuming
1953 // that something follows on the next line. Check that something actually
1954 // follows, otherwise it's probably a misplaced command.
1955 name_only = cmd_is_name_only(arg);
1956
1957 if (compile_expr0(&p, cctx) == FAIL)
1958 return NULL;
1959
1960 if (name_only && lnum == SOURCING_LNUM)
1961 {
1962 semsg(_(e_expression_without_effect_str), arg);
1963 return NULL;
1964 }
1965
1966 // drop the result
1967 generate_instr_drop(cctx, ISN_DROP, 1);
1968
1969 return skipwhite(p);
1970}
1971
1972/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001973 * Get the local variable index for deferred function calls.
1974 * Reserve it when not done already.
1975 * Returns zero for failure.
1976 */
1977 int
1978get_defer_var_idx(cctx_T *cctx)
1979{
1980 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1981 + cctx->ctx_ufunc->uf_dfunc_idx;
1982 if (dfunc->df_defer_var_idx == 0)
1983 {
1984 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1985 TRUE, &t_list_any);
1986 if (lvar == NULL)
1987 return 0;
1988 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1989 }
1990 return dfunc->df_defer_var_idx;
1991}
1992
1993/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001994 * Compile "defer func(arg)".
1995 */
1996 char_u *
1997compile_defer(char_u *arg_start, cctx_T *cctx)
1998{
Bram Moolenaar16900322022-09-08 19:51:45 +01001999 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002000 char_u *arg = arg_start;
2001 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01002002 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002003 type_T *type;
2004 int func_idx;
2005
2006 // Get a funcref for the function name.
2007 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01002008 paren = vim_strchr(arg, '(');
2009 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002010 {
2011 semsg(_(e_missing_parenthesis_str), arg);
2012 return NULL;
2013 }
Bram Moolenaar16900322022-09-08 19:51:45 +01002014 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002015 func_idx = find_internal_func(arg);
2016 if (func_idx >= 0)
2017 // TODO: better type
2018 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
2019 &t_func_any, FALSE);
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02002020 else if (compile_expr0(&arg, cctx) == FAIL)
2021 return NULL;
Bram Moolenaar16900322022-09-08 19:51:45 +01002022 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002023
2024 // check for function type
Yegappan Lakshmanana185a312023-12-16 14:36:08 +01002025 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002026 {
Yegappan Lakshmanana185a312023-12-16 14:36:08 +01002027 type = get_type_on_stack(cctx, 0);
2028 if (type->tt_type != VAR_FUNC)
2029 {
2030 emsg(_(e_function_name_required));
2031 return NULL;
2032 }
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002033 }
2034
2035 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01002036 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002037 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
2038 return NULL;
2039
Yegappan Lakshmanana185a312023-12-16 14:36:08 +01002040 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar16900322022-09-08 19:51:45 +01002041 {
Yegappan Lakshmanana185a312023-12-16 14:36:08 +01002042 if (func_idx >= 0)
2043 {
2044 type2_T *argtypes = NULL;
2045 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
Bram Moolenaar16900322022-09-08 19:51:45 +01002046
Yegappan Lakshmanana185a312023-12-16 14:36:08 +01002047 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
2048 &argtypes, shuffled_argtypes) == FAIL)
2049 return NULL;
2050 }
2051 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
2052 arg_start) == FAIL)
2053 return NULL;
2054
2055 defer_var_idx = get_defer_var_idx(cctx);
2056 if (defer_var_idx == 0)
2057 return NULL;
2058 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL)
Bram Moolenaar16900322022-09-08 19:51:45 +01002059 return NULL;
2060 }
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002061
2062 return skipwhite(arg);
2063}
2064
2065/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002066 * compile "echo expr"
2067 * compile "echomsg expr"
2068 * compile "echoerr expr"
2069 * compile "echoconsole expr"
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002070 * compile "echowindow expr" - may have cmd_count set
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002071 * compile "execute expr"
2072 */
2073 char_u *
Bram Moolenaar9b994112022-12-25 15:59:25 +00002074compile_mult_expr(
2075 char_u *arg,
2076 int cmdidx,
2077 long cmd_count UNUSED,
2078 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002079{
2080 char_u *p = arg;
2081 char_u *prev = arg;
2082 char_u *expr_start;
2083 int count = 0;
2084 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002085 type_T *type;
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002086 int r = OK;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002087
2088 for (;;)
2089 {
2090 if (ends_excmd2(prev, p))
2091 break;
2092 expr_start = p;
2093 if (compile_expr0(&p, cctx) == FAIL)
2094 return NULL;
2095
2096 if (cctx->ctx_skip != SKIP_YES)
2097 {
2098 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00002099 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002100 if (type->tt_type == VAR_VOID)
2101 {
2102 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
2103 return NULL;
2104 }
2105 }
2106
2107 ++count;
2108 prev = p;
2109 p = skipwhite(p);
2110 }
2111
2112 if (count > 0)
2113 {
2114 long save_lnum = cctx->ctx_lnum;
2115
2116 // Use the line number where the command started.
2117 cctx->ctx_lnum = start_ctx_lnum;
2118
2119 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002120 r = generate_ECHO(cctx, cmdidx == CMD_echo, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002121 else if (cmdidx == CMD_execute)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002122 r = generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002123 else if (cmdidx == CMD_echomsg)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002124 r = generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002125#ifdef HAS_MESSAGE_WINDOW
2126 else if (cmdidx == CMD_echowindow)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002127 r = generate_ECHOWINDOW(cctx, count, cmd_count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002128#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002129 else if (cmdidx == CMD_echoconsole)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002130 r = generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002131 else
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002132 r = generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002133
2134 cctx->ctx_lnum = save_lnum;
2135 }
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002136 return r == OK ? p : NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002137}
2138
2139/*
2140 * If "eap" has a range that is not a constant generate an ISN_RANGE
2141 * instruction to compute it and return OK.
2142 * Otherwise return FAIL, the caller must deal with any range.
2143 */
2144 static int
2145compile_variable_range(exarg_T *eap, cctx_T *cctx)
2146{
2147 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
2148 char_u *p = skipdigits(eap->cmd);
2149
2150 if (p == range_end)
2151 return FAIL;
2152 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
2153}
2154
2155/*
2156 * :put r
2157 * :put ={expr}
2158 */
2159 char_u *
2160compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
2161{
2162 char_u *line = arg;
2163 linenr_T lnum;
2164 char *errormsg;
2165 int above = eap->forceit;
2166
2167 eap->regname = *line;
2168
2169 if (eap->regname == '=')
2170 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002171 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002172
2173 if (compile_expr0(&p, cctx) == FAIL)
2174 return NULL;
2175 line = p;
2176 }
2177 else if (eap->regname != NUL)
2178 ++line;
2179
2180 if (compile_variable_range(eap, cctx) == OK)
2181 {
2182 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2183 }
2184 else
2185 {
2186 // Either no range or a number.
2187 // "errormsg" will not be set because the range is ADDR_LINES.
2188 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2189 // cannot happen
2190 return NULL;
2191 if (eap->addr_count == 0)
2192 lnum = -1;
2193 else
2194 lnum = eap->line2;
2195 if (above)
2196 --lnum;
2197 }
2198
2199 generate_PUT(cctx, eap->regname, lnum);
2200 return line;
2201}
2202
2203/*
2204 * A command that is not compiled, execute with legacy code.
2205 */
2206 char_u *
2207compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2208{
2209 char_u *line = line_arg;
2210 char_u *p;
2211 int has_expr = FALSE;
2212 char_u *nextcmd = (char_u *)"";
2213 char_u *tofree = NULL;
2214 char_u *cmd_arg = NULL;
2215
2216 if (cctx->ctx_skip == SKIP_YES)
2217 goto theend;
2218
2219 // If there was a prececing command modifier, drop it and include it in the
2220 // EXEC command.
2221 if (cctx->ctx_has_cmdmod)
2222 {
2223 garray_T *instr = &cctx->ctx_instr;
2224 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2225
2226 if (isn->isn_type == ISN_CMDMOD)
2227 {
2228 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2229 ->cmod_filter_regmatch.regprog);
2230 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2231 --instr->ga_len;
2232 cctx->ctx_has_cmdmod = FALSE;
2233 }
2234 }
2235
2236 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2237 {
2238 long argt = eap->argt;
2239 int usefilter = FALSE;
2240
2241 has_expr = argt & (EX_XFILE | EX_EXPAND);
2242
2243 // If the command can be followed by a bar, find the bar and truncate
2244 // it, so that the following command can be compiled.
2245 // The '|' is overwritten with a NUL, it is put back below.
2246 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2247 && *eap->arg == '!')
2248 // :w !filter or :r !filter or :r! filter
2249 usefilter = TRUE;
2250 if ((argt & EX_TRLBAR) && !usefilter)
2251 {
2252 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002253 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002254 if (eap->nextcmd != NULL)
2255 nextcmd = eap->nextcmd;
2256 }
2257 else if (eap->cmdidx == CMD_wincmd)
2258 {
2259 p = eap->arg;
2260 if (*p != NUL)
2261 ++p;
2262 if (*p == 'g' || *p == Ctrl_G)
2263 ++p;
2264 p = skipwhite(p);
2265 if (*p == '|')
2266 {
2267 *p = NUL;
2268 nextcmd = p + 1;
2269 }
2270 }
2271 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2272 {
2273 // If there is a trailing '{' read lines until the '}'
2274 p = eap->arg + STRLEN(eap->arg) - 1;
2275 while (p > eap->arg && VIM_ISWHITE(*p))
2276 --p;
2277 if (*p == '{')
2278 {
2279 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002280 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002281 int start_lnum = SOURCING_LNUM;
2282
2283 CLEAR_FIELD(ea);
2284 ea.arg = eap->arg;
2285 fill_exarg_from_cctx(&ea, cctx);
2286 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2287 if (tofree != NULL)
2288 {
2289 *p = NUL;
2290 line = concat_str(line, tofree);
2291 if (line == NULL)
2292 goto theend;
2293 vim_free(tofree);
2294 tofree = line;
2295 SOURCING_LNUM = start_lnum;
2296 }
2297 }
2298 }
2299 }
2300
2301 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2302 {
2303 // expand filename in "syntax include [@group] filename"
2304 has_expr = TRUE;
2305 eap->arg = skipwhite(eap->arg + 7);
2306 if (*eap->arg == '@')
2307 eap->arg = skiptowhite(eap->arg);
2308 }
2309
2310 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2311 && STRLEN(eap->arg) > 4)
2312 {
2313 int delim = *eap->arg;
2314
2315 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2316 if (*p == delim)
2317 cmd_arg = p + 1;
2318 }
2319
2320 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2321 cmd_arg = eap->arg;
2322
2323 if (cmd_arg != NULL)
2324 {
2325 exarg_T nea;
2326
2327 CLEAR_FIELD(nea);
2328 nea.cmd = cmd_arg;
2329 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2330 if (nea.cmdidx < CMD_SIZE)
2331 {
2332 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2333 if (has_expr)
2334 eap->arg = skiptowhite(eap->arg);
2335 }
2336 }
2337
2338 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2339 {
2340 int count = 0;
2341 char_u *start = skipwhite(line);
2342
2343 // :cmd xxx`=expr1`yyy`=expr2`zzz
2344 // PUSHS ":cmd xxx"
2345 // eval expr1
2346 // PUSHS "yyy"
2347 // eval expr2
2348 // PUSHS "zzz"
2349 // EXECCONCAT 5
2350 for (;;)
2351 {
2352 if (p > start)
2353 {
2354 char_u *val = vim_strnsave(start, p - start);
2355
2356 generate_PUSHS(cctx, &val);
2357 ++count;
2358 }
2359 p += 2;
2360 if (compile_expr0(&p, cctx) == FAIL)
2361 return NULL;
2362 may_generate_2STRING(-1, TRUE, cctx);
2363 ++count;
2364 p = skipwhite(p);
2365 if (*p != '`')
2366 {
2367 emsg(_(e_missing_backtick));
2368 return NULL;
2369 }
2370 start = p + 1;
2371
2372 p = (char_u *)strstr((char *)start, "`=");
2373 if (p == NULL)
2374 {
2375 if (*skipwhite(start) != NUL)
2376 {
2377 char_u *val = vim_strsave(start);
2378
2379 generate_PUSHS(cctx, &val);
2380 ++count;
2381 }
2382 break;
2383 }
2384 }
2385 generate_EXECCONCAT(cctx, count);
2386 }
2387 else
2388 generate_EXEC_copy(cctx, ISN_EXEC, line);
2389
2390theend:
2391 if (*nextcmd != NUL)
2392 {
2393 // the parser expects a pointer to the bar, put it back
2394 --nextcmd;
2395 *nextcmd = '|';
2396 }
2397 vim_free(tofree);
2398
2399 return nextcmd;
2400}
2401
2402/*
2403 * A script command with heredoc, e.g.
2404 * ruby << EOF
2405 * command
2406 * EOF
2407 * Has been turned into one long line with NL characters by
2408 * get_function_body():
2409 * ruby << EOF<NL> command<NL>EOF
2410 */
2411 char_u *
2412compile_script(char_u *line, cctx_T *cctx)
2413{
2414 if (cctx->ctx_skip != SKIP_YES)
2415 {
2416 isn_T *isn;
2417
2418 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2419 return NULL;
2420 isn->isn_arg.string = vim_strsave(line);
2421 }
2422 return (char_u *)"";
2423}
2424
2425
2426/*
2427 * :s/pat/repl/
2428 */
2429 char_u *
2430compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2431{
2432 char_u *cmd = eap->arg;
2433 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2434
2435 if (expr != NULL)
2436 {
2437 int delimiter = *cmd++;
2438
2439 // There is a \=expr, find it in the substitute part.
2440 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2441 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2442 {
2443 garray_T save_ga = cctx->ctx_instr;
2444 char_u *end;
2445 int expr_res;
2446 int trailing_error;
2447 int instr_count;
2448 isn_T *instr;
2449 isn_T *isn;
2450
2451 cmd += 3;
2452 end = skip_substitute(cmd, delimiter);
2453
2454 // Temporarily reset the list of instructions so that the jump
2455 // labels are correct.
2456 cctx->ctx_instr.ga_len = 0;
2457 cctx->ctx_instr.ga_maxlen = 0;
2458 cctx->ctx_instr.ga_data = NULL;
2459 expr_res = compile_expr0(&cmd, cctx);
2460 if (end[-1] == NUL)
2461 end[-1] = delimiter;
2462 cmd = skipwhite(cmd);
2463 trailing_error = *cmd != delimiter && *cmd != NUL;
2464
2465 if (expr_res == FAIL || trailing_error
2466 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2467 {
2468 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002469 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002470 clear_instr_ga(&cctx->ctx_instr);
2471 cctx->ctx_instr = save_ga;
2472 return NULL;
2473 }
2474
2475 // Move the generated instructions into the ISN_SUBSTITUTE
2476 // instructions, then restore the list of instructions before
2477 // adding the ISN_SUBSTITUTE instruction.
2478 instr_count = cctx->ctx_instr.ga_len;
2479 instr = cctx->ctx_instr.ga_data;
2480 instr[instr_count].isn_type = ISN_FINISH;
2481
2482 cctx->ctx_instr = save_ga;
2483 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2484 {
2485 int idx;
2486
2487 for (idx = 0; idx < instr_count; ++idx)
2488 delete_instr(instr + idx);
2489 vim_free(instr);
2490 return NULL;
2491 }
2492 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2493 isn->isn_arg.subs.subs_instr = instr;
2494
2495 // skip over flags
2496 if (*end == '&')
2497 ++end;
2498 while (ASCII_ISALPHA(*end) || *end == '#')
2499 ++end;
2500 return end;
2501 }
2502 }
2503
2504 return compile_exec(arg, eap, cctx);
2505}
2506
2507 char_u *
2508compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2509{
2510 char_u *arg = eap->arg;
2511 lhs_T *lhs = &cctx->ctx_redir_lhs;
2512
2513 if (lhs->lhs_name != NULL)
2514 {
2515 if (STRNCMP(arg, "END", 3) == 0)
2516 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002517 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002518 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002519 if (lhs->lhs_append)
2520 {
2521 // First load the current variable value.
2522 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002523 cctx) == FAIL)
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002524 return NULL;
2525 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002526
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002527 // Gets the redirected text and put it on the stack, then store
2528 // it in the variable.
2529 generate_instr_type(cctx, ISN_REDIREND, &t_string);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002530
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002531 if (lhs->lhs_append)
2532 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002533
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002534 if (lhs->lhs_has_index)
2535 {
2536 // Use the info in "lhs" to store the value at the index in
2537 // the list or dict.
2538 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002539 &t_string, cctx) == FAIL)
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002540 return NULL;
2541 }
2542 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002543 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002544
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002545 VIM_CLEAR(lhs->lhs_name);
2546 VIM_CLEAR(lhs->lhs_whole);
2547 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002548 return arg + 3;
2549 }
2550 emsg(_(e_cannot_nest_redir));
2551 return NULL;
2552 }
2553
2554 if (arg[0] == '=' && arg[1] == '>')
2555 {
2556 int append = FALSE;
2557
2558 // redirect to a variable is compiled
2559 arg += 2;
2560 if (*arg == '>')
2561 {
2562 ++arg;
2563 append = TRUE;
2564 }
2565 arg = skipwhite(arg);
2566
2567 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002568 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002569 return NULL;
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002570 if (need_type(&t_string, lhs->lhs_member_type, FALSE,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002571 -1, 0, cctx, FALSE, FALSE) == FAIL)
2572 return NULL;
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002573 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002574 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002575 VIM_CLEAR(lhs->lhs_name);
2576 }
2577 else
2578 {
2579 generate_instr(cctx, ISN_REDIRSTART);
2580 lhs->lhs_append = append;
2581 if (lhs->lhs_has_index)
2582 {
2583 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2584 if (lhs->lhs_whole == NULL)
2585 return NULL;
2586 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002587 }
2588
2589 return arg + lhs->lhs_varlen_total;
2590 }
2591
2592 // other redirects are handled like at script level
2593 return compile_exec(line, eap, cctx);
2594}
2595
2596#if defined(FEAT_QUICKFIX) || defined(PROTO)
2597 char_u *
2598compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2599{
2600 isn_T *isn;
2601 char_u *p;
2602
2603 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2604 if (isn == NULL)
2605 return NULL;
2606 isn->isn_arg.number = eap->cmdidx;
2607
2608 p = eap->arg;
2609 if (compile_expr0(&p, cctx) == FAIL)
2610 return NULL;
2611
2612 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2613 if (isn == NULL)
2614 return NULL;
2615 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2616 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2617 return NULL;
2618 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2619 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2620 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2621
2622 return p;
2623}
2624#endif
2625
2626/*
2627 * Compile "return [expr]".
2628 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2629 */
2630 char_u *
2631compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2632{
2633 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002634 type_T *stack_type;
2635
mityu500c4442022-12-02 18:12:05 +00002636 if (*p != NUL && *p != '|' && *p != '\n'
2637 && (legacy || !vim9_comment_start(p)))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002638 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002639 // For a lambda, "return expr" is always used, also when "expr" results
2640 // in a void.
2641 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2642 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002643 {
2644 emsg(_(e_returning_value_in_function_without_return_type));
2645 return NULL;
2646 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002647 if (legacy)
2648 {
2649 int save_flags = cmdmod.cmod_flags;
2650
2651 generate_LEGACY_EVAL(cctx, p);
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002652 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, FALSE, -1,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002653 0, cctx, FALSE, FALSE) == FAIL)
2654 return NULL;
2655 cmdmod.cmod_flags |= CMOD_LEGACY;
2656 (void)skip_expr(&p, NULL);
2657 cmdmod.cmod_flags = save_flags;
2658 }
2659 else
2660 {
2661 // compile return argument into instructions
2662 if (compile_expr0(&p, cctx) == FAIL)
2663 return NULL;
2664 }
2665
2666 if (cctx->ctx_skip != SKIP_YES)
2667 {
2668 // "check_return_type" with uf_ret_type set to &t_unknown is used
2669 // for an inline function without a specified return type. Set the
2670 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002671 stack_type = get_type_on_stack(cctx, 0);
Ernie Raelb077b582023-12-14 20:11:44 +01002672 if (check_type_is_value(stack_type) == FAIL)
2673 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002674 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002675 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002676 || (!check_return_type
2677 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2678 {
2679 cctx->ctx_ufunc->uf_ret_type = stack_type;
2680 }
2681 else
2682 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002683 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, FALSE,
2684 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002685 return NULL;
2686 }
2687 }
2688 }
2689 else
2690 {
2691 // "check_return_type" cannot be TRUE, only used for a lambda which
2692 // always has an argument.
2693 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2694 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2695 {
2696 emsg(_(e_missing_return_value));
2697 return NULL;
2698 }
2699
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02002700 if (IS_CONSTRUCTOR_METHOD(cctx->ctx_ufunc))
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002701 {
2702 // For a class new() constructor, return an object of the class.
2703 generate_instr(cctx, ISN_RETURN_OBJECT);
2704 cctx->ctx_ufunc->uf_ret_type =
2705 &cctx->ctx_ufunc->uf_class->class_object_type;
2706 }
2707 else
2708 // No argument, return zero.
2709 generate_PUSHNR(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002710 }
2711
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002712 // may need ENDLOOP when inside a :for or :while loop
2713 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2714
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002715 // Undo any command modifiers.
2716 generate_undo_cmdmods(cctx);
2717
2718 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2719 return NULL;
2720
2721 // "return val | endif" is possible
2722 return skipwhite(p);
2723}
2724
2725/*
2726 * Check if the separator for a :global or :substitute command is OK.
2727 */
2728 int
2729check_global_and_subst(char_u *cmd, char_u *arg)
2730{
2731 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2732 {
2733 semsg(_(e_separator_not_supported_str), arg);
2734 return FAIL;
2735 }
2736 if (VIM_ISWHITE(cmd[1]))
2737 {
2738 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2739 return FAIL;
2740 }
2741 return OK;
2742}
2743
2744
2745#endif // defined(FEAT_EVAL)