blob: 3c561d1ef55ad51b2d599c2611ee7e3e974c20ec [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"
1974 * compile "execute expr"
1975 */
1976 char_u *
1977compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
1978{
1979 char_u *p = arg;
1980 char_u *prev = arg;
1981 char_u *expr_start;
1982 int count = 0;
1983 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001984 type_T *type;
1985
1986 for (;;)
1987 {
1988 if (ends_excmd2(prev, p))
1989 break;
1990 expr_start = p;
1991 if (compile_expr0(&p, cctx) == FAIL)
1992 return NULL;
1993
1994 if (cctx->ctx_skip != SKIP_YES)
1995 {
1996 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001997 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001998 if (type->tt_type == VAR_VOID)
1999 {
2000 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
2001 return NULL;
2002 }
2003 }
2004
2005 ++count;
2006 prev = p;
2007 p = skipwhite(p);
2008 }
2009
2010 if (count > 0)
2011 {
2012 long save_lnum = cctx->ctx_lnum;
2013
2014 // Use the line number where the command started.
2015 cctx->ctx_lnum = start_ctx_lnum;
2016
2017 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
2018 generate_ECHO(cctx, cmdidx == CMD_echo, count);
2019 else if (cmdidx == CMD_execute)
2020 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
2021 else if (cmdidx == CMD_echomsg)
2022 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002023#ifdef HAS_MESSAGE_WINDOW
2024 else if (cmdidx == CMD_echowindow)
2025 generate_MULT_EXPR(cctx, ISN_ECHOWINDOW, count);
2026#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002027 else if (cmdidx == CMD_echoconsole)
2028 generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
2029 else
2030 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
2031
2032 cctx->ctx_lnum = save_lnum;
2033 }
2034 return p;
2035}
2036
2037/*
2038 * If "eap" has a range that is not a constant generate an ISN_RANGE
2039 * instruction to compute it and return OK.
2040 * Otherwise return FAIL, the caller must deal with any range.
2041 */
2042 static int
2043compile_variable_range(exarg_T *eap, cctx_T *cctx)
2044{
2045 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
2046 char_u *p = skipdigits(eap->cmd);
2047
2048 if (p == range_end)
2049 return FAIL;
2050 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
2051}
2052
2053/*
2054 * :put r
2055 * :put ={expr}
2056 */
2057 char_u *
2058compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
2059{
2060 char_u *line = arg;
2061 linenr_T lnum;
2062 char *errormsg;
2063 int above = eap->forceit;
2064
2065 eap->regname = *line;
2066
2067 if (eap->regname == '=')
2068 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002069 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002070
2071 if (compile_expr0(&p, cctx) == FAIL)
2072 return NULL;
2073 line = p;
2074 }
2075 else if (eap->regname != NUL)
2076 ++line;
2077
2078 if (compile_variable_range(eap, cctx) == OK)
2079 {
2080 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2081 }
2082 else
2083 {
2084 // Either no range or a number.
2085 // "errormsg" will not be set because the range is ADDR_LINES.
2086 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2087 // cannot happen
2088 return NULL;
2089 if (eap->addr_count == 0)
2090 lnum = -1;
2091 else
2092 lnum = eap->line2;
2093 if (above)
2094 --lnum;
2095 }
2096
2097 generate_PUT(cctx, eap->regname, lnum);
2098 return line;
2099}
2100
2101/*
2102 * A command that is not compiled, execute with legacy code.
2103 */
2104 char_u *
2105compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2106{
2107 char_u *line = line_arg;
2108 char_u *p;
2109 int has_expr = FALSE;
2110 char_u *nextcmd = (char_u *)"";
2111 char_u *tofree = NULL;
2112 char_u *cmd_arg = NULL;
2113
2114 if (cctx->ctx_skip == SKIP_YES)
2115 goto theend;
2116
2117 // If there was a prececing command modifier, drop it and include it in the
2118 // EXEC command.
2119 if (cctx->ctx_has_cmdmod)
2120 {
2121 garray_T *instr = &cctx->ctx_instr;
2122 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2123
2124 if (isn->isn_type == ISN_CMDMOD)
2125 {
2126 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2127 ->cmod_filter_regmatch.regprog);
2128 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2129 --instr->ga_len;
2130 cctx->ctx_has_cmdmod = FALSE;
2131 }
2132 }
2133
2134 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2135 {
2136 long argt = eap->argt;
2137 int usefilter = FALSE;
2138
2139 has_expr = argt & (EX_XFILE | EX_EXPAND);
2140
2141 // If the command can be followed by a bar, find the bar and truncate
2142 // it, so that the following command can be compiled.
2143 // The '|' is overwritten with a NUL, it is put back below.
2144 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2145 && *eap->arg == '!')
2146 // :w !filter or :r !filter or :r! filter
2147 usefilter = TRUE;
2148 if ((argt & EX_TRLBAR) && !usefilter)
2149 {
2150 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002151 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002152 if (eap->nextcmd != NULL)
2153 nextcmd = eap->nextcmd;
2154 }
2155 else if (eap->cmdidx == CMD_wincmd)
2156 {
2157 p = eap->arg;
2158 if (*p != NUL)
2159 ++p;
2160 if (*p == 'g' || *p == Ctrl_G)
2161 ++p;
2162 p = skipwhite(p);
2163 if (*p == '|')
2164 {
2165 *p = NUL;
2166 nextcmd = p + 1;
2167 }
2168 }
2169 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2170 {
2171 // If there is a trailing '{' read lines until the '}'
2172 p = eap->arg + STRLEN(eap->arg) - 1;
2173 while (p > eap->arg && VIM_ISWHITE(*p))
2174 --p;
2175 if (*p == '{')
2176 {
2177 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002178 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002179 int start_lnum = SOURCING_LNUM;
2180
2181 CLEAR_FIELD(ea);
2182 ea.arg = eap->arg;
2183 fill_exarg_from_cctx(&ea, cctx);
2184 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2185 if (tofree != NULL)
2186 {
2187 *p = NUL;
2188 line = concat_str(line, tofree);
2189 if (line == NULL)
2190 goto theend;
2191 vim_free(tofree);
2192 tofree = line;
2193 SOURCING_LNUM = start_lnum;
2194 }
2195 }
2196 }
2197 }
2198
2199 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2200 {
2201 // expand filename in "syntax include [@group] filename"
2202 has_expr = TRUE;
2203 eap->arg = skipwhite(eap->arg + 7);
2204 if (*eap->arg == '@')
2205 eap->arg = skiptowhite(eap->arg);
2206 }
2207
2208 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2209 && STRLEN(eap->arg) > 4)
2210 {
2211 int delim = *eap->arg;
2212
2213 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2214 if (*p == delim)
2215 cmd_arg = p + 1;
2216 }
2217
2218 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2219 cmd_arg = eap->arg;
2220
2221 if (cmd_arg != NULL)
2222 {
2223 exarg_T nea;
2224
2225 CLEAR_FIELD(nea);
2226 nea.cmd = cmd_arg;
2227 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2228 if (nea.cmdidx < CMD_SIZE)
2229 {
2230 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2231 if (has_expr)
2232 eap->arg = skiptowhite(eap->arg);
2233 }
2234 }
2235
2236 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2237 {
2238 int count = 0;
2239 char_u *start = skipwhite(line);
2240
2241 // :cmd xxx`=expr1`yyy`=expr2`zzz
2242 // PUSHS ":cmd xxx"
2243 // eval expr1
2244 // PUSHS "yyy"
2245 // eval expr2
2246 // PUSHS "zzz"
2247 // EXECCONCAT 5
2248 for (;;)
2249 {
2250 if (p > start)
2251 {
2252 char_u *val = vim_strnsave(start, p - start);
2253
2254 generate_PUSHS(cctx, &val);
2255 ++count;
2256 }
2257 p += 2;
2258 if (compile_expr0(&p, cctx) == FAIL)
2259 return NULL;
2260 may_generate_2STRING(-1, TRUE, cctx);
2261 ++count;
2262 p = skipwhite(p);
2263 if (*p != '`')
2264 {
2265 emsg(_(e_missing_backtick));
2266 return NULL;
2267 }
2268 start = p + 1;
2269
2270 p = (char_u *)strstr((char *)start, "`=");
2271 if (p == NULL)
2272 {
2273 if (*skipwhite(start) != NUL)
2274 {
2275 char_u *val = vim_strsave(start);
2276
2277 generate_PUSHS(cctx, &val);
2278 ++count;
2279 }
2280 break;
2281 }
2282 }
2283 generate_EXECCONCAT(cctx, count);
2284 }
2285 else
2286 generate_EXEC_copy(cctx, ISN_EXEC, line);
2287
2288theend:
2289 if (*nextcmd != NUL)
2290 {
2291 // the parser expects a pointer to the bar, put it back
2292 --nextcmd;
2293 *nextcmd = '|';
2294 }
2295 vim_free(tofree);
2296
2297 return nextcmd;
2298}
2299
2300/*
2301 * A script command with heredoc, e.g.
2302 * ruby << EOF
2303 * command
2304 * EOF
2305 * Has been turned into one long line with NL characters by
2306 * get_function_body():
2307 * ruby << EOF<NL> command<NL>EOF
2308 */
2309 char_u *
2310compile_script(char_u *line, cctx_T *cctx)
2311{
2312 if (cctx->ctx_skip != SKIP_YES)
2313 {
2314 isn_T *isn;
2315
2316 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2317 return NULL;
2318 isn->isn_arg.string = vim_strsave(line);
2319 }
2320 return (char_u *)"";
2321}
2322
2323
2324/*
2325 * :s/pat/repl/
2326 */
2327 char_u *
2328compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2329{
2330 char_u *cmd = eap->arg;
2331 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2332
2333 if (expr != NULL)
2334 {
2335 int delimiter = *cmd++;
2336
2337 // There is a \=expr, find it in the substitute part.
2338 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2339 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2340 {
2341 garray_T save_ga = cctx->ctx_instr;
2342 char_u *end;
2343 int expr_res;
2344 int trailing_error;
2345 int instr_count;
2346 isn_T *instr;
2347 isn_T *isn;
2348
2349 cmd += 3;
2350 end = skip_substitute(cmd, delimiter);
2351
2352 // Temporarily reset the list of instructions so that the jump
2353 // labels are correct.
2354 cctx->ctx_instr.ga_len = 0;
2355 cctx->ctx_instr.ga_maxlen = 0;
2356 cctx->ctx_instr.ga_data = NULL;
2357 expr_res = compile_expr0(&cmd, cctx);
2358 if (end[-1] == NUL)
2359 end[-1] = delimiter;
2360 cmd = skipwhite(cmd);
2361 trailing_error = *cmd != delimiter && *cmd != NUL;
2362
2363 if (expr_res == FAIL || trailing_error
2364 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2365 {
2366 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002367 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002368 clear_instr_ga(&cctx->ctx_instr);
2369 cctx->ctx_instr = save_ga;
2370 return NULL;
2371 }
2372
2373 // Move the generated instructions into the ISN_SUBSTITUTE
2374 // instructions, then restore the list of instructions before
2375 // adding the ISN_SUBSTITUTE instruction.
2376 instr_count = cctx->ctx_instr.ga_len;
2377 instr = cctx->ctx_instr.ga_data;
2378 instr[instr_count].isn_type = ISN_FINISH;
2379
2380 cctx->ctx_instr = save_ga;
2381 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2382 {
2383 int idx;
2384
2385 for (idx = 0; idx < instr_count; ++idx)
2386 delete_instr(instr + idx);
2387 vim_free(instr);
2388 return NULL;
2389 }
2390 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2391 isn->isn_arg.subs.subs_instr = instr;
2392
2393 // skip over flags
2394 if (*end == '&')
2395 ++end;
2396 while (ASCII_ISALPHA(*end) || *end == '#')
2397 ++end;
2398 return end;
2399 }
2400 }
2401
2402 return compile_exec(arg, eap, cctx);
2403}
2404
2405 char_u *
2406compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2407{
2408 char_u *arg = eap->arg;
2409 lhs_T *lhs = &cctx->ctx_redir_lhs;
2410
2411 if (lhs->lhs_name != NULL)
2412 {
2413 if (STRNCMP(arg, "END", 3) == 0)
2414 {
2415 if (lhs->lhs_append)
2416 {
2417 // First load the current variable value.
2418 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
2419 cctx) == FAIL)
2420 return NULL;
2421 }
2422
2423 // Gets the redirected text and put it on the stack, then store it
2424 // in the variable.
2425 generate_instr_type(cctx, ISN_REDIREND, &t_string);
2426
2427 if (lhs->lhs_append)
LemonBoy372bcce2022-04-25 12:43:20 +01002428 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002429
2430 if (lhs->lhs_has_index)
2431 {
2432 // Use the info in "lhs" to store the value at the index in the
2433 // list or dict.
2434 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
2435 &t_string, cctx) == FAIL)
2436 return NULL;
2437 }
Bram Moolenaar5cd64792021-12-25 18:23:24 +00002438 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002439 return NULL;
2440
2441 VIM_CLEAR(lhs->lhs_name);
2442 VIM_CLEAR(lhs->lhs_whole);
2443 return arg + 3;
2444 }
2445 emsg(_(e_cannot_nest_redir));
2446 return NULL;
2447 }
2448
2449 if (arg[0] == '=' && arg[1] == '>')
2450 {
2451 int append = FALSE;
2452
2453 // redirect to a variable is compiled
2454 arg += 2;
2455 if (*arg == '>')
2456 {
2457 ++arg;
2458 append = TRUE;
2459 }
2460 arg = skipwhite(arg);
2461
2462 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002463 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002464 return NULL;
2465 if (need_type(&t_string, lhs->lhs_member_type,
2466 -1, 0, cctx, FALSE, FALSE) == FAIL)
2467 return NULL;
2468 generate_instr(cctx, ISN_REDIRSTART);
2469 lhs->lhs_append = append;
2470 if (lhs->lhs_has_index)
2471 {
2472 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2473 if (lhs->lhs_whole == NULL)
2474 return NULL;
2475 }
2476
2477 return arg + lhs->lhs_varlen_total;
2478 }
2479
2480 // other redirects are handled like at script level
2481 return compile_exec(line, eap, cctx);
2482}
2483
2484#if defined(FEAT_QUICKFIX) || defined(PROTO)
2485 char_u *
2486compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2487{
2488 isn_T *isn;
2489 char_u *p;
2490
2491 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2492 if (isn == NULL)
2493 return NULL;
2494 isn->isn_arg.number = eap->cmdidx;
2495
2496 p = eap->arg;
2497 if (compile_expr0(&p, cctx) == FAIL)
2498 return NULL;
2499
2500 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2501 if (isn == NULL)
2502 return NULL;
2503 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2504 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2505 return NULL;
2506 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2507 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2508 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2509
2510 return p;
2511}
2512#endif
2513
2514/*
2515 * Compile "return [expr]".
2516 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2517 */
2518 char_u *
2519compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2520{
2521 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002522 type_T *stack_type;
2523
2524 if (*p != NUL && *p != '|' && *p != '\n')
2525 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002526 // For a lambda, "return expr" is always used, also when "expr" results
2527 // in a void.
2528 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2529 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002530 {
2531 emsg(_(e_returning_value_in_function_without_return_type));
2532 return NULL;
2533 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002534 if (legacy)
2535 {
2536 int save_flags = cmdmod.cmod_flags;
2537
2538 generate_LEGACY_EVAL(cctx, p);
2539 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
2540 0, cctx, FALSE, FALSE) == FAIL)
2541 return NULL;
2542 cmdmod.cmod_flags |= CMOD_LEGACY;
2543 (void)skip_expr(&p, NULL);
2544 cmdmod.cmod_flags = save_flags;
2545 }
2546 else
2547 {
2548 // compile return argument into instructions
2549 if (compile_expr0(&p, cctx) == FAIL)
2550 return NULL;
2551 }
2552
2553 if (cctx->ctx_skip != SKIP_YES)
2554 {
2555 // "check_return_type" with uf_ret_type set to &t_unknown is used
2556 // for an inline function without a specified return type. Set the
2557 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002558 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002559 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002560 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002561 || (!check_return_type
2562 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2563 {
2564 cctx->ctx_ufunc->uf_ret_type = stack_type;
2565 }
2566 else
2567 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002568 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
2569 0, cctx, FALSE, FALSE) == FAIL)
2570 return NULL;
2571 }
2572 }
2573 }
2574 else
2575 {
2576 // "check_return_type" cannot be TRUE, only used for a lambda which
2577 // always has an argument.
2578 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2579 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2580 {
2581 emsg(_(e_missing_return_value));
2582 return NULL;
2583 }
2584
2585 // No argument, return zero.
2586 generate_PUSHNR(cctx, 0);
2587 }
2588
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002589 // may need ENDLOOP when inside a :for or :while loop
2590 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2591
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002592 // Undo any command modifiers.
2593 generate_undo_cmdmods(cctx);
2594
2595 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2596 return NULL;
2597
2598 // "return val | endif" is possible
2599 return skipwhite(p);
2600}
2601
2602/*
2603 * Check if the separator for a :global or :substitute command is OK.
2604 */
2605 int
2606check_global_and_subst(char_u *cmd, char_u *arg)
2607{
2608 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2609 {
2610 semsg(_(e_separator_not_supported_str), arg);
2611 return FAIL;
2612 }
2613 if (VIM_ISWHITE(cmd[1]))
2614 {
2615 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2616 return FAIL;
2617 }
2618 return OK;
2619}
2620
2621
2622#endif // defined(FEAT_EVAL)