blob: c9c222c470c471ddbf32043546c9e213bfd881c3 [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.
884 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
885 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.
897 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
898 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;
1053 var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
1054 if (var_lvar == NULL)
1055 // out of memory or used as an argument
1056 goto failed;
1057
1058 if (semicolon && idx == var_count - 1)
1059 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001060 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1061 }
1062
1063 if (*p == ',' || *p == ';')
1064 ++p;
1065 arg = skipwhite(p);
1066 vim_free(name);
1067 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001068
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001069 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001070 compile_fill_loop_info(&forscope->fs_loop_info, funcref_lvar_idx, cctx);
1071 forscope->fs_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001072 }
1073
1074 return arg_end;
1075
1076failed:
1077 vim_free(name);
1078 drop_scope(cctx);
1079 return NULL;
1080}
1081
1082/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001083 * Used when ending a loop of :for and :while: Generate an ISN_ENDLOOP
1084 * instruction if any variable was declared that could be used by a new
1085 * closure.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001086 */
1087 static int
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001088compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001089{
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001090 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1091 && cctx->ctx_closure_count > loop_info->li_closure_count)
Bram Moolenaarcc341812022-09-19 15:54:34 +01001092 return generate_ENDLOOP(cctx, loop_info);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001093 return OK;
1094}
1095
1096/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001097 * compile "endfor"
1098 */
1099 char_u *
1100compile_endfor(char_u *arg, cctx_T *cctx)
1101{
1102 garray_T *instr = &cctx->ctx_instr;
1103 scope_T *scope = cctx->ctx_scope;
1104 forscope_T *forscope;
1105 isn_T *isn;
1106
1107 if (misplaced_cmdmod(cctx))
1108 return NULL;
1109
1110 if (scope == NULL || scope->se_type != FOR_SCOPE)
1111 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001112 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001113 return NULL;
1114 }
1115 forscope = &scope->se_u.se_for;
1116 cctx->ctx_scope = scope->se_outer;
1117 if (cctx->ctx_skip != SKIP_YES)
1118 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001119 // Handle the case that any local variables were declared that might be
1120 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001121 if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001122 return NULL;
1123
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001124 unwind_locals(cctx, scope->se_local_count);
1125
1126 // At end of ":for" scope jump back to the FOR instruction.
1127 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1128
1129 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001130 // In debug mode an ISN_DEBUG was inserted.
1131 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1132 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001133 isn->isn_arg.forloop.for_end = instr->ga_len;
1134
1135 // Fill in the "end" label any BREAK statements
1136 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1137
1138 // Below the ":for" scope drop the "expr" list from the stack.
1139 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1140 return NULL;
1141 }
1142
1143 vim_free(scope);
1144
1145 return arg;
1146}
1147
1148/*
1149 * compile "while expr"
1150 *
1151 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001152 * top: EVAL expr Push result of "expr"
1153 * WHILE funcref-idx end Jump if false
1154 * ... body ...
1155 * ENDLOOP funcref-idx off count only if closure uses local var
1156 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001157 * end:
1158 *
1159 */
1160 char_u *
1161compile_while(char_u *arg, cctx_T *cctx)
1162{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001163 char_u *p = arg;
1164 scope_T *scope;
1165 whilescope_T *whilescope;
1166 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001167 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001168
1169 scope = new_scope(cctx, WHILE_SCOPE);
1170 if (scope == NULL)
1171 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001172 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
1173 {
1174 emsg(_(e_loop_nesting_too_deep));
1175 return NULL;
1176 }
1177 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001178 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001179
1180 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001181 whilescope->ws_top_label = current_instr_idx(cctx);
1182
1183 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1184 // It is not used when no closures are encountered, we don't know yet.
1185 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
1186 if (funcref_lvar == NULL)
1187 {
1188 drop_scope(cctx);
1189 return NULL; // out of memory
1190 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001191 // get the index before a following reserve_local() makes the lval invalid
1192 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001193
1194 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001195 compile_fill_loop_info(&whilescope->ws_loop_info, funcref_lvar_idx, cctx);
1196 whilescope->ws_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001197
1198 // compile "expr"
1199 if (compile_expr0(&p, cctx) == FAIL)
1200 return NULL;
1201
1202 if (!ends_excmd2(arg, skipwhite(p)))
1203 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001204 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001205 return NULL;
1206 }
1207
1208 if (cctx->ctx_skip != SKIP_YES)
1209 {
1210 if (bool_on_stack(cctx) == FAIL)
1211 return FAIL;
1212
1213 // CMDMOD_REV must come before the jump
1214 generate_undo_cmdmods(cctx);
1215
1216 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001217 if (compile_jump_to_end(&whilescope->ws_end_label,
Bram Moolenaarcc341812022-09-19 15:54:34 +01001218 JUMP_WHILE_FALSE, funcref_lvar_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001219 return FAIL;
1220 }
1221
1222 return p;
1223}
1224
1225/*
1226 * compile "endwhile"
1227 */
1228 char_u *
1229compile_endwhile(char_u *arg, cctx_T *cctx)
1230{
1231 scope_T *scope = cctx->ctx_scope;
1232 garray_T *instr = &cctx->ctx_instr;
1233
1234 if (misplaced_cmdmod(cctx))
1235 return NULL;
1236 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1237 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001238 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001239 return NULL;
1240 }
1241 cctx->ctx_scope = scope->se_outer;
1242 if (cctx->ctx_skip != SKIP_YES)
1243 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001244 whilescope_T *whilescope = &scope->se_u.se_while;
1245
1246 // Handle the case that any local variables were declared that might be
1247 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001248 if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001249 return NULL;
1250
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001251 unwind_locals(cctx, scope->se_local_count);
1252
1253#ifdef FEAT_PROFILE
1254 // count the endwhile before jumping
1255 may_generate_prof_end(cctx, cctx->ctx_lnum);
1256#endif
1257
1258 // At end of ":for" scope jump back to the FOR instruction.
1259 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1260
1261 // Fill in the "end" label in the WHILE statement so it can jump here.
1262 // And in any jumps for ":break"
1263 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1264 instr->ga_len, cctx);
1265 }
1266
1267 vim_free(scope);
1268
1269 return arg;
1270}
1271
1272/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001273 * Get the current information about variables declared inside a loop.
Bram Moolenaarcc341812022-09-19 15:54:34 +01001274 * Returns TRUE if there are any and fills "lvi".
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001275 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001276 int
1277get_loop_var_info(cctx_T *cctx, loopvarinfo_T *lvi)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001278{
1279 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001280 int prev_local_count = 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001281
Bram Moolenaarcc341812022-09-19 15:54:34 +01001282 CLEAR_POINTER(lvi);
1283 for (;;)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001284 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01001285 loop_info_T *loopinfo;
1286 int cur_local_last;
1287 int start_local_count;
1288
1289 while (scope != NULL && scope->se_type != WHILE_SCOPE
1290 && scope->se_type != FOR_SCOPE)
1291 scope = scope->se_outer;
1292 if (scope == NULL)
1293 break;
1294
1295 if (scope->se_type == WHILE_SCOPE)
1296 {
1297 loopinfo = &scope->se_u.se_while.ws_loop_info;
1298 // :while reserves one variable for funcref count
1299 cur_local_last = loopinfo->li_local_count - 1;
1300 }
1301 else
1302 {
1303 loopinfo = &scope->se_u.se_for.fs_loop_info;
1304 // :for reserves three variable: loop count, funcref count and loop
1305 // var
1306 cur_local_last = loopinfo->li_local_count - 3;
1307 }
1308
1309 start_local_count = loopinfo->li_local_count;
1310 if (cctx->ctx_locals.ga_len > start_local_count)
1311 {
1312 lvi->lvi_loop[loopinfo->li_depth].var_idx =
1313 (short)start_local_count;
1314 lvi->lvi_loop[loopinfo->li_depth].var_count =
1315 (short)(cctx->ctx_locals.ga_len - start_local_count
1316 - prev_local_count);
1317 if (lvi->lvi_depth == 0)
1318 lvi->lvi_depth = loopinfo->li_depth + 1;
1319 }
1320
1321 scope = scope->se_outer;
1322 prev_local_count = cctx->ctx_locals.ga_len - cur_local_last;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001323 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001324 return lvi->lvi_depth > 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001325}
1326
1327/*
Bram Moolenaarcc341812022-09-19 15:54:34 +01001328 * Get the index of the variable "idx" in a loop, if any.
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001329 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001330 void
1331get_loop_var_idx(cctx_T *cctx, int idx, lvar_T *lvar)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001332{
Bram Moolenaarcc341812022-09-19 15:54:34 +01001333 loopvarinfo_T lvi;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001334
Bram Moolenaarcc341812022-09-19 15:54:34 +01001335 lvar->lv_loop_depth = -1;
1336 lvar->lv_loop_idx = -1;
1337 if (get_loop_var_info(cctx, &lvi))
1338 {
1339 int depth;
1340
1341 for (depth = lvi.lvi_depth - 1; depth >= 0; --depth)
1342 if (idx >= lvi.lvi_loop[depth].var_idx
1343 && idx < lvi.lvi_loop[depth].var_idx
1344 + lvi.lvi_loop[depth].var_count)
1345 {
1346 lvar->lv_loop_depth = depth;
1347 lvar->lv_loop_idx = lvi.lvi_loop[depth].var_idx;
1348 return;
1349 }
1350 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001351}
1352
1353/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001354 * Common for :break, :continue and :return
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001355 */
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001356 static int
1357compile_find_scope(
1358 int *loop_label, // where to jump to or NULL
1359 endlabel_T ***el, // end label or NULL
1360 int *try_scopes, // :try scopes encountered or NULL
1361 char *error, // error to use when no scope found
1362 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001363{
1364 scope_T *scope = cctx->ctx_scope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001365
1366 for (;;)
1367 {
1368 if (scope == NULL)
1369 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001370 if (error != NULL)
1371 emsg(_(error));
1372 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001373 }
1374 if (scope->se_type == FOR_SCOPE)
1375 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001376 if (compile_loop_end(&scope->se_u.se_for.fs_loop_info, cctx)
1377 == FAIL)
1378 return FAIL;
1379 if (loop_label != NULL)
1380 *loop_label = scope->se_u.se_for.fs_top_label;
1381 if (el != NULL)
1382 *el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001383 break;
1384 }
1385 if (scope->se_type == WHILE_SCOPE)
1386 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001387 if (compile_loop_end(&scope->se_u.se_while.ws_loop_info, cctx)
1388 == FAIL)
1389 return FAIL;
1390 if (loop_label != NULL)
1391 *loop_label = scope->se_u.se_while.ws_top_label;
1392 if (el != NULL)
1393 *el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001394 break;
1395 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001396 if (try_scopes != NULL && scope->se_type == TRY_SCOPE)
1397 ++*try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001398 scope = scope->se_outer;
1399 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001400 return OK;
1401}
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001402
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001403/*
1404 * compile "continue"
1405 */
1406 char_u *
1407compile_continue(char_u *arg, cctx_T *cctx)
1408{
1409 int try_scopes = 0;
1410 int loop_label;
1411
1412 if (compile_find_scope(&loop_label, NULL, &try_scopes,
1413 e_continue_without_while_or_for, cctx) == FAIL)
1414 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001415 if (try_scopes > 0)
1416 // Inside one or more try/catch blocks we first need to jump to the
1417 // "finally" or "endtry" to cleanup.
1418 generate_TRYCONT(cctx, try_scopes, loop_label);
1419 else
1420 // Jump back to the FOR or WHILE instruction.
1421 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1422
1423 return arg;
1424}
1425
1426/*
1427 * compile "break"
1428 */
1429 char_u *
1430compile_break(char_u *arg, cctx_T *cctx)
1431{
Bram Moolenaar873f8242022-03-10 21:53:44 +00001432 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001433 endlabel_T **el;
1434
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001435 if (compile_find_scope(NULL, &el, &try_scopes,
1436 e_break_without_while_or_for, cctx) == FAIL)
1437 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001438
Bram Moolenaar873f8242022-03-10 21:53:44 +00001439 if (try_scopes > 0)
1440 // Inside one or more try/catch blocks we first need to jump to the
1441 // "finally" or "endtry" to cleanup. Then come to the next JUMP
1442 // intruction, which we don't know the index of yet.
1443 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1444
1445 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1446 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001447 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001448 return FAIL;
1449
1450 return arg;
1451}
1452
1453/*
1454 * compile "{" start of block
1455 */
1456 char_u *
1457compile_block(char_u *arg, cctx_T *cctx)
1458{
1459 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1460 return NULL;
1461 return skipwhite(arg + 1);
1462}
1463
1464/*
1465 * compile end of block: drop one scope
1466 */
1467 void
1468compile_endblock(cctx_T *cctx)
1469{
1470 scope_T *scope = cctx->ctx_scope;
1471
1472 cctx->ctx_scope = scope->se_outer;
1473 unwind_locals(cctx, scope->se_local_count);
1474 vim_free(scope);
1475}
1476
1477/*
1478 * Compile "try".
1479 * Creates a new scope for the try-endtry, pointing to the first catch and
1480 * finally.
1481 * Creates another scope for the "try" block itself.
1482 * TRY instruction sets up exception handling at runtime.
1483 *
1484 * "try"
1485 * TRY -> catch1, -> finally push trystack entry
1486 * ... try block
1487 * "throw {exception}"
1488 * EVAL {exception}
1489 * THROW create exception
1490 * ... try block
1491 * " catch {expr}"
1492 * JUMP -> finally
1493 * catch1: PUSH exception
1494 * EVAL {expr}
1495 * MATCH
1496 * JUMP nomatch -> catch2
1497 * CATCH remove exception
1498 * ... catch block
1499 * " catch"
1500 * JUMP -> finally
1501 * catch2: CATCH remove exception
1502 * ... catch block
1503 * " finally"
1504 * finally:
1505 * ... finally block
1506 * " endtry"
1507 * ENDTRY pop trystack entry, may rethrow
1508 */
1509 char_u *
1510compile_try(char_u *arg, cctx_T *cctx)
1511{
1512 garray_T *instr = &cctx->ctx_instr;
1513 scope_T *try_scope;
1514 scope_T *scope;
1515
1516 if (misplaced_cmdmod(cctx))
1517 return NULL;
1518
1519 // scope that holds the jumps that go to catch/finally/endtry
1520 try_scope = new_scope(cctx, TRY_SCOPE);
1521 if (try_scope == NULL)
1522 return NULL;
1523
1524 if (cctx->ctx_skip != SKIP_YES)
1525 {
1526 isn_T *isn;
1527
1528 // "try_catch" is set when the first ":catch" is found or when no catch
1529 // is found and ":finally" is found.
1530 // "try_finally" is set when ":finally" is found
1531 // "try_endtry" is set when ":endtry" is found
1532 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1533 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1534 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001535 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1536 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001537 return NULL;
1538 }
1539
1540 // scope for the try block itself
1541 scope = new_scope(cctx, BLOCK_SCOPE);
1542 if (scope == NULL)
1543 return NULL;
1544
1545 return arg;
1546}
1547
1548/*
1549 * Compile "catch {expr}".
1550 */
1551 char_u *
1552compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1553{
1554 scope_T *scope = cctx->ctx_scope;
1555 garray_T *instr = &cctx->ctx_instr;
1556 char_u *p;
1557 isn_T *isn;
1558
1559 if (misplaced_cmdmod(cctx))
1560 return NULL;
1561
1562 // end block scope from :try or :catch
1563 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1564 compile_endblock(cctx);
1565 scope = cctx->ctx_scope;
1566
1567 // Error if not in a :try scope
1568 if (scope == NULL || scope->se_type != TRY_SCOPE)
1569 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001570 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001571 return NULL;
1572 }
1573
1574 if (scope->se_u.se_try.ts_caught_all)
1575 {
1576 emsg(_(e_catch_unreachable_after_catch_all));
1577 return NULL;
1578 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001579 if (!cctx->ctx_had_return)
1580 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001581
1582 if (cctx->ctx_skip != SKIP_YES)
1583 {
1584#ifdef FEAT_PROFILE
1585 // the profile-start should be after the jump
1586 if (cctx->ctx_compile_type == CT_PROFILE
1587 && instr->ga_len > 0
1588 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1589 .isn_type == ISN_PROF_START)
1590 --instr->ga_len;
1591#endif
1592 // Jump from end of previous block to :finally or :endtry
1593 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001594 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001595 return NULL;
1596
1597 // End :try or :catch scope: set value in ISN_TRY instruction
1598 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001599 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1600 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001601 if (scope->se_u.se_try.ts_catch_label != 0)
1602 {
1603 // Previous catch without match jumps here
1604 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1605 isn->isn_arg.jump.jump_where = instr->ga_len;
1606 }
1607#ifdef FEAT_PROFILE
1608 if (cctx->ctx_compile_type == CT_PROFILE)
1609 {
1610 // a "throw" that jumps here needs to be counted
1611 generate_instr(cctx, ISN_PROF_END);
1612 // the "catch" is also counted
1613 generate_instr(cctx, ISN_PROF_START);
1614 }
1615#endif
1616 if (cctx->ctx_compile_type == CT_DEBUG)
1617 generate_instr_debug(cctx);
1618 }
1619
1620 p = skipwhite(arg);
1621 if (ends_excmd2(arg, p))
1622 {
1623 scope->se_u.se_try.ts_caught_all = TRUE;
1624 scope->se_u.se_try.ts_catch_label = 0;
1625 }
1626 else
1627 {
1628 char_u *end;
1629 char_u *pat;
1630 char_u *tofree = NULL;
1631 int dropped = 0;
1632 int len;
1633
1634 // Push v:exception, push {expr} and MATCH
1635 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1636
1637 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1638 if (*end != *p)
1639 {
1640 semsg(_(e_separator_mismatch_str), p);
1641 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001642 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001643 }
1644 if (tofree == NULL)
1645 len = (int)(end - (p + 1));
1646 else
1647 len = (int)(end - tofree);
1648 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1649 vim_free(tofree);
1650 p += len + 2 + dropped;
1651 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001652 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001653 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001654 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001655
1656 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1657 return NULL;
1658
1659 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1660 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1661 return NULL;
1662 }
1663
1664 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1665 return NULL;
1666
1667 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1668 return NULL;
1669 return p;
1670}
1671
1672 char_u *
1673compile_finally(char_u *arg, cctx_T *cctx)
1674{
1675 scope_T *scope = cctx->ctx_scope;
1676 garray_T *instr = &cctx->ctx_instr;
1677 isn_T *isn;
1678 int this_instr;
1679
1680 if (misplaced_cmdmod(cctx))
1681 return NULL;
1682
1683 // end block scope from :try or :catch
1684 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1685 compile_endblock(cctx);
1686 scope = cctx->ctx_scope;
1687
1688 // Error if not in a :try scope
1689 if (scope == NULL || scope->se_type != TRY_SCOPE)
1690 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001691 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001692 return NULL;
1693 }
1694
1695 if (cctx->ctx_skip != SKIP_YES)
1696 {
1697 // End :catch or :finally scope: set value in ISN_TRY instruction
1698 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001699 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001700 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001701 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001702 return NULL;
1703 }
1704
1705 this_instr = instr->ga_len;
1706#ifdef FEAT_PROFILE
1707 if (cctx->ctx_compile_type == CT_PROFILE
1708 && ((isn_T *)instr->ga_data)[this_instr - 1]
1709 .isn_type == ISN_PROF_START)
1710 {
1711 // jump to the profile start of the "finally"
1712 --this_instr;
1713
1714 // jump to the profile end above it
1715 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1716 .isn_type == ISN_PROF_END)
1717 --this_instr;
1718 }
1719#endif
1720
1721 // Fill in the "end" label in jumps at the end of the blocks.
1722 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1723 this_instr, cctx);
1724
1725 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001726 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1727 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1728 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001729 if (scope->se_u.se_try.ts_catch_label != 0)
1730 {
1731 // Previous catch without match jumps here
1732 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1733 isn->isn_arg.jump.jump_where = this_instr;
1734 scope->se_u.se_try.ts_catch_label = 0;
1735 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001736 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001737 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1738 return NULL;
1739 }
1740
1741 return arg;
1742}
1743
1744 char_u *
1745compile_endtry(char_u *arg, cctx_T *cctx)
1746{
1747 scope_T *scope = cctx->ctx_scope;
1748 garray_T *instr = &cctx->ctx_instr;
1749 isn_T *try_isn;
1750
1751 if (misplaced_cmdmod(cctx))
1752 return NULL;
1753
1754 // end block scope from :catch or :finally
1755 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1756 compile_endblock(cctx);
1757 scope = cctx->ctx_scope;
1758
1759 // Error if not in a :try scope
1760 if (scope == NULL || scope->se_type != TRY_SCOPE)
1761 {
1762 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001763 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001764 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001765 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001766 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001767 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001768 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001769 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001770 return NULL;
1771 }
1772
1773 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1774 if (cctx->ctx_skip != SKIP_YES)
1775 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001776 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1777 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001778 {
1779 emsg(_(e_missing_catch_or_finally));
1780 return NULL;
1781 }
1782
1783#ifdef FEAT_PROFILE
1784 if (cctx->ctx_compile_type == CT_PROFILE
1785 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1786 .isn_type == ISN_PROF_START)
1787 // move the profile start after "endtry" so that it's not counted when
1788 // the exception is rethrown.
1789 --instr->ga_len;
1790#endif
1791
1792 // Fill in the "end" label in jumps at the end of the blocks, if not
1793 // done by ":finally".
1794 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1795 instr->ga_len, cctx);
1796
1797 if (scope->se_u.se_try.ts_catch_label != 0)
1798 {
1799 // Last catch without match jumps here
1800 isn_T *isn = ((isn_T *)instr->ga_data)
1801 + scope->se_u.se_try.ts_catch_label;
1802 isn->isn_arg.jump.jump_where = instr->ga_len;
1803 }
1804 }
1805
Bram Moolenaar53c29612022-01-12 16:18:18 +00001806 // If there is a finally clause that ends in return then we will return.
1807 // If one of the blocks didn't end in "return" or we did not catch all
1808 // exceptions reset the had_return flag.
1809 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1810 && (scope->se_u.se_try.ts_no_return
1811 || !scope->se_u.se_try.ts_caught_all))
1812 cctx->ctx_had_return = FALSE;
1813
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001814 compile_endblock(cctx);
1815
1816 if (cctx->ctx_skip != SKIP_YES)
1817 {
1818 // End :catch or :finally scope: set instruction index in ISN_TRY
1819 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001820 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001821 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001822 return NULL;
1823#ifdef FEAT_PROFILE
1824 if (cctx->ctx_compile_type == CT_PROFILE)
1825 generate_instr(cctx, ISN_PROF_START);
1826#endif
1827 }
1828 return arg;
1829}
1830
1831/*
1832 * compile "throw {expr}"
1833 */
1834 char_u *
1835compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1836{
1837 char_u *p = skipwhite(arg);
1838
1839 if (compile_expr0(&p, cctx) == FAIL)
1840 return NULL;
1841 if (cctx->ctx_skip == SKIP_YES)
1842 return p;
1843 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1844 return NULL;
1845 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1846 return NULL;
1847
1848 return p;
1849}
1850
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001851/*
1852 * Compile an expression or function call.
1853 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001854 char_u *
1855compile_eval(char_u *arg, cctx_T *cctx)
1856{
1857 char_u *p = arg;
1858 int name_only;
1859 long lnum = SOURCING_LNUM;
1860
1861 // find_ex_command() will consider a variable name an expression, assuming
1862 // that something follows on the next line. Check that something actually
1863 // follows, otherwise it's probably a misplaced command.
1864 name_only = cmd_is_name_only(arg);
1865
1866 if (compile_expr0(&p, cctx) == FAIL)
1867 return NULL;
1868
1869 if (name_only && lnum == SOURCING_LNUM)
1870 {
1871 semsg(_(e_expression_without_effect_str), arg);
1872 return NULL;
1873 }
1874
1875 // drop the result
1876 generate_instr_drop(cctx, ISN_DROP, 1);
1877
1878 return skipwhite(p);
1879}
1880
1881/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001882 * Get the local variable index for deferred function calls.
1883 * Reserve it when not done already.
1884 * Returns zero for failure.
1885 */
1886 int
1887get_defer_var_idx(cctx_T *cctx)
1888{
1889 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1890 + cctx->ctx_ufunc->uf_dfunc_idx;
1891 if (dfunc->df_defer_var_idx == 0)
1892 {
1893 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1894 TRUE, &t_list_any);
1895 if (lvar == NULL)
1896 return 0;
1897 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1898 }
1899 return dfunc->df_defer_var_idx;
1900}
1901
1902/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001903 * Compile "defer func(arg)".
1904 */
1905 char_u *
1906compile_defer(char_u *arg_start, cctx_T *cctx)
1907{
Bram Moolenaar16900322022-09-08 19:51:45 +01001908 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001909 char_u *arg = arg_start;
1910 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001911 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001912 type_T *type;
1913 int func_idx;
1914
1915 // Get a funcref for the function name.
1916 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01001917 paren = vim_strchr(arg, '(');
1918 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001919 {
1920 semsg(_(e_missing_parenthesis_str), arg);
1921 return NULL;
1922 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001923 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001924 func_idx = find_internal_func(arg);
1925 if (func_idx >= 0)
1926 // TODO: better type
1927 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1928 &t_func_any, FALSE);
1929 else if (compile_expr0(&arg, cctx) == FAIL)
1930 return NULL;
Bram Moolenaar16900322022-09-08 19:51:45 +01001931 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001932
1933 // check for function type
1934 type = get_type_on_stack(cctx, 0);
1935 if (type->tt_type != VAR_FUNC)
1936 {
1937 emsg(_(e_function_name_required));
1938 return NULL;
1939 }
1940
1941 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01001942 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001943 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1944 return NULL;
1945
Bram Moolenaar16900322022-09-08 19:51:45 +01001946 if (func_idx >= 0)
1947 {
1948 type2_T *argtypes = NULL;
1949 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1950
1951 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
1952 &argtypes, shuffled_argtypes) == FAIL)
1953 return NULL;
1954 }
1955 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
1956 arg_start) == FAIL)
1957 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001958
Bram Moolenaar806a2732022-09-04 15:40:36 +01001959 defer_var_idx = get_defer_var_idx(cctx);
1960 if (defer_var_idx == 0)
1961 return NULL;
1962 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001963 return NULL;
1964
1965 return skipwhite(arg);
1966}
1967
1968/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001969 * compile "echo expr"
1970 * compile "echomsg expr"
1971 * compile "echoerr expr"
1972 * compile "echoconsole expr"
1973 * compile "execute expr"
1974 */
1975 char_u *
1976compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
1977{
1978 char_u *p = arg;
1979 char_u *prev = arg;
1980 char_u *expr_start;
1981 int count = 0;
1982 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001983 type_T *type;
1984
1985 for (;;)
1986 {
1987 if (ends_excmd2(prev, p))
1988 break;
1989 expr_start = p;
1990 if (compile_expr0(&p, cctx) == FAIL)
1991 return NULL;
1992
1993 if (cctx->ctx_skip != SKIP_YES)
1994 {
1995 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001996 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001997 if (type->tt_type == VAR_VOID)
1998 {
1999 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
2000 return NULL;
2001 }
2002 }
2003
2004 ++count;
2005 prev = p;
2006 p = skipwhite(p);
2007 }
2008
2009 if (count > 0)
2010 {
2011 long save_lnum = cctx->ctx_lnum;
2012
2013 // Use the line number where the command started.
2014 cctx->ctx_lnum = start_ctx_lnum;
2015
2016 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
2017 generate_ECHO(cctx, cmdidx == CMD_echo, count);
2018 else if (cmdidx == CMD_execute)
2019 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
2020 else if (cmdidx == CMD_echomsg)
2021 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002022#ifdef HAS_MESSAGE_WINDOW
2023 else if (cmdidx == CMD_echowindow)
2024 generate_MULT_EXPR(cctx, ISN_ECHOWINDOW, count);
2025#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002026 else if (cmdidx == CMD_echoconsole)
2027 generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
2028 else
2029 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
2030
2031 cctx->ctx_lnum = save_lnum;
2032 }
2033 return p;
2034}
2035
2036/*
2037 * If "eap" has a range that is not a constant generate an ISN_RANGE
2038 * instruction to compute it and return OK.
2039 * Otherwise return FAIL, the caller must deal with any range.
2040 */
2041 static int
2042compile_variable_range(exarg_T *eap, cctx_T *cctx)
2043{
2044 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
2045 char_u *p = skipdigits(eap->cmd);
2046
2047 if (p == range_end)
2048 return FAIL;
2049 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
2050}
2051
2052/*
2053 * :put r
2054 * :put ={expr}
2055 */
2056 char_u *
2057compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
2058{
2059 char_u *line = arg;
2060 linenr_T lnum;
2061 char *errormsg;
2062 int above = eap->forceit;
2063
2064 eap->regname = *line;
2065
2066 if (eap->regname == '=')
2067 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002068 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002069
2070 if (compile_expr0(&p, cctx) == FAIL)
2071 return NULL;
2072 line = p;
2073 }
2074 else if (eap->regname != NUL)
2075 ++line;
2076
2077 if (compile_variable_range(eap, cctx) == OK)
2078 {
2079 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2080 }
2081 else
2082 {
2083 // Either no range or a number.
2084 // "errormsg" will not be set because the range is ADDR_LINES.
2085 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2086 // cannot happen
2087 return NULL;
2088 if (eap->addr_count == 0)
2089 lnum = -1;
2090 else
2091 lnum = eap->line2;
2092 if (above)
2093 --lnum;
2094 }
2095
2096 generate_PUT(cctx, eap->regname, lnum);
2097 return line;
2098}
2099
2100/*
2101 * A command that is not compiled, execute with legacy code.
2102 */
2103 char_u *
2104compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2105{
2106 char_u *line = line_arg;
2107 char_u *p;
2108 int has_expr = FALSE;
2109 char_u *nextcmd = (char_u *)"";
2110 char_u *tofree = NULL;
2111 char_u *cmd_arg = NULL;
2112
2113 if (cctx->ctx_skip == SKIP_YES)
2114 goto theend;
2115
2116 // If there was a prececing command modifier, drop it and include it in the
2117 // EXEC command.
2118 if (cctx->ctx_has_cmdmod)
2119 {
2120 garray_T *instr = &cctx->ctx_instr;
2121 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2122
2123 if (isn->isn_type == ISN_CMDMOD)
2124 {
2125 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2126 ->cmod_filter_regmatch.regprog);
2127 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2128 --instr->ga_len;
2129 cctx->ctx_has_cmdmod = FALSE;
2130 }
2131 }
2132
2133 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2134 {
2135 long argt = eap->argt;
2136 int usefilter = FALSE;
2137
2138 has_expr = argt & (EX_XFILE | EX_EXPAND);
2139
2140 // If the command can be followed by a bar, find the bar and truncate
2141 // it, so that the following command can be compiled.
2142 // The '|' is overwritten with a NUL, it is put back below.
2143 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2144 && *eap->arg == '!')
2145 // :w !filter or :r !filter or :r! filter
2146 usefilter = TRUE;
2147 if ((argt & EX_TRLBAR) && !usefilter)
2148 {
2149 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002150 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002151 if (eap->nextcmd != NULL)
2152 nextcmd = eap->nextcmd;
2153 }
2154 else if (eap->cmdidx == CMD_wincmd)
2155 {
2156 p = eap->arg;
2157 if (*p != NUL)
2158 ++p;
2159 if (*p == 'g' || *p == Ctrl_G)
2160 ++p;
2161 p = skipwhite(p);
2162 if (*p == '|')
2163 {
2164 *p = NUL;
2165 nextcmd = p + 1;
2166 }
2167 }
2168 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2169 {
2170 // If there is a trailing '{' read lines until the '}'
2171 p = eap->arg + STRLEN(eap->arg) - 1;
2172 while (p > eap->arg && VIM_ISWHITE(*p))
2173 --p;
2174 if (*p == '{')
2175 {
2176 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002177 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002178 int start_lnum = SOURCING_LNUM;
2179
2180 CLEAR_FIELD(ea);
2181 ea.arg = eap->arg;
2182 fill_exarg_from_cctx(&ea, cctx);
2183 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2184 if (tofree != NULL)
2185 {
2186 *p = NUL;
2187 line = concat_str(line, tofree);
2188 if (line == NULL)
2189 goto theend;
2190 vim_free(tofree);
2191 tofree = line;
2192 SOURCING_LNUM = start_lnum;
2193 }
2194 }
2195 }
2196 }
2197
2198 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2199 {
2200 // expand filename in "syntax include [@group] filename"
2201 has_expr = TRUE;
2202 eap->arg = skipwhite(eap->arg + 7);
2203 if (*eap->arg == '@')
2204 eap->arg = skiptowhite(eap->arg);
2205 }
2206
2207 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2208 && STRLEN(eap->arg) > 4)
2209 {
2210 int delim = *eap->arg;
2211
2212 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2213 if (*p == delim)
2214 cmd_arg = p + 1;
2215 }
2216
2217 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2218 cmd_arg = eap->arg;
2219
2220 if (cmd_arg != NULL)
2221 {
2222 exarg_T nea;
2223
2224 CLEAR_FIELD(nea);
2225 nea.cmd = cmd_arg;
2226 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2227 if (nea.cmdidx < CMD_SIZE)
2228 {
2229 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2230 if (has_expr)
2231 eap->arg = skiptowhite(eap->arg);
2232 }
2233 }
2234
2235 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2236 {
2237 int count = 0;
2238 char_u *start = skipwhite(line);
2239
2240 // :cmd xxx`=expr1`yyy`=expr2`zzz
2241 // PUSHS ":cmd xxx"
2242 // eval expr1
2243 // PUSHS "yyy"
2244 // eval expr2
2245 // PUSHS "zzz"
2246 // EXECCONCAT 5
2247 for (;;)
2248 {
2249 if (p > start)
2250 {
2251 char_u *val = vim_strnsave(start, p - start);
2252
2253 generate_PUSHS(cctx, &val);
2254 ++count;
2255 }
2256 p += 2;
2257 if (compile_expr0(&p, cctx) == FAIL)
2258 return NULL;
2259 may_generate_2STRING(-1, TRUE, cctx);
2260 ++count;
2261 p = skipwhite(p);
2262 if (*p != '`')
2263 {
2264 emsg(_(e_missing_backtick));
2265 return NULL;
2266 }
2267 start = p + 1;
2268
2269 p = (char_u *)strstr((char *)start, "`=");
2270 if (p == NULL)
2271 {
2272 if (*skipwhite(start) != NUL)
2273 {
2274 char_u *val = vim_strsave(start);
2275
2276 generate_PUSHS(cctx, &val);
2277 ++count;
2278 }
2279 break;
2280 }
2281 }
2282 generate_EXECCONCAT(cctx, count);
2283 }
2284 else
2285 generate_EXEC_copy(cctx, ISN_EXEC, line);
2286
2287theend:
2288 if (*nextcmd != NUL)
2289 {
2290 // the parser expects a pointer to the bar, put it back
2291 --nextcmd;
2292 *nextcmd = '|';
2293 }
2294 vim_free(tofree);
2295
2296 return nextcmd;
2297}
2298
2299/*
2300 * A script command with heredoc, e.g.
2301 * ruby << EOF
2302 * command
2303 * EOF
2304 * Has been turned into one long line with NL characters by
2305 * get_function_body():
2306 * ruby << EOF<NL> command<NL>EOF
2307 */
2308 char_u *
2309compile_script(char_u *line, cctx_T *cctx)
2310{
2311 if (cctx->ctx_skip != SKIP_YES)
2312 {
2313 isn_T *isn;
2314
2315 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2316 return NULL;
2317 isn->isn_arg.string = vim_strsave(line);
2318 }
2319 return (char_u *)"";
2320}
2321
2322
2323/*
2324 * :s/pat/repl/
2325 */
2326 char_u *
2327compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2328{
2329 char_u *cmd = eap->arg;
2330 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2331
2332 if (expr != NULL)
2333 {
2334 int delimiter = *cmd++;
2335
2336 // There is a \=expr, find it in the substitute part.
2337 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2338 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2339 {
2340 garray_T save_ga = cctx->ctx_instr;
2341 char_u *end;
2342 int expr_res;
2343 int trailing_error;
2344 int instr_count;
2345 isn_T *instr;
2346 isn_T *isn;
2347
2348 cmd += 3;
2349 end = skip_substitute(cmd, delimiter);
2350
2351 // Temporarily reset the list of instructions so that the jump
2352 // labels are correct.
2353 cctx->ctx_instr.ga_len = 0;
2354 cctx->ctx_instr.ga_maxlen = 0;
2355 cctx->ctx_instr.ga_data = NULL;
2356 expr_res = compile_expr0(&cmd, cctx);
2357 if (end[-1] == NUL)
2358 end[-1] = delimiter;
2359 cmd = skipwhite(cmd);
2360 trailing_error = *cmd != delimiter && *cmd != NUL;
2361
2362 if (expr_res == FAIL || trailing_error
2363 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2364 {
2365 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002366 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002367 clear_instr_ga(&cctx->ctx_instr);
2368 cctx->ctx_instr = save_ga;
2369 return NULL;
2370 }
2371
2372 // Move the generated instructions into the ISN_SUBSTITUTE
2373 // instructions, then restore the list of instructions before
2374 // adding the ISN_SUBSTITUTE instruction.
2375 instr_count = cctx->ctx_instr.ga_len;
2376 instr = cctx->ctx_instr.ga_data;
2377 instr[instr_count].isn_type = ISN_FINISH;
2378
2379 cctx->ctx_instr = save_ga;
2380 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2381 {
2382 int idx;
2383
2384 for (idx = 0; idx < instr_count; ++idx)
2385 delete_instr(instr + idx);
2386 vim_free(instr);
2387 return NULL;
2388 }
2389 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2390 isn->isn_arg.subs.subs_instr = instr;
2391
2392 // skip over flags
2393 if (*end == '&')
2394 ++end;
2395 while (ASCII_ISALPHA(*end) || *end == '#')
2396 ++end;
2397 return end;
2398 }
2399 }
2400
2401 return compile_exec(arg, eap, cctx);
2402}
2403
2404 char_u *
2405compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2406{
2407 char_u *arg = eap->arg;
2408 lhs_T *lhs = &cctx->ctx_redir_lhs;
2409
2410 if (lhs->lhs_name != NULL)
2411 {
2412 if (STRNCMP(arg, "END", 3) == 0)
2413 {
2414 if (lhs->lhs_append)
2415 {
2416 // First load the current variable value.
2417 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
2418 cctx) == FAIL)
2419 return NULL;
2420 }
2421
2422 // Gets the redirected text and put it on the stack, then store it
2423 // in the variable.
2424 generate_instr_type(cctx, ISN_REDIREND, &t_string);
2425
2426 if (lhs->lhs_append)
LemonBoy372bcce2022-04-25 12:43:20 +01002427 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002428
2429 if (lhs->lhs_has_index)
2430 {
2431 // Use the info in "lhs" to store the value at the index in the
2432 // list or dict.
2433 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
2434 &t_string, cctx) == FAIL)
2435 return NULL;
2436 }
Bram Moolenaar5cd64792021-12-25 18:23:24 +00002437 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002438 return NULL;
2439
2440 VIM_CLEAR(lhs->lhs_name);
2441 VIM_CLEAR(lhs->lhs_whole);
2442 return arg + 3;
2443 }
2444 emsg(_(e_cannot_nest_redir));
2445 return NULL;
2446 }
2447
2448 if (arg[0] == '=' && arg[1] == '>')
2449 {
2450 int append = FALSE;
2451
2452 // redirect to a variable is compiled
2453 arg += 2;
2454 if (*arg == '>')
2455 {
2456 ++arg;
2457 append = TRUE;
2458 }
2459 arg = skipwhite(arg);
2460
2461 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002462 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002463 return NULL;
2464 if (need_type(&t_string, lhs->lhs_member_type,
2465 -1, 0, cctx, FALSE, FALSE) == FAIL)
2466 return NULL;
2467 generate_instr(cctx, ISN_REDIRSTART);
2468 lhs->lhs_append = append;
2469 if (lhs->lhs_has_index)
2470 {
2471 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2472 if (lhs->lhs_whole == NULL)
2473 return NULL;
2474 }
2475
2476 return arg + lhs->lhs_varlen_total;
2477 }
2478
2479 // other redirects are handled like at script level
2480 return compile_exec(line, eap, cctx);
2481}
2482
2483#if defined(FEAT_QUICKFIX) || defined(PROTO)
2484 char_u *
2485compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2486{
2487 isn_T *isn;
2488 char_u *p;
2489
2490 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2491 if (isn == NULL)
2492 return NULL;
2493 isn->isn_arg.number = eap->cmdidx;
2494
2495 p = eap->arg;
2496 if (compile_expr0(&p, cctx) == FAIL)
2497 return NULL;
2498
2499 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2500 if (isn == NULL)
2501 return NULL;
2502 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2503 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2504 return NULL;
2505 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2506 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2507 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2508
2509 return p;
2510}
2511#endif
2512
2513/*
2514 * Compile "return [expr]".
2515 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2516 */
2517 char_u *
2518compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2519{
2520 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002521 type_T *stack_type;
2522
2523 if (*p != NUL && *p != '|' && *p != '\n')
2524 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002525 // For a lambda, "return expr" is always used, also when "expr" results
2526 // in a void.
2527 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2528 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002529 {
2530 emsg(_(e_returning_value_in_function_without_return_type));
2531 return NULL;
2532 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002533 if (legacy)
2534 {
2535 int save_flags = cmdmod.cmod_flags;
2536
2537 generate_LEGACY_EVAL(cctx, p);
2538 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
2539 0, cctx, FALSE, FALSE) == FAIL)
2540 return NULL;
2541 cmdmod.cmod_flags |= CMOD_LEGACY;
2542 (void)skip_expr(&p, NULL);
2543 cmdmod.cmod_flags = save_flags;
2544 }
2545 else
2546 {
2547 // compile return argument into instructions
2548 if (compile_expr0(&p, cctx) == FAIL)
2549 return NULL;
2550 }
2551
2552 if (cctx->ctx_skip != SKIP_YES)
2553 {
2554 // "check_return_type" with uf_ret_type set to &t_unknown is used
2555 // for an inline function without a specified return type. Set the
2556 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002557 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002558 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002559 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002560 || (!check_return_type
2561 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2562 {
2563 cctx->ctx_ufunc->uf_ret_type = stack_type;
2564 }
2565 else
2566 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002567 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
2568 0, cctx, FALSE, FALSE) == FAIL)
2569 return NULL;
2570 }
2571 }
2572 }
2573 else
2574 {
2575 // "check_return_type" cannot be TRUE, only used for a lambda which
2576 // always has an argument.
2577 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2578 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2579 {
2580 emsg(_(e_missing_return_value));
2581 return NULL;
2582 }
2583
2584 // No argument, return zero.
2585 generate_PUSHNR(cctx, 0);
2586 }
2587
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002588 // may need ENDLOOP when inside a :for or :while loop
2589 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2590
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002591 // Undo any command modifiers.
2592 generate_undo_cmdmods(cctx);
2593
2594 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2595 return NULL;
2596
2597 // "return val | endif" is possible
2598 return skipwhite(p);
2599}
2600
2601/*
2602 * Check if the separator for a :global or :substitute command is OK.
2603 */
2604 int
2605check_global_and_subst(char_u *cmd, char_u *arg)
2606{
2607 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2608 {
2609 semsg(_(e_separator_not_supported_str), arg);
2610 return FAIL;
2611 }
2612 if (VIM_ISWHITE(cmd[1]))
2613 {
2614 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2615 return FAIL;
2616 }
2617 return OK;
2618}
2619
2620
2621#endif // defined(FEAT_EVAL)