blob: d209a16640486a0d13e9fd7ee78a1efd454927f2 [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".
60 */
61 static void
62unwind_locals(cctx_T *cctx, int new_top)
63{
64 if (cctx->ctx_locals.ga_len > new_top)
65 {
66 int idx;
67 lvar_T *lvar;
68
69 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
70 {
71 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
72 vim_free(lvar->lv_name);
73 }
74 }
75 cctx->ctx_locals.ga_len = new_top;
76}
77
78/*
79 * Free all local variables.
80 */
81 void
82free_locals(cctx_T *cctx)
83{
84 unwind_locals(cctx, 0);
85 ga_clear(&cctx->ctx_locals);
86}
87
88
89/*
90 * Check if "name" can be "unlet".
91 */
92 int
93check_vim9_unlet(char_u *name)
94{
Bram Moolenaardbdd16b2022-08-14 21:46:07 +010095 if (*name == NUL)
96 {
97 semsg(_(e_argument_required_for_str), "unlet");
98 return FAIL;
99 }
100
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000101 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
102 {
103 // "unlet s:var" is allowed in legacy script.
104 if (*name == 's' && !script_is_vim9())
105 return OK;
106 semsg(_(e_cannot_unlet_str), name);
107 return FAIL;
108 }
109 return OK;
110}
111
112/*
113 * Callback passed to ex_unletlock().
114 */
115 static int
116compile_unlet(
117 lval_T *lvp,
118 char_u *name_end,
119 exarg_T *eap,
120 int deep UNUSED,
121 void *coookie)
122{
123 cctx_T *cctx = coookie;
124 char_u *p = lvp->ll_name;
125 int cc = *name_end;
126 int ret = OK;
127
128 if (cctx->ctx_skip == SKIP_YES)
129 return OK;
130
131 *name_end = NUL;
132 if (*p == '$')
133 {
134 // :unlet $ENV_VAR
135 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
136 }
137 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
138 {
139 lhs_T lhs;
140
141 // This is similar to assigning: lookup the list/dict, compile the
142 // idx/key. Then instead of storing the value unlet the item.
143 // unlet {list}[idx]
144 // unlet {dict}[key] dict.key
145 //
146 // Figure out the LHS type and other properties.
147 //
Bram Moolenaar97f8c102022-04-02 19:43:57 +0100148 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, FALSE, 0, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000149
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000150 // Use the info in "lhs" to unlet the item at the index in the
151 // list or dict.
152 if (ret == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000153 {
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000154 if (!lhs.lhs_has_index)
155 {
156 semsg(_(e_cannot_unlet_imported_item_str), p);
157 ret = FAIL;
158 }
159 else
160 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000161 }
162
163 vim_free(lhs.lhs_name);
164 }
165 else if (check_vim9_unlet(p) == FAIL)
166 {
167 ret = FAIL;
168 }
169 else
170 {
171 // Normal name. Only supports g:, w:, t: and b: namespaces.
172 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
173 }
174
175 *name_end = cc;
176 return ret;
177}
178
179/*
180 * Callback passed to ex_unletlock().
181 */
182 static int
183compile_lock_unlock(
184 lval_T *lvp,
185 char_u *name_end,
186 exarg_T *eap,
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000187 int deep,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000188 void *coookie)
189{
190 cctx_T *cctx = coookie;
191 int cc = *name_end;
192 char_u *p = lvp->ll_name;
193 int ret = OK;
194 size_t len;
195 char_u *buf;
196 isntype_T isn = ISN_EXEC;
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100197 char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000198
199 if (cctx->ctx_skip == SKIP_YES)
200 return OK;
201
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100202 if (*p == NUL)
203 {
204 semsg(_(e_argument_required_for_str), cmd);
205 return FAIL;
206 }
207
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000208 // Cannot use :lockvar and :unlockvar on local variables.
209 if (p[1] != ':')
210 {
211 char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
212
213 if (lookup_local(p, end - p, NULL, cctx) == OK)
214 {
215 char_u *s = p;
216
217 if (*end != '.' && *end != '[')
218 {
219 emsg(_(e_cannot_lock_unlock_local_variable));
220 return FAIL;
221 }
222
223 // For "d.member" put the local variable on the stack, it will be
224 // passed to ex_lockvar() indirectly.
225 if (compile_load(&s, end, cctx, FALSE, FALSE) == FAIL)
226 return FAIL;
227 isn = ISN_LOCKUNLOCK;
228 }
229 }
230
231 // Checking is done at runtime.
232 *name_end = NUL;
233 len = name_end - p + 20;
234 buf = alloc(len);
235 if (buf == NULL)
236 ret = FAIL;
237 else
238 {
Bram Moolenaare939f5e2022-01-26 21:32:59 +0000239 if (deep < 0)
240 vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
241 else
242 vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000243 ret = generate_EXEC_copy(cctx, isn, buf);
244
245 vim_free(buf);
246 *name_end = cc;
247 }
248 return ret;
249}
250
251/*
252 * compile "unlet var", "lock var" and "unlock var"
253 * "arg" points to "var".
254 */
255 char_u *
256compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
257{
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000258 int deep = 0;
259 char_u *p = arg;
260
261 if (eap->cmdidx != CMD_unlet)
262 {
263 if (eap->forceit)
264 deep = -1;
265 else if (vim_isdigit(*p))
266 {
267 deep = getdigits(&p);
268 p = skipwhite(p);
269 }
270 else
271 deep = 2;
272 }
273
274 ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000275 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
276 cctx);
277 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
278}
279
280/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100281 * Generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
282 * "funcref_idx" is used for JUMP_WHILE_FALSE
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000283 */
284 static int
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100285compile_jump_to_end(
286 endlabel_T **el,
287 jumpwhen_T when,
288 int funcref_idx,
289 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000290{
291 garray_T *instr = &cctx->ctx_instr;
292 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
293
294 if (endlabel == NULL)
295 return FAIL;
296 endlabel->el_next = *el;
297 *el = endlabel;
298 endlabel->el_end_label = instr->ga_len;
299
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100300 if (when == JUMP_WHILE_FALSE)
301 generate_WHILE(cctx, funcref_idx);
302 else
303 generate_JUMP(cctx, when, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000304 return OK;
305}
306
307 static void
308compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
309{
310 garray_T *instr = &cctx->ctx_instr;
311
312 while (*el != NULL)
313 {
314 endlabel_T *cur = (*el);
315 isn_T *isn;
316
317 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
318 isn->isn_arg.jump.jump_where = jump_where;
319 *el = cur->el_next;
320 vim_free(cur);
321 }
322}
323
324 static void
325compile_free_jump_to_end(endlabel_T **el)
326{
327 while (*el != NULL)
328 {
329 endlabel_T *cur = (*el);
330
331 *el = cur->el_next;
332 vim_free(cur);
333 }
334}
335
336/*
337 * Create a new scope and set up the generic items.
338 */
339 static scope_T *
340new_scope(cctx_T *cctx, scopetype_T type)
341{
342 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
343
344 if (scope == NULL)
345 return NULL;
346 scope->se_outer = cctx->ctx_scope;
347 cctx->ctx_scope = scope;
348 scope->se_type = type;
349 scope->se_local_count = cctx->ctx_locals.ga_len;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100350 if (scope->se_outer != NULL)
351 scope->se_loop_depth = scope->se_outer->se_loop_depth;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000352 return scope;
353}
354
355/*
356 * Free the current scope and go back to the outer scope.
357 */
358 void
359drop_scope(cctx_T *cctx)
360{
361 scope_T *scope = cctx->ctx_scope;
362
363 if (scope == NULL)
364 {
365 iemsg("calling drop_scope() without a scope");
366 return;
367 }
368 cctx->ctx_scope = scope->se_outer;
369 switch (scope->se_type)
370 {
371 case IF_SCOPE:
372 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
373 case FOR_SCOPE:
374 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
375 case WHILE_SCOPE:
376 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
377 case TRY_SCOPE:
378 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
379 case NO_SCOPE:
380 case BLOCK_SCOPE:
381 break;
382 }
383 vim_free(scope);
384}
385
386 static int
387misplaced_cmdmod(cctx_T *cctx)
388{
389 garray_T *instr = &cctx->ctx_instr;
390
391 if (cctx->ctx_has_cmdmod
392 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
393 == ISN_CMDMOD)
394 {
395 emsg(_(e_misplaced_command_modifier));
396 return TRUE;
397 }
398 return FALSE;
399}
400
401/*
402 * compile "if expr"
403 *
404 * "if expr" Produces instructions:
405 * EVAL expr Push result of "expr"
406 * JUMP_IF_FALSE end
407 * ... body ...
408 * end:
409 *
410 * "if expr | else" Produces instructions:
411 * EVAL expr Push result of "expr"
412 * JUMP_IF_FALSE else
413 * ... body ...
414 * JUMP_ALWAYS end
415 * else:
416 * ... body ...
417 * end:
418 *
419 * "if expr1 | elseif expr2 | else" Produces instructions:
420 * EVAL expr Push result of "expr"
421 * JUMP_IF_FALSE elseif
422 * ... body ...
423 * JUMP_ALWAYS end
424 * elseif:
425 * EVAL expr Push result of "expr"
426 * JUMP_IF_FALSE else
427 * ... body ...
428 * JUMP_ALWAYS end
429 * else:
430 * ... body ...
431 * end:
432 */
433 char_u *
434compile_if(char_u *arg, cctx_T *cctx)
435{
436 char_u *p = arg;
437 garray_T *instr = &cctx->ctx_instr;
438 int instr_count = instr->ga_len;
439 scope_T *scope;
440 skip_T skip_save = cctx->ctx_skip;
441 ppconst_T ppconst;
442
443 CLEAR_FIELD(ppconst);
444 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
445 {
446 clear_ppconst(&ppconst);
447 return NULL;
448 }
449 if (!ends_excmd2(arg, skipwhite(p)))
450 {
Bram Moolenaar74409f62022-01-01 15:58:22 +0000451 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000452 return NULL;
453 }
454 if (cctx->ctx_skip == SKIP_YES)
455 clear_ppconst(&ppconst);
456 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
457 {
458 int error = FALSE;
459 int v;
460
461 // The expression results in a constant.
462 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
463 clear_ppconst(&ppconst);
464 if (error)
465 return NULL;
466 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
467 }
468 else
469 {
470 // Not a constant, generate instructions for the expression.
471 cctx->ctx_skip = SKIP_UNKNOWN;
472 if (generate_ppconst(cctx, &ppconst) == FAIL)
473 return NULL;
474 if (bool_on_stack(cctx) == FAIL)
475 return NULL;
476 }
477
478 // CMDMOD_REV must come before the jump
479 generate_undo_cmdmods(cctx);
480
481 scope = new_scope(cctx, IF_SCOPE);
482 if (scope == NULL)
483 return NULL;
484 scope->se_skip_save = skip_save;
485 // "is_had_return" will be reset if any block does not end in :return
486 scope->se_u.se_if.is_had_return = TRUE;
487
488 if (cctx->ctx_skip == SKIP_UNKNOWN)
489 {
490 // "where" is set when ":elseif", "else" or ":endif" is found
491 scope->se_u.se_if.is_if_label = instr->ga_len;
492 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
493 }
494 else
495 scope->se_u.se_if.is_if_label = -1;
496
497#ifdef FEAT_PROFILE
498 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
499 && skip_save != SKIP_YES)
500 {
501 // generated a profile start, need to generate a profile end, since it
502 // won't be done after returning
503 cctx->ctx_skip = SKIP_NOT;
504 generate_instr(cctx, ISN_PROF_END);
505 cctx->ctx_skip = SKIP_YES;
506 }
507#endif
508
509 return p;
510}
511
512 char_u *
513compile_elseif(char_u *arg, cctx_T *cctx)
514{
515 char_u *p = arg;
516 garray_T *instr = &cctx->ctx_instr;
517 int instr_count;
518 isn_T *isn;
519 scope_T *scope = cctx->ctx_scope;
520 ppconst_T ppconst;
521 skip_T save_skip = cctx->ctx_skip;
522
523 if (scope == NULL || scope->se_type != IF_SCOPE)
524 {
525 emsg(_(e_elseif_without_if));
526 return NULL;
527 }
528 unwind_locals(cctx, scope->se_local_count);
529 if (!cctx->ctx_had_return)
530 scope->se_u.se_if.is_had_return = FALSE;
531
532 if (cctx->ctx_skip == SKIP_NOT)
533 {
534 // previous block was executed, this one and following will not
535 cctx->ctx_skip = SKIP_YES;
536 scope->se_u.se_if.is_seen_skip_not = TRUE;
537 }
538 if (scope->se_u.se_if.is_seen_skip_not)
539 {
540 // A previous block was executed, skip over expression and bail out.
541 // Do not count the "elseif" for profiling and cmdmod
542 instr->ga_len = current_instr_idx(cctx);
543
544 skip_expr_cctx(&p, cctx);
545 return p;
546 }
547
548 if (cctx->ctx_skip == SKIP_UNKNOWN)
549 {
550 int moved_cmdmod = FALSE;
551 int saved_debug = FALSE;
552 isn_T debug_isn;
553
554 // Move any CMDMOD instruction to after the jump
555 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
556 {
557 if (GA_GROW_FAILS(instr, 1))
558 return NULL;
559 ((isn_T *)instr->ga_data)[instr->ga_len] =
560 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
561 --instr->ga_len;
562 moved_cmdmod = TRUE;
563 }
564
565 // Remove the already generated ISN_DEBUG, it is written below the
566 // ISN_FOR instruction.
567 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
568 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
569 .isn_type == ISN_DEBUG)
570 {
571 --instr->ga_len;
572 debug_isn = ((isn_T *)instr->ga_data)[instr->ga_len];
573 saved_debug = TRUE;
574 }
575
576 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100577 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000578 return NULL;
579 // previous "if" or "elseif" jumps here
580 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
581 isn->isn_arg.jump.jump_where = instr->ga_len;
582
583 if (moved_cmdmod)
584 ++instr->ga_len;
585
586 if (saved_debug)
587 {
588 // move the debug instruction here
589 if (GA_GROW_FAILS(instr, 1))
590 return NULL;
591 ((isn_T *)instr->ga_data)[instr->ga_len] = debug_isn;
592 ++instr->ga_len;
593 }
594 }
595
596 // compile "expr"; if we know it evaluates to FALSE skip the block
597 CLEAR_FIELD(ppconst);
598 if (cctx->ctx_skip == SKIP_YES)
599 {
600 cctx->ctx_skip = SKIP_UNKNOWN;
601#ifdef FEAT_PROFILE
602 if (cctx->ctx_compile_type == CT_PROFILE)
603 // the previous block was skipped, need to profile this line
604 generate_instr(cctx, ISN_PROF_START);
605#endif
606 if (cctx->ctx_compile_type == CT_DEBUG)
607 // the previous block was skipped, may want to debug this line
608 generate_instr_debug(cctx);
609 }
610
611 instr_count = instr->ga_len;
612 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
613 {
614 clear_ppconst(&ppconst);
615 return NULL;
616 }
617 cctx->ctx_skip = save_skip;
618 if (!ends_excmd2(arg, skipwhite(p)))
619 {
620 clear_ppconst(&ppconst);
Bram Moolenaar74409f62022-01-01 15:58:22 +0000621 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000622 return NULL;
623 }
624 if (scope->se_skip_save == SKIP_YES)
625 clear_ppconst(&ppconst);
626 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
627 {
628 int error = FALSE;
629 int v;
630
631 // The expression result is a constant.
632 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
633 if (error)
634 {
635 clear_ppconst(&ppconst);
636 return NULL;
637 }
638 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
639 clear_ppconst(&ppconst);
640 scope->se_u.se_if.is_if_label = -1;
641 }
642 else
643 {
644 // Not a constant, generate instructions for the expression.
645 cctx->ctx_skip = SKIP_UNKNOWN;
646 if (generate_ppconst(cctx, &ppconst) == FAIL)
647 return NULL;
648 if (bool_on_stack(cctx) == FAIL)
649 return NULL;
650
651 // CMDMOD_REV must come before the jump
652 generate_undo_cmdmods(cctx);
653
654 // "where" is set when ":elseif", "else" or ":endif" is found
655 scope->se_u.se_if.is_if_label = instr->ga_len;
656 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
657 }
658
659 return p;
660}
661
662 char_u *
663compile_else(char_u *arg, cctx_T *cctx)
664{
665 char_u *p = arg;
666 garray_T *instr = &cctx->ctx_instr;
667 isn_T *isn;
668 scope_T *scope = cctx->ctx_scope;
669
670 if (scope == NULL || scope->se_type != IF_SCOPE)
671 {
672 emsg(_(e_else_without_if));
673 return NULL;
674 }
675 unwind_locals(cctx, scope->se_local_count);
676 if (!cctx->ctx_had_return)
677 scope->se_u.se_if.is_had_return = FALSE;
678 scope->se_u.se_if.is_seen_else = TRUE;
679
680#ifdef FEAT_PROFILE
681 if (cctx->ctx_compile_type == CT_PROFILE)
682 {
683 if (cctx->ctx_skip == SKIP_NOT
684 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
685 .isn_type == ISN_PROF_START)
686 // the previous block was executed, do not count "else" for
687 // profiling
688 --instr->ga_len;
689 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
690 {
691 // the previous block was not executed, this one will, do count the
692 // "else" for profiling
693 cctx->ctx_skip = SKIP_NOT;
694 generate_instr(cctx, ISN_PROF_END);
695 generate_instr(cctx, ISN_PROF_START);
696 cctx->ctx_skip = SKIP_YES;
697 }
698 }
699#endif
700
701 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
702 {
703 // jump from previous block to the end, unless the else block is empty
704 if (cctx->ctx_skip == SKIP_UNKNOWN)
705 {
706 if (!cctx->ctx_had_return
707 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100708 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000709 return NULL;
710 }
711
712 if (cctx->ctx_skip == SKIP_UNKNOWN)
713 {
714 if (scope->se_u.se_if.is_if_label >= 0)
715 {
716 // previous "if" or "elseif" jumps here
717 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
718 isn->isn_arg.jump.jump_where = instr->ga_len;
719 scope->se_u.se_if.is_if_label = -1;
720 }
721 }
722
723 if (cctx->ctx_skip != SKIP_UNKNOWN)
724 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
725 }
726
727 return p;
728}
729
730 char_u *
731compile_endif(char_u *arg, cctx_T *cctx)
732{
733 scope_T *scope = cctx->ctx_scope;
734 ifscope_T *ifscope;
735 garray_T *instr = &cctx->ctx_instr;
736 isn_T *isn;
737
738 if (misplaced_cmdmod(cctx))
739 return NULL;
740
741 if (scope == NULL || scope->se_type != IF_SCOPE)
742 {
743 emsg(_(e_endif_without_if));
744 return NULL;
745 }
746 ifscope = &scope->se_u.se_if;
747 unwind_locals(cctx, scope->se_local_count);
748 if (!cctx->ctx_had_return)
749 ifscope->is_had_return = FALSE;
750
751 if (scope->se_u.se_if.is_if_label >= 0)
752 {
753 // previous "if" or "elseif" jumps here
754 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
755 isn->isn_arg.jump.jump_where = instr->ga_len;
756 }
757 // Fill in the "end" label in jumps at the end of the blocks.
758 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
759
760#ifdef FEAT_PROFILE
761 // even when skipping we count the endif as executed, unless the block it's
762 // in is skipped
763 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
764 && scope->se_skip_save != SKIP_YES)
765 {
766 cctx->ctx_skip = SKIP_NOT;
767 generate_instr(cctx, ISN_PROF_START);
768 }
769#endif
770 cctx->ctx_skip = scope->se_skip_save;
771
772 // If all the blocks end in :return and there is an :else then the
773 // had_return flag is set.
774 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
775
776 drop_scope(cctx);
777 return arg;
778}
779
780/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +0100781 * Save the info needed for ENDLOOP. Used by :for and :while.
782 */
783 static void
784compile_fill_loop_info(loop_info_T *loop_info, int funcref_idx, cctx_T *cctx)
785{
786 loop_info->li_funcref_idx = funcref_idx;
787 loop_info->li_local_count = cctx->ctx_locals.ga_len;
788 loop_info->li_closure_count = cctx->ctx_closure_count;
789}
790
791/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000792 * Compile "for var in expr":
793 *
794 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100795 * STORE -1 in loop-idx Set index to -1
796 * EVAL expr Result of "expr" on top of stack
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000797 * top: FOR loop-idx, end Increment index, use list on bottom of stack
798 * - if beyond end, jump to "end"
799 * - otherwise get item from list and push it
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100800 * - store ec_funcrefs in var "loop-idx" + 1
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000801 * STORE var Store item in "var"
802 * ... body ...
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100803 * ENDLOOP funcref-idx off count Only if closure uses local var
804 * JUMP top Jump back to repeat
805 * end: DROP Drop the result of "expr"
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000806 *
807 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
808 * UNPACK 2 Split item in 2
809 * STORE var1 Store item in "var1"
810 * STORE var2 Store item in "var2"
811 */
812 char_u *
813compile_for(char_u *arg_start, cctx_T *cctx)
814{
815 char_u *arg;
816 char_u *arg_end;
817 char_u *name = NULL;
818 char_u *p;
819 char_u *wp;
820 int var_count = 0;
821 int var_list = FALSE;
822 int semicolon = FALSE;
823 size_t varlen;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000824 garray_T *instr = &cctx->ctx_instr;
825 scope_T *scope;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100826 forscope_T *forscope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000827 lvar_T *loop_lvar; // loop iteration variable
Bram Moolenaarcc341812022-09-19 15:54:34 +0100828 int loop_lvar_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100829 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100830 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000831 lvar_T *var_lvar; // variable for "var"
832 type_T *vartype;
833 type_T *item_type = &t_any;
834 int idx;
835 int prev_lnum = cctx->ctx_prev_lnum;
836
837 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
838 if (p == NULL)
839 return NULL;
840 if (var_count == 0)
841 var_count = 1;
842 else
843 var_list = TRUE; // can also be a list of one variable
844
845 // consume "in"
846 wp = p;
847 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
848 return NULL;
849 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
850 {
851 if (*p == ':' && wp != p)
852 semsg(_(e_no_white_space_allowed_before_colon_str), p);
853 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000854 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000855 return NULL;
856 }
857 wp = p + 2;
858 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
859 return NULL;
860
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000861 // Find the already generated ISN_DEBUG to get the line number for the
862 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000863 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
864 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
865 .isn_type == ISN_DEBUG)
866 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000867 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000868 .isn_arg.debug.dbg_break_lnum;
869 }
870
871 scope = new_scope(cctx, FOR_SCOPE);
872 if (scope == NULL)
873 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100874 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
875 {
876 emsg(_(e_loop_nesting_too_deep));
877 return NULL;
878 }
879 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100880 forscope = &scope->se_u.se_for;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000881
882 // Reserve a variable to store the loop iteration counter and initialize it
883 // to -1.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100884 loop_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000885 if (loop_lvar == NULL)
886 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000887 drop_scope(cctx);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100888 return NULL; // out of memory
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000889 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100890 // get the index before a following reserve_local() makes the lval invalid
891 loop_lvar_idx = loop_lvar->lv_idx;
892 generate_STORENR(cctx, loop_lvar_idx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000893
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100894 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
895 // The variable index is always the loop var index plus one.
896 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100897 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100898 if (funcref_lvar == NULL)
899 {
900 drop_scope(cctx);
901 return NULL; // out of memory
902 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100903 // get the index before a following reserve_local() makes the lval invalid
904 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100905
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000906 // compile "expr", it remains on the stack until "endfor"
907 arg = p;
908 if (compile_expr0(&arg, cctx) == FAIL)
909 {
910 drop_scope(cctx);
911 return NULL;
912 }
913 arg_end = arg;
914
915 if (cctx->ctx_skip != SKIP_YES)
916 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000917 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000918 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000919 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000920 if (vartype->tt_type != VAR_LIST
921 && vartype->tt_type != VAR_STRING
922 && vartype->tt_type != VAR_BLOB
923 && vartype->tt_type != VAR_ANY
924 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000925 {
926 semsg(_(e_for_loop_on_str_not_supported),
927 vartype_name(vartype->tt_type));
928 drop_scope(cctx);
929 return NULL;
930 }
931
932 if (vartype->tt_type == VAR_STRING)
933 item_type = &t_string;
934 else if (vartype->tt_type == VAR_BLOB)
935 item_type = &t_number;
936 else if (vartype->tt_type == VAR_LIST
937 && vartype->tt_member->tt_type != VAR_ANY)
938 {
939 if (!var_list)
940 item_type = vartype->tt_member;
941 else if (vartype->tt_member->tt_type == VAR_LIST
942 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
943 item_type = vartype->tt_member->tt_member;
944 }
945
946 // CMDMOD_REV must come before the FOR instruction.
947 generate_undo_cmdmods(cctx);
948
949 // "for_end" is set when ":endfor" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100950 forscope->fs_top_label = current_instr_idx(cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000951
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000952 if (cctx->ctx_compile_type == CT_DEBUG)
953 {
954 int save_prev_lnum = cctx->ctx_prev_lnum;
955 isn_T *isn;
956
957 // Add ISN_DEBUG here, before deciding to end the loop. There will
958 // be another ISN_DEBUG before the next instruction.
959 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
960 // Increment the variable count so that the loop variable can be
961 // inspected.
962 cctx->ctx_prev_lnum = prev_lnum;
963 isn = generate_instr_debug(cctx);
964 ++isn->isn_arg.debug.dbg_var_names_len;
965 cctx->ctx_prev_lnum = save_prev_lnum;
966 }
967
Bram Moolenaarcc341812022-09-19 15:54:34 +0100968 generate_FOR(cctx, loop_lvar_idx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000969
970 arg = arg_start;
971 if (var_list)
972 {
973 generate_UNPACK(cctx, var_count, semicolon);
974 arg = skipwhite(arg + 1); // skip white after '['
975
Bram Moolenaar078a4612022-01-04 15:17:03 +0000976 // drop the list item
977 --cctx->ctx_type_stack.ga_len;
978
979 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000980 for (idx = 0; idx < var_count; ++idx)
981 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000982 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
983
984 if (push_type_stack(cctx, type) == FAIL)
985 {
986 drop_scope(cctx);
987 return NULL;
988 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000989 }
990 }
991
992 for (idx = 0; idx < var_count; ++idx)
993 {
994 assign_dest_T dest = dest_local;
995 int opt_flags = 0;
996 int vimvaridx = -1;
997 type_T *type = &t_any;
998 type_T *lhs_type = &t_any;
999 where_T where = WHERE_INIT;
1000
1001 p = skip_var_one(arg, FALSE);
1002 varlen = p - arg;
1003 name = vim_strnsave(arg, varlen);
1004 if (name == NULL)
1005 goto failed;
1006 if (*p == ':')
1007 {
1008 p = skipwhite(p + 1);
1009 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
1010 }
1011
1012 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
1013 &vimvaridx, &type, cctx) == FAIL)
1014 goto failed;
1015 if (dest != dest_local)
1016 {
1017 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
1018 0, 0, type, name) == FAIL)
1019 goto failed;
1020 }
1021 else if (varlen == 1 && *arg == '_')
1022 {
1023 // Assigning to "_": drop the value.
1024 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1025 goto failed;
1026 }
1027 else
1028 {
1029 // Script var is not supported.
1030 if (STRNCMP(name, "s:", 2) == 0)
1031 {
1032 emsg(_(e_cannot_use_script_variable_in_for_loop));
1033 goto failed;
1034 }
1035
1036 if (!valid_varname(arg, (int)varlen, FALSE))
1037 goto failed;
1038 if (lookup_local(arg, varlen, NULL, cctx) == OK)
1039 {
1040 semsg(_(e_variable_already_declared), arg);
1041 goto failed;
1042 }
1043
1044 // Reserve a variable to store "var".
1045 where.wt_index = var_list ? idx + 1 : 0;
1046 where.wt_variable = TRUE;
1047 if (lhs_type == &t_any)
1048 lhs_type = item_type;
1049 else if (item_type != &t_unknown
Bram Moolenaara1c51952022-02-02 16:20:26 +00001050 && need_type_where(item_type, lhs_type, -1,
1051 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001052 goto failed;
Bram Moolenaar6586a012022-09-30 11:04:50 +01001053 var_lvar = reserve_local(cctx, arg, varlen, ASSIGN_CONST,
1054 lhs_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001055 if (var_lvar == NULL)
1056 // out of memory or used as an argument
1057 goto failed;
1058
1059 if (semicolon && idx == var_count - 1)
1060 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001061 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1062 }
1063
1064 if (*p == ',' || *p == ';')
1065 ++p;
1066 arg = skipwhite(p);
1067 vim_free(name);
1068 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001069
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001070 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001071 compile_fill_loop_info(&forscope->fs_loop_info, funcref_lvar_idx, cctx);
1072 forscope->fs_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001073 }
1074
1075 return arg_end;
1076
1077failed:
1078 vim_free(name);
1079 drop_scope(cctx);
1080 return NULL;
1081}
1082
1083/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001084 * Used when ending a loop of :for and :while: Generate an ISN_ENDLOOP
1085 * instruction if any variable was declared that could be used by a new
1086 * closure.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001087 */
1088 static int
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001089compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001090{
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001091 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1092 && cctx->ctx_closure_count > loop_info->li_closure_count)
Bram Moolenaarcc341812022-09-19 15:54:34 +01001093 return generate_ENDLOOP(cctx, loop_info);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001094 return OK;
1095}
1096
1097/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001098 * compile "endfor"
1099 */
1100 char_u *
1101compile_endfor(char_u *arg, cctx_T *cctx)
1102{
1103 garray_T *instr = &cctx->ctx_instr;
1104 scope_T *scope = cctx->ctx_scope;
1105 forscope_T *forscope;
1106 isn_T *isn;
1107
1108 if (misplaced_cmdmod(cctx))
1109 return NULL;
1110
1111 if (scope == NULL || scope->se_type != FOR_SCOPE)
1112 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001113 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001114 return NULL;
1115 }
1116 forscope = &scope->se_u.se_for;
1117 cctx->ctx_scope = scope->se_outer;
1118 if (cctx->ctx_skip != SKIP_YES)
1119 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001120 // Handle the case that any local variables were declared that might be
1121 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001122 if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001123 return NULL;
1124
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001125 unwind_locals(cctx, scope->se_local_count);
1126
1127 // At end of ":for" scope jump back to the FOR instruction.
1128 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1129
1130 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001131 // In debug mode an ISN_DEBUG was inserted.
1132 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1133 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001134 isn->isn_arg.forloop.for_end = instr->ga_len;
1135
1136 // Fill in the "end" label any BREAK statements
1137 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1138
1139 // Below the ":for" scope drop the "expr" list from the stack.
1140 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1141 return NULL;
1142 }
1143
1144 vim_free(scope);
1145
1146 return arg;
1147}
1148
1149/*
1150 * compile "while expr"
1151 *
1152 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001153 * top: EVAL expr Push result of "expr"
1154 * WHILE funcref-idx end Jump if false
1155 * ... body ...
1156 * ENDLOOP funcref-idx off count only if closure uses local var
1157 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001158 * end:
1159 *
1160 */
1161 char_u *
1162compile_while(char_u *arg, cctx_T *cctx)
1163{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001164 char_u *p = arg;
1165 scope_T *scope;
1166 whilescope_T *whilescope;
1167 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001168 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001169
1170 scope = new_scope(cctx, WHILE_SCOPE);
1171 if (scope == NULL)
1172 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001173 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
1174 {
1175 emsg(_(e_loop_nesting_too_deep));
1176 return NULL;
1177 }
1178 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001179 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001180
1181 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001182 whilescope->ws_top_label = current_instr_idx(cctx);
1183
1184 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1185 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +01001186 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001187 if (funcref_lvar == NULL)
1188 {
1189 drop_scope(cctx);
1190 return NULL; // out of memory
1191 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001192 // get the index before a following reserve_local() makes the lval invalid
1193 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001194
1195 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001196 compile_fill_loop_info(&whilescope->ws_loop_info, funcref_lvar_idx, cctx);
1197 whilescope->ws_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001198
1199 // compile "expr"
1200 if (compile_expr0(&p, cctx) == FAIL)
1201 return NULL;
1202
1203 if (!ends_excmd2(arg, skipwhite(p)))
1204 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001205 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001206 return NULL;
1207 }
1208
1209 if (cctx->ctx_skip != SKIP_YES)
1210 {
1211 if (bool_on_stack(cctx) == FAIL)
1212 return FAIL;
1213
1214 // CMDMOD_REV must come before the jump
1215 generate_undo_cmdmods(cctx);
1216
1217 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001218 if (compile_jump_to_end(&whilescope->ws_end_label,
Bram Moolenaarcc341812022-09-19 15:54:34 +01001219 JUMP_WHILE_FALSE, funcref_lvar_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001220 return FAIL;
1221 }
1222
1223 return p;
1224}
1225
1226/*
1227 * compile "endwhile"
1228 */
1229 char_u *
1230compile_endwhile(char_u *arg, cctx_T *cctx)
1231{
1232 scope_T *scope = cctx->ctx_scope;
1233 garray_T *instr = &cctx->ctx_instr;
1234
1235 if (misplaced_cmdmod(cctx))
1236 return NULL;
1237 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1238 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001239 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001240 return NULL;
1241 }
1242 cctx->ctx_scope = scope->se_outer;
1243 if (cctx->ctx_skip != SKIP_YES)
1244 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001245 whilescope_T *whilescope = &scope->se_u.se_while;
1246
1247 // Handle the case that any local variables were declared that might be
1248 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001249 if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001250 return NULL;
1251
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001252 unwind_locals(cctx, scope->se_local_count);
1253
1254#ifdef FEAT_PROFILE
1255 // count the endwhile before jumping
1256 may_generate_prof_end(cctx, cctx->ctx_lnum);
1257#endif
1258
1259 // At end of ":for" scope jump back to the FOR instruction.
1260 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1261
1262 // Fill in the "end" label in the WHILE statement so it can jump here.
1263 // And in any jumps for ":break"
1264 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1265 instr->ga_len, cctx);
1266 }
1267
1268 vim_free(scope);
1269
1270 return arg;
1271}
1272
1273/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001274 * Get the current information about variables declared inside a loop.
Bram Moolenaarcc341812022-09-19 15:54:34 +01001275 * Returns TRUE if there are any and fills "lvi".
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001276 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001277 int
1278get_loop_var_info(cctx_T *cctx, loopvarinfo_T *lvi)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001279{
1280 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001281 int prev_local_count = 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001282
Bram Moolenaarcc341812022-09-19 15:54:34 +01001283 CLEAR_POINTER(lvi);
1284 for (;;)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001285 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01001286 loop_info_T *loopinfo;
1287 int cur_local_last;
1288 int start_local_count;
1289
1290 while (scope != NULL && scope->se_type != WHILE_SCOPE
1291 && scope->se_type != FOR_SCOPE)
1292 scope = scope->se_outer;
1293 if (scope == NULL)
1294 break;
1295
1296 if (scope->se_type == WHILE_SCOPE)
1297 {
1298 loopinfo = &scope->se_u.se_while.ws_loop_info;
1299 // :while reserves one variable for funcref count
1300 cur_local_last = loopinfo->li_local_count - 1;
1301 }
1302 else
1303 {
1304 loopinfo = &scope->se_u.se_for.fs_loop_info;
1305 // :for reserves three variable: loop count, funcref count and loop
1306 // var
1307 cur_local_last = loopinfo->li_local_count - 3;
1308 }
1309
1310 start_local_count = loopinfo->li_local_count;
1311 if (cctx->ctx_locals.ga_len > start_local_count)
1312 {
1313 lvi->lvi_loop[loopinfo->li_depth].var_idx =
1314 (short)start_local_count;
1315 lvi->lvi_loop[loopinfo->li_depth].var_count =
1316 (short)(cctx->ctx_locals.ga_len - start_local_count
1317 - prev_local_count);
1318 if (lvi->lvi_depth == 0)
1319 lvi->lvi_depth = loopinfo->li_depth + 1;
1320 }
1321
1322 scope = scope->se_outer;
1323 prev_local_count = cctx->ctx_locals.ga_len - cur_local_last;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001324 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001325 return lvi->lvi_depth > 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001326}
1327
1328/*
Bram Moolenaarcc341812022-09-19 15:54:34 +01001329 * Get the index of the variable "idx" in a loop, if any.
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001330 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001331 void
1332get_loop_var_idx(cctx_T *cctx, int idx, lvar_T *lvar)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001333{
Bram Moolenaarcc341812022-09-19 15:54:34 +01001334 loopvarinfo_T lvi;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001335
Bram Moolenaarcc341812022-09-19 15:54:34 +01001336 lvar->lv_loop_depth = -1;
1337 lvar->lv_loop_idx = -1;
1338 if (get_loop_var_info(cctx, &lvi))
1339 {
1340 int depth;
1341
1342 for (depth = lvi.lvi_depth - 1; depth >= 0; --depth)
1343 if (idx >= lvi.lvi_loop[depth].var_idx
1344 && idx < lvi.lvi_loop[depth].var_idx
1345 + lvi.lvi_loop[depth].var_count)
1346 {
1347 lvar->lv_loop_depth = depth;
1348 lvar->lv_loop_idx = lvi.lvi_loop[depth].var_idx;
1349 return;
1350 }
1351 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001352}
1353
1354/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001355 * Common for :break, :continue and :return
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001356 */
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001357 static int
1358compile_find_scope(
1359 int *loop_label, // where to jump to or NULL
1360 endlabel_T ***el, // end label or NULL
1361 int *try_scopes, // :try scopes encountered or NULL
1362 char *error, // error to use when no scope found
1363 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001364{
1365 scope_T *scope = cctx->ctx_scope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001366
1367 for (;;)
1368 {
1369 if (scope == NULL)
1370 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001371 if (error != NULL)
1372 emsg(_(error));
1373 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001374 }
1375 if (scope->se_type == FOR_SCOPE)
1376 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001377 if (compile_loop_end(&scope->se_u.se_for.fs_loop_info, cctx)
1378 == FAIL)
1379 return FAIL;
1380 if (loop_label != NULL)
1381 *loop_label = scope->se_u.se_for.fs_top_label;
1382 if (el != NULL)
1383 *el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001384 break;
1385 }
1386 if (scope->se_type == WHILE_SCOPE)
1387 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001388 if (compile_loop_end(&scope->se_u.se_while.ws_loop_info, cctx)
1389 == FAIL)
1390 return FAIL;
1391 if (loop_label != NULL)
1392 *loop_label = scope->se_u.se_while.ws_top_label;
1393 if (el != NULL)
1394 *el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001395 break;
1396 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001397 if (try_scopes != NULL && scope->se_type == TRY_SCOPE)
1398 ++*try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001399 scope = scope->se_outer;
1400 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001401 return OK;
1402}
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001403
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001404/*
1405 * compile "continue"
1406 */
1407 char_u *
1408compile_continue(char_u *arg, cctx_T *cctx)
1409{
1410 int try_scopes = 0;
1411 int loop_label;
1412
1413 if (compile_find_scope(&loop_label, NULL, &try_scopes,
1414 e_continue_without_while_or_for, cctx) == FAIL)
1415 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001416 if (try_scopes > 0)
1417 // Inside one or more try/catch blocks we first need to jump to the
1418 // "finally" or "endtry" to cleanup.
1419 generate_TRYCONT(cctx, try_scopes, loop_label);
1420 else
1421 // Jump back to the FOR or WHILE instruction.
1422 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1423
1424 return arg;
1425}
1426
1427/*
1428 * compile "break"
1429 */
1430 char_u *
1431compile_break(char_u *arg, cctx_T *cctx)
1432{
Bram Moolenaar873f8242022-03-10 21:53:44 +00001433 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001434 endlabel_T **el;
1435
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001436 if (compile_find_scope(NULL, &el, &try_scopes,
1437 e_break_without_while_or_for, cctx) == FAIL)
1438 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001439
Bram Moolenaar873f8242022-03-10 21:53:44 +00001440 if (try_scopes > 0)
1441 // Inside one or more try/catch blocks we first need to jump to the
1442 // "finally" or "endtry" to cleanup. Then come to the next JUMP
1443 // intruction, which we don't know the index of yet.
1444 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1445
1446 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1447 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001448 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001449 return FAIL;
1450
1451 return arg;
1452}
1453
1454/*
1455 * compile "{" start of block
1456 */
1457 char_u *
1458compile_block(char_u *arg, cctx_T *cctx)
1459{
1460 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1461 return NULL;
1462 return skipwhite(arg + 1);
1463}
1464
1465/*
1466 * compile end of block: drop one scope
1467 */
1468 void
1469compile_endblock(cctx_T *cctx)
1470{
1471 scope_T *scope = cctx->ctx_scope;
1472
1473 cctx->ctx_scope = scope->se_outer;
1474 unwind_locals(cctx, scope->se_local_count);
1475 vim_free(scope);
1476}
1477
1478/*
1479 * Compile "try".
1480 * Creates a new scope for the try-endtry, pointing to the first catch and
1481 * finally.
1482 * Creates another scope for the "try" block itself.
1483 * TRY instruction sets up exception handling at runtime.
1484 *
1485 * "try"
1486 * TRY -> catch1, -> finally push trystack entry
1487 * ... try block
1488 * "throw {exception}"
1489 * EVAL {exception}
1490 * THROW create exception
1491 * ... try block
1492 * " catch {expr}"
1493 * JUMP -> finally
1494 * catch1: PUSH exception
1495 * EVAL {expr}
1496 * MATCH
1497 * JUMP nomatch -> catch2
1498 * CATCH remove exception
1499 * ... catch block
1500 * " catch"
1501 * JUMP -> finally
1502 * catch2: CATCH remove exception
1503 * ... catch block
1504 * " finally"
1505 * finally:
1506 * ... finally block
1507 * " endtry"
1508 * ENDTRY pop trystack entry, may rethrow
1509 */
1510 char_u *
1511compile_try(char_u *arg, cctx_T *cctx)
1512{
1513 garray_T *instr = &cctx->ctx_instr;
1514 scope_T *try_scope;
1515 scope_T *scope;
1516
1517 if (misplaced_cmdmod(cctx))
1518 return NULL;
1519
1520 // scope that holds the jumps that go to catch/finally/endtry
1521 try_scope = new_scope(cctx, TRY_SCOPE);
1522 if (try_scope == NULL)
1523 return NULL;
1524
1525 if (cctx->ctx_skip != SKIP_YES)
1526 {
1527 isn_T *isn;
1528
1529 // "try_catch" is set when the first ":catch" is found or when no catch
1530 // is found and ":finally" is found.
1531 // "try_finally" is set when ":finally" is found
1532 // "try_endtry" is set when ":endtry" is found
1533 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1534 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1535 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001536 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1537 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001538 return NULL;
1539 }
1540
1541 // scope for the try block itself
1542 scope = new_scope(cctx, BLOCK_SCOPE);
1543 if (scope == NULL)
1544 return NULL;
1545
1546 return arg;
1547}
1548
1549/*
1550 * Compile "catch {expr}".
1551 */
1552 char_u *
1553compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1554{
1555 scope_T *scope = cctx->ctx_scope;
1556 garray_T *instr = &cctx->ctx_instr;
1557 char_u *p;
1558 isn_T *isn;
1559
1560 if (misplaced_cmdmod(cctx))
1561 return NULL;
1562
1563 // end block scope from :try or :catch
1564 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1565 compile_endblock(cctx);
1566 scope = cctx->ctx_scope;
1567
1568 // Error if not in a :try scope
1569 if (scope == NULL || scope->se_type != TRY_SCOPE)
1570 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001571 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001572 return NULL;
1573 }
1574
1575 if (scope->se_u.se_try.ts_caught_all)
1576 {
1577 emsg(_(e_catch_unreachable_after_catch_all));
1578 return NULL;
1579 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001580 if (!cctx->ctx_had_return)
1581 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001582
1583 if (cctx->ctx_skip != SKIP_YES)
1584 {
1585#ifdef FEAT_PROFILE
1586 // the profile-start should be after the jump
1587 if (cctx->ctx_compile_type == CT_PROFILE
1588 && instr->ga_len > 0
1589 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1590 .isn_type == ISN_PROF_START)
1591 --instr->ga_len;
1592#endif
1593 // Jump from end of previous block to :finally or :endtry
1594 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001595 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001596 return NULL;
1597
1598 // End :try or :catch scope: set value in ISN_TRY instruction
1599 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001600 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1601 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001602 if (scope->se_u.se_try.ts_catch_label != 0)
1603 {
1604 // Previous catch without match jumps here
1605 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1606 isn->isn_arg.jump.jump_where = instr->ga_len;
1607 }
1608#ifdef FEAT_PROFILE
1609 if (cctx->ctx_compile_type == CT_PROFILE)
1610 {
1611 // a "throw" that jumps here needs to be counted
1612 generate_instr(cctx, ISN_PROF_END);
1613 // the "catch" is also counted
1614 generate_instr(cctx, ISN_PROF_START);
1615 }
1616#endif
1617 if (cctx->ctx_compile_type == CT_DEBUG)
1618 generate_instr_debug(cctx);
1619 }
1620
1621 p = skipwhite(arg);
1622 if (ends_excmd2(arg, p))
1623 {
1624 scope->se_u.se_try.ts_caught_all = TRUE;
1625 scope->se_u.se_try.ts_catch_label = 0;
1626 }
1627 else
1628 {
1629 char_u *end;
1630 char_u *pat;
1631 char_u *tofree = NULL;
1632 int dropped = 0;
1633 int len;
1634
1635 // Push v:exception, push {expr} and MATCH
1636 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1637
1638 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1639 if (*end != *p)
1640 {
1641 semsg(_(e_separator_mismatch_str), p);
1642 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001643 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001644 }
1645 if (tofree == NULL)
1646 len = (int)(end - (p + 1));
1647 else
1648 len = (int)(end - tofree);
1649 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1650 vim_free(tofree);
1651 p += len + 2 + dropped;
1652 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001653 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001654 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001655 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001656
1657 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1658 return NULL;
1659
1660 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1661 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1662 return NULL;
1663 }
1664
1665 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1666 return NULL;
1667
1668 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1669 return NULL;
1670 return p;
1671}
1672
1673 char_u *
1674compile_finally(char_u *arg, cctx_T *cctx)
1675{
1676 scope_T *scope = cctx->ctx_scope;
1677 garray_T *instr = &cctx->ctx_instr;
1678 isn_T *isn;
1679 int this_instr;
1680
1681 if (misplaced_cmdmod(cctx))
1682 return NULL;
1683
1684 // end block scope from :try or :catch
1685 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1686 compile_endblock(cctx);
1687 scope = cctx->ctx_scope;
1688
1689 // Error if not in a :try scope
1690 if (scope == NULL || scope->se_type != TRY_SCOPE)
1691 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001692 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001693 return NULL;
1694 }
1695
1696 if (cctx->ctx_skip != SKIP_YES)
1697 {
1698 // End :catch or :finally scope: set value in ISN_TRY instruction
1699 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001700 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001701 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001702 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001703 return NULL;
1704 }
1705
1706 this_instr = instr->ga_len;
1707#ifdef FEAT_PROFILE
1708 if (cctx->ctx_compile_type == CT_PROFILE
1709 && ((isn_T *)instr->ga_data)[this_instr - 1]
1710 .isn_type == ISN_PROF_START)
1711 {
1712 // jump to the profile start of the "finally"
1713 --this_instr;
1714
1715 // jump to the profile end above it
1716 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1717 .isn_type == ISN_PROF_END)
1718 --this_instr;
1719 }
1720#endif
1721
1722 // Fill in the "end" label in jumps at the end of the blocks.
1723 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1724 this_instr, cctx);
1725
1726 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001727 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1728 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1729 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001730 if (scope->se_u.se_try.ts_catch_label != 0)
1731 {
1732 // Previous catch without match jumps here
1733 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1734 isn->isn_arg.jump.jump_where = this_instr;
1735 scope->se_u.se_try.ts_catch_label = 0;
1736 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001737 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001738 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1739 return NULL;
1740 }
1741
1742 return arg;
1743}
1744
1745 char_u *
1746compile_endtry(char_u *arg, cctx_T *cctx)
1747{
1748 scope_T *scope = cctx->ctx_scope;
1749 garray_T *instr = &cctx->ctx_instr;
1750 isn_T *try_isn;
1751
1752 if (misplaced_cmdmod(cctx))
1753 return NULL;
1754
1755 // end block scope from :catch or :finally
1756 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1757 compile_endblock(cctx);
1758 scope = cctx->ctx_scope;
1759
1760 // Error if not in a :try scope
1761 if (scope == NULL || scope->se_type != TRY_SCOPE)
1762 {
1763 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001764 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001765 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001766 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001767 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001768 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001769 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001770 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001771 return NULL;
1772 }
1773
1774 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1775 if (cctx->ctx_skip != SKIP_YES)
1776 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001777 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1778 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001779 {
1780 emsg(_(e_missing_catch_or_finally));
1781 return NULL;
1782 }
1783
1784#ifdef FEAT_PROFILE
1785 if (cctx->ctx_compile_type == CT_PROFILE
1786 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1787 .isn_type == ISN_PROF_START)
1788 // move the profile start after "endtry" so that it's not counted when
1789 // the exception is rethrown.
1790 --instr->ga_len;
1791#endif
1792
1793 // Fill in the "end" label in jumps at the end of the blocks, if not
1794 // done by ":finally".
1795 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1796 instr->ga_len, cctx);
1797
1798 if (scope->se_u.se_try.ts_catch_label != 0)
1799 {
1800 // Last catch without match jumps here
1801 isn_T *isn = ((isn_T *)instr->ga_data)
1802 + scope->se_u.se_try.ts_catch_label;
1803 isn->isn_arg.jump.jump_where = instr->ga_len;
1804 }
1805 }
1806
Bram Moolenaar53c29612022-01-12 16:18:18 +00001807 // If there is a finally clause that ends in return then we will return.
1808 // If one of the blocks didn't end in "return" or we did not catch all
1809 // exceptions reset the had_return flag.
1810 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1811 && (scope->se_u.se_try.ts_no_return
1812 || !scope->se_u.se_try.ts_caught_all))
1813 cctx->ctx_had_return = FALSE;
1814
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001815 compile_endblock(cctx);
1816
1817 if (cctx->ctx_skip != SKIP_YES)
1818 {
1819 // End :catch or :finally scope: set instruction index in ISN_TRY
1820 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001821 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001822 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001823 return NULL;
1824#ifdef FEAT_PROFILE
1825 if (cctx->ctx_compile_type == CT_PROFILE)
1826 generate_instr(cctx, ISN_PROF_START);
1827#endif
1828 }
1829 return arg;
1830}
1831
1832/*
1833 * compile "throw {expr}"
1834 */
1835 char_u *
1836compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1837{
1838 char_u *p = skipwhite(arg);
1839
1840 if (compile_expr0(&p, cctx) == FAIL)
1841 return NULL;
1842 if (cctx->ctx_skip == SKIP_YES)
1843 return p;
1844 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1845 return NULL;
1846 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1847 return NULL;
1848
1849 return p;
1850}
1851
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001852/*
1853 * Compile an expression or function call.
1854 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001855 char_u *
1856compile_eval(char_u *arg, cctx_T *cctx)
1857{
1858 char_u *p = arg;
1859 int name_only;
1860 long lnum = SOURCING_LNUM;
1861
1862 // find_ex_command() will consider a variable name an expression, assuming
1863 // that something follows on the next line. Check that something actually
1864 // follows, otherwise it's probably a misplaced command.
1865 name_only = cmd_is_name_only(arg);
1866
1867 if (compile_expr0(&p, cctx) == FAIL)
1868 return NULL;
1869
1870 if (name_only && lnum == SOURCING_LNUM)
1871 {
1872 semsg(_(e_expression_without_effect_str), arg);
1873 return NULL;
1874 }
1875
1876 // drop the result
1877 generate_instr_drop(cctx, ISN_DROP, 1);
1878
1879 return skipwhite(p);
1880}
1881
1882/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001883 * Get the local variable index for deferred function calls.
1884 * Reserve it when not done already.
1885 * Returns zero for failure.
1886 */
1887 int
1888get_defer_var_idx(cctx_T *cctx)
1889{
1890 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1891 + cctx->ctx_ufunc->uf_dfunc_idx;
1892 if (dfunc->df_defer_var_idx == 0)
1893 {
1894 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1895 TRUE, &t_list_any);
1896 if (lvar == NULL)
1897 return 0;
1898 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1899 }
1900 return dfunc->df_defer_var_idx;
1901}
1902
1903/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001904 * Compile "defer func(arg)".
1905 */
1906 char_u *
1907compile_defer(char_u *arg_start, cctx_T *cctx)
1908{
Bram Moolenaar16900322022-09-08 19:51:45 +01001909 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001910 char_u *arg = arg_start;
1911 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001912 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001913 type_T *type;
1914 int func_idx;
1915
1916 // Get a funcref for the function name.
1917 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01001918 paren = vim_strchr(arg, '(');
1919 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001920 {
1921 semsg(_(e_missing_parenthesis_str), arg);
1922 return NULL;
1923 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001924 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001925 func_idx = find_internal_func(arg);
1926 if (func_idx >= 0)
1927 // TODO: better type
1928 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1929 &t_func_any, FALSE);
1930 else if (compile_expr0(&arg, cctx) == FAIL)
1931 return NULL;
Bram Moolenaar16900322022-09-08 19:51:45 +01001932 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001933
1934 // check for function type
1935 type = get_type_on_stack(cctx, 0);
1936 if (type->tt_type != VAR_FUNC)
1937 {
1938 emsg(_(e_function_name_required));
1939 return NULL;
1940 }
1941
1942 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01001943 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001944 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1945 return NULL;
1946
Bram Moolenaar16900322022-09-08 19:51:45 +01001947 if (func_idx >= 0)
1948 {
1949 type2_T *argtypes = NULL;
1950 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1951
1952 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
1953 &argtypes, shuffled_argtypes) == FAIL)
1954 return NULL;
1955 }
1956 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
1957 arg_start) == FAIL)
1958 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001959
Bram Moolenaar806a2732022-09-04 15:40:36 +01001960 defer_var_idx = get_defer_var_idx(cctx);
1961 if (defer_var_idx == 0)
1962 return NULL;
1963 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001964 return NULL;
1965
1966 return skipwhite(arg);
1967}
1968
1969/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001970 * compile "echo expr"
1971 * compile "echomsg expr"
1972 * compile "echoerr expr"
1973 * compile "echoconsole expr"
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01001974 * compile "echowindow expr" - may have cmd_count set
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001975 * compile "execute expr"
1976 */
1977 char_u *
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01001978compile_mult_expr(char_u *arg, int cmdidx, long cmd_count, cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001979{
1980 char_u *p = arg;
1981 char_u *prev = arg;
1982 char_u *expr_start;
1983 int count = 0;
1984 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001985 type_T *type;
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01001986 int r = OK;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001987
1988 for (;;)
1989 {
1990 if (ends_excmd2(prev, p))
1991 break;
1992 expr_start = p;
1993 if (compile_expr0(&p, cctx) == FAIL)
1994 return NULL;
1995
1996 if (cctx->ctx_skip != SKIP_YES)
1997 {
1998 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001999 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002000 if (type->tt_type == VAR_VOID)
2001 {
2002 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
2003 return NULL;
2004 }
2005 }
2006
2007 ++count;
2008 prev = p;
2009 p = skipwhite(p);
2010 }
2011
2012 if (count > 0)
2013 {
2014 long save_lnum = cctx->ctx_lnum;
2015
2016 // Use the line number where the command started.
2017 cctx->ctx_lnum = start_ctx_lnum;
2018
2019 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002020 r = generate_ECHO(cctx, cmdidx == CMD_echo, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002021 else if (cmdidx == CMD_execute)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002022 r = generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002023 else if (cmdidx == CMD_echomsg)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002024 r = generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002025#ifdef HAS_MESSAGE_WINDOW
2026 else if (cmdidx == CMD_echowindow)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002027 r = generate_ECHOWINDOW(cctx, count, cmd_count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002028#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002029 else if (cmdidx == CMD_echoconsole)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002030 r = generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002031 else
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002032 r = generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002033
2034 cctx->ctx_lnum = save_lnum;
2035 }
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002036 return r == OK ? p : NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002037}
2038
2039/*
2040 * If "eap" has a range that is not a constant generate an ISN_RANGE
2041 * instruction to compute it and return OK.
2042 * Otherwise return FAIL, the caller must deal with any range.
2043 */
2044 static int
2045compile_variable_range(exarg_T *eap, cctx_T *cctx)
2046{
2047 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
2048 char_u *p = skipdigits(eap->cmd);
2049
2050 if (p == range_end)
2051 return FAIL;
2052 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
2053}
2054
2055/*
2056 * :put r
2057 * :put ={expr}
2058 */
2059 char_u *
2060compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
2061{
2062 char_u *line = arg;
2063 linenr_T lnum;
2064 char *errormsg;
2065 int above = eap->forceit;
2066
2067 eap->regname = *line;
2068
2069 if (eap->regname == '=')
2070 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002071 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002072
2073 if (compile_expr0(&p, cctx) == FAIL)
2074 return NULL;
2075 line = p;
2076 }
2077 else if (eap->regname != NUL)
2078 ++line;
2079
2080 if (compile_variable_range(eap, cctx) == OK)
2081 {
2082 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2083 }
2084 else
2085 {
2086 // Either no range or a number.
2087 // "errormsg" will not be set because the range is ADDR_LINES.
2088 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2089 // cannot happen
2090 return NULL;
2091 if (eap->addr_count == 0)
2092 lnum = -1;
2093 else
2094 lnum = eap->line2;
2095 if (above)
2096 --lnum;
2097 }
2098
2099 generate_PUT(cctx, eap->regname, lnum);
2100 return line;
2101}
2102
2103/*
2104 * A command that is not compiled, execute with legacy code.
2105 */
2106 char_u *
2107compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2108{
2109 char_u *line = line_arg;
2110 char_u *p;
2111 int has_expr = FALSE;
2112 char_u *nextcmd = (char_u *)"";
2113 char_u *tofree = NULL;
2114 char_u *cmd_arg = NULL;
2115
2116 if (cctx->ctx_skip == SKIP_YES)
2117 goto theend;
2118
2119 // If there was a prececing command modifier, drop it and include it in the
2120 // EXEC command.
2121 if (cctx->ctx_has_cmdmod)
2122 {
2123 garray_T *instr = &cctx->ctx_instr;
2124 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2125
2126 if (isn->isn_type == ISN_CMDMOD)
2127 {
2128 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2129 ->cmod_filter_regmatch.regprog);
2130 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2131 --instr->ga_len;
2132 cctx->ctx_has_cmdmod = FALSE;
2133 }
2134 }
2135
2136 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2137 {
2138 long argt = eap->argt;
2139 int usefilter = FALSE;
2140
2141 has_expr = argt & (EX_XFILE | EX_EXPAND);
2142
2143 // If the command can be followed by a bar, find the bar and truncate
2144 // it, so that the following command can be compiled.
2145 // The '|' is overwritten with a NUL, it is put back below.
2146 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2147 && *eap->arg == '!')
2148 // :w !filter or :r !filter or :r! filter
2149 usefilter = TRUE;
2150 if ((argt & EX_TRLBAR) && !usefilter)
2151 {
2152 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002153 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002154 if (eap->nextcmd != NULL)
2155 nextcmd = eap->nextcmd;
2156 }
2157 else if (eap->cmdidx == CMD_wincmd)
2158 {
2159 p = eap->arg;
2160 if (*p != NUL)
2161 ++p;
2162 if (*p == 'g' || *p == Ctrl_G)
2163 ++p;
2164 p = skipwhite(p);
2165 if (*p == '|')
2166 {
2167 *p = NUL;
2168 nextcmd = p + 1;
2169 }
2170 }
2171 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2172 {
2173 // If there is a trailing '{' read lines until the '}'
2174 p = eap->arg + STRLEN(eap->arg) - 1;
2175 while (p > eap->arg && VIM_ISWHITE(*p))
2176 --p;
2177 if (*p == '{')
2178 {
2179 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002180 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002181 int start_lnum = SOURCING_LNUM;
2182
2183 CLEAR_FIELD(ea);
2184 ea.arg = eap->arg;
2185 fill_exarg_from_cctx(&ea, cctx);
2186 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2187 if (tofree != NULL)
2188 {
2189 *p = NUL;
2190 line = concat_str(line, tofree);
2191 if (line == NULL)
2192 goto theend;
2193 vim_free(tofree);
2194 tofree = line;
2195 SOURCING_LNUM = start_lnum;
2196 }
2197 }
2198 }
2199 }
2200
2201 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2202 {
2203 // expand filename in "syntax include [@group] filename"
2204 has_expr = TRUE;
2205 eap->arg = skipwhite(eap->arg + 7);
2206 if (*eap->arg == '@')
2207 eap->arg = skiptowhite(eap->arg);
2208 }
2209
2210 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2211 && STRLEN(eap->arg) > 4)
2212 {
2213 int delim = *eap->arg;
2214
2215 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2216 if (*p == delim)
2217 cmd_arg = p + 1;
2218 }
2219
2220 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2221 cmd_arg = eap->arg;
2222
2223 if (cmd_arg != NULL)
2224 {
2225 exarg_T nea;
2226
2227 CLEAR_FIELD(nea);
2228 nea.cmd = cmd_arg;
2229 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2230 if (nea.cmdidx < CMD_SIZE)
2231 {
2232 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2233 if (has_expr)
2234 eap->arg = skiptowhite(eap->arg);
2235 }
2236 }
2237
2238 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2239 {
2240 int count = 0;
2241 char_u *start = skipwhite(line);
2242
2243 // :cmd xxx`=expr1`yyy`=expr2`zzz
2244 // PUSHS ":cmd xxx"
2245 // eval expr1
2246 // PUSHS "yyy"
2247 // eval expr2
2248 // PUSHS "zzz"
2249 // EXECCONCAT 5
2250 for (;;)
2251 {
2252 if (p > start)
2253 {
2254 char_u *val = vim_strnsave(start, p - start);
2255
2256 generate_PUSHS(cctx, &val);
2257 ++count;
2258 }
2259 p += 2;
2260 if (compile_expr0(&p, cctx) == FAIL)
2261 return NULL;
2262 may_generate_2STRING(-1, TRUE, cctx);
2263 ++count;
2264 p = skipwhite(p);
2265 if (*p != '`')
2266 {
2267 emsg(_(e_missing_backtick));
2268 return NULL;
2269 }
2270 start = p + 1;
2271
2272 p = (char_u *)strstr((char *)start, "`=");
2273 if (p == NULL)
2274 {
2275 if (*skipwhite(start) != NUL)
2276 {
2277 char_u *val = vim_strsave(start);
2278
2279 generate_PUSHS(cctx, &val);
2280 ++count;
2281 }
2282 break;
2283 }
2284 }
2285 generate_EXECCONCAT(cctx, count);
2286 }
2287 else
2288 generate_EXEC_copy(cctx, ISN_EXEC, line);
2289
2290theend:
2291 if (*nextcmd != NUL)
2292 {
2293 // the parser expects a pointer to the bar, put it back
2294 --nextcmd;
2295 *nextcmd = '|';
2296 }
2297 vim_free(tofree);
2298
2299 return nextcmd;
2300}
2301
2302/*
2303 * A script command with heredoc, e.g.
2304 * ruby << EOF
2305 * command
2306 * EOF
2307 * Has been turned into one long line with NL characters by
2308 * get_function_body():
2309 * ruby << EOF<NL> command<NL>EOF
2310 */
2311 char_u *
2312compile_script(char_u *line, cctx_T *cctx)
2313{
2314 if (cctx->ctx_skip != SKIP_YES)
2315 {
2316 isn_T *isn;
2317
2318 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2319 return NULL;
2320 isn->isn_arg.string = vim_strsave(line);
2321 }
2322 return (char_u *)"";
2323}
2324
2325
2326/*
2327 * :s/pat/repl/
2328 */
2329 char_u *
2330compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2331{
2332 char_u *cmd = eap->arg;
2333 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2334
2335 if (expr != NULL)
2336 {
2337 int delimiter = *cmd++;
2338
2339 // There is a \=expr, find it in the substitute part.
2340 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2341 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2342 {
2343 garray_T save_ga = cctx->ctx_instr;
2344 char_u *end;
2345 int expr_res;
2346 int trailing_error;
2347 int instr_count;
2348 isn_T *instr;
2349 isn_T *isn;
2350
2351 cmd += 3;
2352 end = skip_substitute(cmd, delimiter);
2353
2354 // Temporarily reset the list of instructions so that the jump
2355 // labels are correct.
2356 cctx->ctx_instr.ga_len = 0;
2357 cctx->ctx_instr.ga_maxlen = 0;
2358 cctx->ctx_instr.ga_data = NULL;
2359 expr_res = compile_expr0(&cmd, cctx);
2360 if (end[-1] == NUL)
2361 end[-1] = delimiter;
2362 cmd = skipwhite(cmd);
2363 trailing_error = *cmd != delimiter && *cmd != NUL;
2364
2365 if (expr_res == FAIL || trailing_error
2366 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2367 {
2368 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002369 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002370 clear_instr_ga(&cctx->ctx_instr);
2371 cctx->ctx_instr = save_ga;
2372 return NULL;
2373 }
2374
2375 // Move the generated instructions into the ISN_SUBSTITUTE
2376 // instructions, then restore the list of instructions before
2377 // adding the ISN_SUBSTITUTE instruction.
2378 instr_count = cctx->ctx_instr.ga_len;
2379 instr = cctx->ctx_instr.ga_data;
2380 instr[instr_count].isn_type = ISN_FINISH;
2381
2382 cctx->ctx_instr = save_ga;
2383 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2384 {
2385 int idx;
2386
2387 for (idx = 0; idx < instr_count; ++idx)
2388 delete_instr(instr + idx);
2389 vim_free(instr);
2390 return NULL;
2391 }
2392 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2393 isn->isn_arg.subs.subs_instr = instr;
2394
2395 // skip over flags
2396 if (*end == '&')
2397 ++end;
2398 while (ASCII_ISALPHA(*end) || *end == '#')
2399 ++end;
2400 return end;
2401 }
2402 }
2403
2404 return compile_exec(arg, eap, cctx);
2405}
2406
2407 char_u *
2408compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2409{
2410 char_u *arg = eap->arg;
2411 lhs_T *lhs = &cctx->ctx_redir_lhs;
2412
2413 if (lhs->lhs_name != NULL)
2414 {
2415 if (STRNCMP(arg, "END", 3) == 0)
2416 {
2417 if (lhs->lhs_append)
2418 {
2419 // First load the current variable value.
2420 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
2421 cctx) == FAIL)
2422 return NULL;
2423 }
2424
2425 // Gets the redirected text and put it on the stack, then store it
2426 // in the variable.
2427 generate_instr_type(cctx, ISN_REDIREND, &t_string);
2428
2429 if (lhs->lhs_append)
LemonBoy372bcce2022-04-25 12:43:20 +01002430 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002431
2432 if (lhs->lhs_has_index)
2433 {
2434 // Use the info in "lhs" to store the value at the index in the
2435 // list or dict.
2436 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
2437 &t_string, cctx) == FAIL)
2438 return NULL;
2439 }
Bram Moolenaar5cd64792021-12-25 18:23:24 +00002440 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002441 return NULL;
2442
2443 VIM_CLEAR(lhs->lhs_name);
2444 VIM_CLEAR(lhs->lhs_whole);
2445 return arg + 3;
2446 }
2447 emsg(_(e_cannot_nest_redir));
2448 return NULL;
2449 }
2450
2451 if (arg[0] == '=' && arg[1] == '>')
2452 {
2453 int append = FALSE;
2454
2455 // redirect to a variable is compiled
2456 arg += 2;
2457 if (*arg == '>')
2458 {
2459 ++arg;
2460 append = TRUE;
2461 }
2462 arg = skipwhite(arg);
2463
2464 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002465 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002466 return NULL;
2467 if (need_type(&t_string, lhs->lhs_member_type,
2468 -1, 0, cctx, FALSE, FALSE) == FAIL)
2469 return NULL;
2470 generate_instr(cctx, ISN_REDIRSTART);
2471 lhs->lhs_append = append;
2472 if (lhs->lhs_has_index)
2473 {
2474 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2475 if (lhs->lhs_whole == NULL)
2476 return NULL;
2477 }
2478
2479 return arg + lhs->lhs_varlen_total;
2480 }
2481
2482 // other redirects are handled like at script level
2483 return compile_exec(line, eap, cctx);
2484}
2485
2486#if defined(FEAT_QUICKFIX) || defined(PROTO)
2487 char_u *
2488compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2489{
2490 isn_T *isn;
2491 char_u *p;
2492
2493 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2494 if (isn == NULL)
2495 return NULL;
2496 isn->isn_arg.number = eap->cmdidx;
2497
2498 p = eap->arg;
2499 if (compile_expr0(&p, cctx) == FAIL)
2500 return NULL;
2501
2502 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2503 if (isn == NULL)
2504 return NULL;
2505 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2506 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2507 return NULL;
2508 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2509 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2510 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2511
2512 return p;
2513}
2514#endif
2515
2516/*
2517 * Compile "return [expr]".
2518 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2519 */
2520 char_u *
2521compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2522{
2523 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002524 type_T *stack_type;
2525
2526 if (*p != NUL && *p != '|' && *p != '\n')
2527 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002528 // For a lambda, "return expr" is always used, also when "expr" results
2529 // in a void.
2530 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2531 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002532 {
2533 emsg(_(e_returning_value_in_function_without_return_type));
2534 return NULL;
2535 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002536 if (legacy)
2537 {
2538 int save_flags = cmdmod.cmod_flags;
2539
2540 generate_LEGACY_EVAL(cctx, p);
2541 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
2542 0, cctx, FALSE, FALSE) == FAIL)
2543 return NULL;
2544 cmdmod.cmod_flags |= CMOD_LEGACY;
2545 (void)skip_expr(&p, NULL);
2546 cmdmod.cmod_flags = save_flags;
2547 }
2548 else
2549 {
2550 // compile return argument into instructions
2551 if (compile_expr0(&p, cctx) == FAIL)
2552 return NULL;
2553 }
2554
2555 if (cctx->ctx_skip != SKIP_YES)
2556 {
2557 // "check_return_type" with uf_ret_type set to &t_unknown is used
2558 // for an inline function without a specified return type. Set the
2559 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002560 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002561 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002562 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002563 || (!check_return_type
2564 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2565 {
2566 cctx->ctx_ufunc->uf_ret_type = stack_type;
2567 }
2568 else
2569 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002570 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
2571 0, cctx, FALSE, FALSE) == FAIL)
2572 return NULL;
2573 }
2574 }
2575 }
2576 else
2577 {
2578 // "check_return_type" cannot be TRUE, only used for a lambda which
2579 // always has an argument.
2580 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2581 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2582 {
2583 emsg(_(e_missing_return_value));
2584 return NULL;
2585 }
2586
2587 // No argument, return zero.
2588 generate_PUSHNR(cctx, 0);
2589 }
2590
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002591 // may need ENDLOOP when inside a :for or :while loop
2592 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2593
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002594 // Undo any command modifiers.
2595 generate_undo_cmdmods(cctx);
2596
2597 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2598 return NULL;
2599
2600 // "return val | endif" is possible
2601 return skipwhite(p);
2602}
2603
2604/*
2605 * Check if the separator for a :global or :substitute command is OK.
2606 */
2607 int
2608check_global_and_subst(char_u *cmd, char_u *arg)
2609{
2610 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2611 {
2612 semsg(_(e_separator_not_supported_str), arg);
2613 return FAIL;
2614 }
2615 if (VIM_ISWHITE(cmd[1]))
2616 {
2617 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2618 return FAIL;
2619 }
2620 return OK;
2621}
2622
2623
2624#endif // defined(FEAT_EVAL)