blob: 35a382138bf3be8fc9e4a86fc36c6598e1d845ae [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{
95 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
96 {
97 // "unlet s:var" is allowed in legacy script.
98 if (*name == 's' && !script_is_vim9())
99 return OK;
100 semsg(_(e_cannot_unlet_str), name);
101 return FAIL;
102 }
103 return OK;
104}
105
106/*
107 * Callback passed to ex_unletlock().
108 */
109 static int
110compile_unlet(
111 lval_T *lvp,
112 char_u *name_end,
113 exarg_T *eap,
114 int deep UNUSED,
115 void *coookie)
116{
117 cctx_T *cctx = coookie;
118 char_u *p = lvp->ll_name;
119 int cc = *name_end;
120 int ret = OK;
121
122 if (cctx->ctx_skip == SKIP_YES)
123 return OK;
124
125 *name_end = NUL;
126 if (*p == '$')
127 {
128 // :unlet $ENV_VAR
129 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
130 }
131 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
132 {
133 lhs_T lhs;
134
135 // This is similar to assigning: lookup the list/dict, compile the
136 // idx/key. Then instead of storing the value unlet the item.
137 // unlet {list}[idx]
138 // unlet {dict}[key] dict.key
139 //
140 // Figure out the LHS type and other properties.
141 //
Bram Moolenaar97f8c102022-04-02 19:43:57 +0100142 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, FALSE, 0, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000143
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000144 // Use the info in "lhs" to unlet the item at the index in the
145 // list or dict.
146 if (ret == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000147 {
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000148 if (!lhs.lhs_has_index)
149 {
150 semsg(_(e_cannot_unlet_imported_item_str), p);
151 ret = FAIL;
152 }
153 else
154 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000155 }
156
157 vim_free(lhs.lhs_name);
158 }
159 else if (check_vim9_unlet(p) == FAIL)
160 {
161 ret = FAIL;
162 }
163 else
164 {
165 // Normal name. Only supports g:, w:, t: and b: namespaces.
166 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
167 }
168
169 *name_end = cc;
170 return ret;
171}
172
173/*
174 * Callback passed to ex_unletlock().
175 */
176 static int
177compile_lock_unlock(
178 lval_T *lvp,
179 char_u *name_end,
180 exarg_T *eap,
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000181 int deep,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000182 void *coookie)
183{
184 cctx_T *cctx = coookie;
185 int cc = *name_end;
186 char_u *p = lvp->ll_name;
187 int ret = OK;
188 size_t len;
189 char_u *buf;
190 isntype_T isn = ISN_EXEC;
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100191 char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000192
193 if (cctx->ctx_skip == SKIP_YES)
194 return OK;
195
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100196 if (*p == NUL)
197 {
198 semsg(_(e_argument_required_for_str), cmd);
199 return FAIL;
200 }
201
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000202 // Cannot use :lockvar and :unlockvar on local variables.
203 if (p[1] != ':')
204 {
205 char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
206
207 if (lookup_local(p, end - p, NULL, cctx) == OK)
208 {
209 char_u *s = p;
210
211 if (*end != '.' && *end != '[')
212 {
213 emsg(_(e_cannot_lock_unlock_local_variable));
214 return FAIL;
215 }
216
217 // For "d.member" put the local variable on the stack, it will be
218 // passed to ex_lockvar() indirectly.
219 if (compile_load(&s, end, cctx, FALSE, FALSE) == FAIL)
220 return FAIL;
221 isn = ISN_LOCKUNLOCK;
222 }
223 }
224
225 // Checking is done at runtime.
226 *name_end = NUL;
227 len = name_end - p + 20;
228 buf = alloc(len);
229 if (buf == NULL)
230 ret = FAIL;
231 else
232 {
Bram Moolenaare939f5e2022-01-26 21:32:59 +0000233 if (deep < 0)
234 vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
235 else
236 vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000237 ret = generate_EXEC_copy(cctx, isn, buf);
238
239 vim_free(buf);
240 *name_end = cc;
241 }
242 return ret;
243}
244
245/*
246 * compile "unlet var", "lock var" and "unlock var"
247 * "arg" points to "var".
248 */
249 char_u *
250compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
251{
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000252 int deep = 0;
253 char_u *p = arg;
254
255 if (eap->cmdidx != CMD_unlet)
256 {
257 if (eap->forceit)
258 deep = -1;
259 else if (vim_isdigit(*p))
260 {
261 deep = getdigits(&p);
262 p = skipwhite(p);
263 }
264 else
265 deep = 2;
266 }
267
268 ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000269 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
270 cctx);
271 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
272}
273
274/*
275 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
276 */
277 static int
278compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
279{
280 garray_T *instr = &cctx->ctx_instr;
281 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
282
283 if (endlabel == NULL)
284 return FAIL;
285 endlabel->el_next = *el;
286 *el = endlabel;
287 endlabel->el_end_label = instr->ga_len;
288
289 generate_JUMP(cctx, when, 0);
290 return OK;
291}
292
293 static void
294compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
295{
296 garray_T *instr = &cctx->ctx_instr;
297
298 while (*el != NULL)
299 {
300 endlabel_T *cur = (*el);
301 isn_T *isn;
302
303 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
304 isn->isn_arg.jump.jump_where = jump_where;
305 *el = cur->el_next;
306 vim_free(cur);
307 }
308}
309
310 static void
311compile_free_jump_to_end(endlabel_T **el)
312{
313 while (*el != NULL)
314 {
315 endlabel_T *cur = (*el);
316
317 *el = cur->el_next;
318 vim_free(cur);
319 }
320}
321
322/*
323 * Create a new scope and set up the generic items.
324 */
325 static scope_T *
326new_scope(cctx_T *cctx, scopetype_T type)
327{
328 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
329
330 if (scope == NULL)
331 return NULL;
332 scope->se_outer = cctx->ctx_scope;
333 cctx->ctx_scope = scope;
334 scope->se_type = type;
335 scope->se_local_count = cctx->ctx_locals.ga_len;
336 return scope;
337}
338
339/*
340 * Free the current scope and go back to the outer scope.
341 */
342 void
343drop_scope(cctx_T *cctx)
344{
345 scope_T *scope = cctx->ctx_scope;
346
347 if (scope == NULL)
348 {
349 iemsg("calling drop_scope() without a scope");
350 return;
351 }
352 cctx->ctx_scope = scope->se_outer;
353 switch (scope->se_type)
354 {
355 case IF_SCOPE:
356 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
357 case FOR_SCOPE:
358 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
359 case WHILE_SCOPE:
360 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
361 case TRY_SCOPE:
362 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
363 case NO_SCOPE:
364 case BLOCK_SCOPE:
365 break;
366 }
367 vim_free(scope);
368}
369
370 static int
371misplaced_cmdmod(cctx_T *cctx)
372{
373 garray_T *instr = &cctx->ctx_instr;
374
375 if (cctx->ctx_has_cmdmod
376 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
377 == ISN_CMDMOD)
378 {
379 emsg(_(e_misplaced_command_modifier));
380 return TRUE;
381 }
382 return FALSE;
383}
384
385/*
386 * compile "if expr"
387 *
388 * "if expr" Produces instructions:
389 * EVAL expr Push result of "expr"
390 * JUMP_IF_FALSE end
391 * ... body ...
392 * end:
393 *
394 * "if expr | else" Produces instructions:
395 * EVAL expr Push result of "expr"
396 * JUMP_IF_FALSE else
397 * ... body ...
398 * JUMP_ALWAYS end
399 * else:
400 * ... body ...
401 * end:
402 *
403 * "if expr1 | elseif expr2 | else" Produces instructions:
404 * EVAL expr Push result of "expr"
405 * JUMP_IF_FALSE elseif
406 * ... body ...
407 * JUMP_ALWAYS end
408 * elseif:
409 * EVAL expr Push result of "expr"
410 * JUMP_IF_FALSE else
411 * ... body ...
412 * JUMP_ALWAYS end
413 * else:
414 * ... body ...
415 * end:
416 */
417 char_u *
418compile_if(char_u *arg, cctx_T *cctx)
419{
420 char_u *p = arg;
421 garray_T *instr = &cctx->ctx_instr;
422 int instr_count = instr->ga_len;
423 scope_T *scope;
424 skip_T skip_save = cctx->ctx_skip;
425 ppconst_T ppconst;
426
427 CLEAR_FIELD(ppconst);
428 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
429 {
430 clear_ppconst(&ppconst);
431 return NULL;
432 }
433 if (!ends_excmd2(arg, skipwhite(p)))
434 {
Bram Moolenaar74409f62022-01-01 15:58:22 +0000435 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000436 return NULL;
437 }
438 if (cctx->ctx_skip == SKIP_YES)
439 clear_ppconst(&ppconst);
440 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
441 {
442 int error = FALSE;
443 int v;
444
445 // The expression results in a constant.
446 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
447 clear_ppconst(&ppconst);
448 if (error)
449 return NULL;
450 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
451 }
452 else
453 {
454 // Not a constant, generate instructions for the expression.
455 cctx->ctx_skip = SKIP_UNKNOWN;
456 if (generate_ppconst(cctx, &ppconst) == FAIL)
457 return NULL;
458 if (bool_on_stack(cctx) == FAIL)
459 return NULL;
460 }
461
462 // CMDMOD_REV must come before the jump
463 generate_undo_cmdmods(cctx);
464
465 scope = new_scope(cctx, IF_SCOPE);
466 if (scope == NULL)
467 return NULL;
468 scope->se_skip_save = skip_save;
469 // "is_had_return" will be reset if any block does not end in :return
470 scope->se_u.se_if.is_had_return = TRUE;
471
472 if (cctx->ctx_skip == SKIP_UNKNOWN)
473 {
474 // "where" is set when ":elseif", "else" or ":endif" is found
475 scope->se_u.se_if.is_if_label = instr->ga_len;
476 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
477 }
478 else
479 scope->se_u.se_if.is_if_label = -1;
480
481#ifdef FEAT_PROFILE
482 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
483 && skip_save != SKIP_YES)
484 {
485 // generated a profile start, need to generate a profile end, since it
486 // won't be done after returning
487 cctx->ctx_skip = SKIP_NOT;
488 generate_instr(cctx, ISN_PROF_END);
489 cctx->ctx_skip = SKIP_YES;
490 }
491#endif
492
493 return p;
494}
495
496 char_u *
497compile_elseif(char_u *arg, cctx_T *cctx)
498{
499 char_u *p = arg;
500 garray_T *instr = &cctx->ctx_instr;
501 int instr_count;
502 isn_T *isn;
503 scope_T *scope = cctx->ctx_scope;
504 ppconst_T ppconst;
505 skip_T save_skip = cctx->ctx_skip;
506
507 if (scope == NULL || scope->se_type != IF_SCOPE)
508 {
509 emsg(_(e_elseif_without_if));
510 return NULL;
511 }
512 unwind_locals(cctx, scope->se_local_count);
513 if (!cctx->ctx_had_return)
514 scope->se_u.se_if.is_had_return = FALSE;
515
516 if (cctx->ctx_skip == SKIP_NOT)
517 {
518 // previous block was executed, this one and following will not
519 cctx->ctx_skip = SKIP_YES;
520 scope->se_u.se_if.is_seen_skip_not = TRUE;
521 }
522 if (scope->se_u.se_if.is_seen_skip_not)
523 {
524 // A previous block was executed, skip over expression and bail out.
525 // Do not count the "elseif" for profiling and cmdmod
526 instr->ga_len = current_instr_idx(cctx);
527
528 skip_expr_cctx(&p, cctx);
529 return p;
530 }
531
532 if (cctx->ctx_skip == SKIP_UNKNOWN)
533 {
534 int moved_cmdmod = FALSE;
535 int saved_debug = FALSE;
536 isn_T debug_isn;
537
538 // Move any CMDMOD instruction to after the jump
539 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
540 {
541 if (GA_GROW_FAILS(instr, 1))
542 return NULL;
543 ((isn_T *)instr->ga_data)[instr->ga_len] =
544 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
545 --instr->ga_len;
546 moved_cmdmod = TRUE;
547 }
548
549 // Remove the already generated ISN_DEBUG, it is written below the
550 // ISN_FOR instruction.
551 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
552 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
553 .isn_type == ISN_DEBUG)
554 {
555 --instr->ga_len;
556 debug_isn = ((isn_T *)instr->ga_data)[instr->ga_len];
557 saved_debug = TRUE;
558 }
559
560 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
561 JUMP_ALWAYS, cctx) == FAIL)
562 return NULL;
563 // previous "if" or "elseif" jumps here
564 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
565 isn->isn_arg.jump.jump_where = instr->ga_len;
566
567 if (moved_cmdmod)
568 ++instr->ga_len;
569
570 if (saved_debug)
571 {
572 // move the debug instruction here
573 if (GA_GROW_FAILS(instr, 1))
574 return NULL;
575 ((isn_T *)instr->ga_data)[instr->ga_len] = debug_isn;
576 ++instr->ga_len;
577 }
578 }
579
580 // compile "expr"; if we know it evaluates to FALSE skip the block
581 CLEAR_FIELD(ppconst);
582 if (cctx->ctx_skip == SKIP_YES)
583 {
584 cctx->ctx_skip = SKIP_UNKNOWN;
585#ifdef FEAT_PROFILE
586 if (cctx->ctx_compile_type == CT_PROFILE)
587 // the previous block was skipped, need to profile this line
588 generate_instr(cctx, ISN_PROF_START);
589#endif
590 if (cctx->ctx_compile_type == CT_DEBUG)
591 // the previous block was skipped, may want to debug this line
592 generate_instr_debug(cctx);
593 }
594
595 instr_count = instr->ga_len;
596 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
597 {
598 clear_ppconst(&ppconst);
599 return NULL;
600 }
601 cctx->ctx_skip = save_skip;
602 if (!ends_excmd2(arg, skipwhite(p)))
603 {
604 clear_ppconst(&ppconst);
Bram Moolenaar74409f62022-01-01 15:58:22 +0000605 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000606 return NULL;
607 }
608 if (scope->se_skip_save == SKIP_YES)
609 clear_ppconst(&ppconst);
610 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
611 {
612 int error = FALSE;
613 int v;
614
615 // The expression result is a constant.
616 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
617 if (error)
618 {
619 clear_ppconst(&ppconst);
620 return NULL;
621 }
622 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
623 clear_ppconst(&ppconst);
624 scope->se_u.se_if.is_if_label = -1;
625 }
626 else
627 {
628 // Not a constant, generate instructions for the expression.
629 cctx->ctx_skip = SKIP_UNKNOWN;
630 if (generate_ppconst(cctx, &ppconst) == FAIL)
631 return NULL;
632 if (bool_on_stack(cctx) == FAIL)
633 return NULL;
634
635 // CMDMOD_REV must come before the jump
636 generate_undo_cmdmods(cctx);
637
638 // "where" is set when ":elseif", "else" or ":endif" is found
639 scope->se_u.se_if.is_if_label = instr->ga_len;
640 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
641 }
642
643 return p;
644}
645
646 char_u *
647compile_else(char_u *arg, cctx_T *cctx)
648{
649 char_u *p = arg;
650 garray_T *instr = &cctx->ctx_instr;
651 isn_T *isn;
652 scope_T *scope = cctx->ctx_scope;
653
654 if (scope == NULL || scope->se_type != IF_SCOPE)
655 {
656 emsg(_(e_else_without_if));
657 return NULL;
658 }
659 unwind_locals(cctx, scope->se_local_count);
660 if (!cctx->ctx_had_return)
661 scope->se_u.se_if.is_had_return = FALSE;
662 scope->se_u.se_if.is_seen_else = TRUE;
663
664#ifdef FEAT_PROFILE
665 if (cctx->ctx_compile_type == CT_PROFILE)
666 {
667 if (cctx->ctx_skip == SKIP_NOT
668 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
669 .isn_type == ISN_PROF_START)
670 // the previous block was executed, do not count "else" for
671 // profiling
672 --instr->ga_len;
673 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
674 {
675 // the previous block was not executed, this one will, do count the
676 // "else" for profiling
677 cctx->ctx_skip = SKIP_NOT;
678 generate_instr(cctx, ISN_PROF_END);
679 generate_instr(cctx, ISN_PROF_START);
680 cctx->ctx_skip = SKIP_YES;
681 }
682 }
683#endif
684
685 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
686 {
687 // jump from previous block to the end, unless the else block is empty
688 if (cctx->ctx_skip == SKIP_UNKNOWN)
689 {
690 if (!cctx->ctx_had_return
691 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
692 JUMP_ALWAYS, cctx) == FAIL)
693 return NULL;
694 }
695
696 if (cctx->ctx_skip == SKIP_UNKNOWN)
697 {
698 if (scope->se_u.se_if.is_if_label >= 0)
699 {
700 // previous "if" or "elseif" jumps here
701 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
702 isn->isn_arg.jump.jump_where = instr->ga_len;
703 scope->se_u.se_if.is_if_label = -1;
704 }
705 }
706
707 if (cctx->ctx_skip != SKIP_UNKNOWN)
708 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
709 }
710
711 return p;
712}
713
714 char_u *
715compile_endif(char_u *arg, cctx_T *cctx)
716{
717 scope_T *scope = cctx->ctx_scope;
718 ifscope_T *ifscope;
719 garray_T *instr = &cctx->ctx_instr;
720 isn_T *isn;
721
722 if (misplaced_cmdmod(cctx))
723 return NULL;
724
725 if (scope == NULL || scope->se_type != IF_SCOPE)
726 {
727 emsg(_(e_endif_without_if));
728 return NULL;
729 }
730 ifscope = &scope->se_u.se_if;
731 unwind_locals(cctx, scope->se_local_count);
732 if (!cctx->ctx_had_return)
733 ifscope->is_had_return = FALSE;
734
735 if (scope->se_u.se_if.is_if_label >= 0)
736 {
737 // previous "if" or "elseif" jumps here
738 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
739 isn->isn_arg.jump.jump_where = instr->ga_len;
740 }
741 // Fill in the "end" label in jumps at the end of the blocks.
742 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
743
744#ifdef FEAT_PROFILE
745 // even when skipping we count the endif as executed, unless the block it's
746 // in is skipped
747 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
748 && scope->se_skip_save != SKIP_YES)
749 {
750 cctx->ctx_skip = SKIP_NOT;
751 generate_instr(cctx, ISN_PROF_START);
752 }
753#endif
754 cctx->ctx_skip = scope->se_skip_save;
755
756 // If all the blocks end in :return and there is an :else then the
757 // had_return flag is set.
758 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
759
760 drop_scope(cctx);
761 return arg;
762}
763
764/*
765 * Compile "for var in expr":
766 *
767 * Produces instructions:
768 * PUSHNR -1
769 * STORE loop-idx Set index to -1
770 * EVAL expr result of "expr" on top of stack
771 * top: FOR loop-idx, end Increment index, use list on bottom of stack
772 * - if beyond end, jump to "end"
773 * - otherwise get item from list and push it
774 * STORE var Store item in "var"
775 * ... body ...
776 * JUMP top Jump back to repeat
777 * end: DROP Drop the result of "expr"
778 *
779 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
780 * UNPACK 2 Split item in 2
781 * STORE var1 Store item in "var1"
782 * STORE var2 Store item in "var2"
783 */
784 char_u *
785compile_for(char_u *arg_start, cctx_T *cctx)
786{
787 char_u *arg;
788 char_u *arg_end;
789 char_u *name = NULL;
790 char_u *p;
791 char_u *wp;
792 int var_count = 0;
793 int var_list = FALSE;
794 int semicolon = FALSE;
795 size_t varlen;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000796 garray_T *instr = &cctx->ctx_instr;
797 scope_T *scope;
798 lvar_T *loop_lvar; // loop iteration variable
799 lvar_T *var_lvar; // variable for "var"
800 type_T *vartype;
801 type_T *item_type = &t_any;
802 int idx;
803 int prev_lnum = cctx->ctx_prev_lnum;
804
805 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
806 if (p == NULL)
807 return NULL;
808 if (var_count == 0)
809 var_count = 1;
810 else
811 var_list = TRUE; // can also be a list of one variable
812
813 // consume "in"
814 wp = p;
815 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
816 return NULL;
817 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
818 {
819 if (*p == ':' && wp != p)
820 semsg(_(e_no_white_space_allowed_before_colon_str), p);
821 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000822 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000823 return NULL;
824 }
825 wp = p + 2;
826 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
827 return NULL;
828
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000829 // Find the already generated ISN_DEBUG to get the line number for the
830 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000831 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
832 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
833 .isn_type == ISN_DEBUG)
834 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000835 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000836 .isn_arg.debug.dbg_break_lnum;
837 }
838
839 scope = new_scope(cctx, FOR_SCOPE);
840 if (scope == NULL)
841 return NULL;
842
843 // Reserve a variable to store the loop iteration counter and initialize it
844 // to -1.
845 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
846 if (loop_lvar == NULL)
847 {
848 // out of memory
849 drop_scope(cctx);
850 return NULL;
851 }
852 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
853
854 // compile "expr", it remains on the stack until "endfor"
855 arg = p;
856 if (compile_expr0(&arg, cctx) == FAIL)
857 {
858 drop_scope(cctx);
859 return NULL;
860 }
861 arg_end = arg;
862
863 if (cctx->ctx_skip != SKIP_YES)
864 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000865 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000866 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000867 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000868 if (vartype->tt_type != VAR_LIST
869 && vartype->tt_type != VAR_STRING
870 && vartype->tt_type != VAR_BLOB
871 && vartype->tt_type != VAR_ANY
872 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000873 {
874 semsg(_(e_for_loop_on_str_not_supported),
875 vartype_name(vartype->tt_type));
876 drop_scope(cctx);
877 return NULL;
878 }
879
880 if (vartype->tt_type == VAR_STRING)
881 item_type = &t_string;
882 else if (vartype->tt_type == VAR_BLOB)
883 item_type = &t_number;
884 else if (vartype->tt_type == VAR_LIST
885 && vartype->tt_member->tt_type != VAR_ANY)
886 {
887 if (!var_list)
888 item_type = vartype->tt_member;
889 else if (vartype->tt_member->tt_type == VAR_LIST
890 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
891 item_type = vartype->tt_member->tt_member;
892 }
893
894 // CMDMOD_REV must come before the FOR instruction.
895 generate_undo_cmdmods(cctx);
896
897 // "for_end" is set when ":endfor" is found
898 scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
899
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000900 if (cctx->ctx_compile_type == CT_DEBUG)
901 {
902 int save_prev_lnum = cctx->ctx_prev_lnum;
903 isn_T *isn;
904
905 // Add ISN_DEBUG here, before deciding to end the loop. There will
906 // be another ISN_DEBUG before the next instruction.
907 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
908 // Increment the variable count so that the loop variable can be
909 // inspected.
910 cctx->ctx_prev_lnum = prev_lnum;
911 isn = generate_instr_debug(cctx);
912 ++isn->isn_arg.debug.dbg_var_names_len;
913 cctx->ctx_prev_lnum = save_prev_lnum;
914 }
915
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000916 generate_FOR(cctx, loop_lvar->lv_idx);
917
918 arg = arg_start;
919 if (var_list)
920 {
921 generate_UNPACK(cctx, var_count, semicolon);
922 arg = skipwhite(arg + 1); // skip white after '['
923
Bram Moolenaar078a4612022-01-04 15:17:03 +0000924 // drop the list item
925 --cctx->ctx_type_stack.ga_len;
926
927 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000928 for (idx = 0; idx < var_count; ++idx)
929 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000930 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
931
932 if (push_type_stack(cctx, type) == FAIL)
933 {
934 drop_scope(cctx);
935 return NULL;
936 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000937 }
938 }
939
940 for (idx = 0; idx < var_count; ++idx)
941 {
942 assign_dest_T dest = dest_local;
943 int opt_flags = 0;
944 int vimvaridx = -1;
945 type_T *type = &t_any;
946 type_T *lhs_type = &t_any;
947 where_T where = WHERE_INIT;
948
949 p = skip_var_one(arg, FALSE);
950 varlen = p - arg;
951 name = vim_strnsave(arg, varlen);
952 if (name == NULL)
953 goto failed;
954 if (*p == ':')
955 {
956 p = skipwhite(p + 1);
957 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
958 }
959
960 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
961 &vimvaridx, &type, cctx) == FAIL)
962 goto failed;
963 if (dest != dest_local)
964 {
965 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
966 0, 0, type, name) == FAIL)
967 goto failed;
968 }
969 else if (varlen == 1 && *arg == '_')
970 {
971 // Assigning to "_": drop the value.
972 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
973 goto failed;
974 }
975 else
976 {
977 // Script var is not supported.
978 if (STRNCMP(name, "s:", 2) == 0)
979 {
980 emsg(_(e_cannot_use_script_variable_in_for_loop));
981 goto failed;
982 }
983
984 if (!valid_varname(arg, (int)varlen, FALSE))
985 goto failed;
986 if (lookup_local(arg, varlen, NULL, cctx) == OK)
987 {
988 semsg(_(e_variable_already_declared), arg);
989 goto failed;
990 }
991
992 // Reserve a variable to store "var".
993 where.wt_index = var_list ? idx + 1 : 0;
994 where.wt_variable = TRUE;
995 if (lhs_type == &t_any)
996 lhs_type = item_type;
997 else if (item_type != &t_unknown
Bram Moolenaara1c51952022-02-02 16:20:26 +0000998 && need_type_where(item_type, lhs_type, -1,
999 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001000 goto failed;
1001 var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
1002 if (var_lvar == NULL)
1003 // out of memory or used as an argument
1004 goto failed;
1005
1006 if (semicolon && idx == var_count - 1)
1007 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001008 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1009 }
1010
1011 if (*p == ',' || *p == ';')
1012 ++p;
1013 arg = skipwhite(p);
1014 vim_free(name);
1015 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001016 }
1017
1018 return arg_end;
1019
1020failed:
1021 vim_free(name);
1022 drop_scope(cctx);
1023 return NULL;
1024}
1025
1026/*
1027 * compile "endfor"
1028 */
1029 char_u *
1030compile_endfor(char_u *arg, cctx_T *cctx)
1031{
1032 garray_T *instr = &cctx->ctx_instr;
1033 scope_T *scope = cctx->ctx_scope;
1034 forscope_T *forscope;
1035 isn_T *isn;
1036
1037 if (misplaced_cmdmod(cctx))
1038 return NULL;
1039
1040 if (scope == NULL || scope->se_type != FOR_SCOPE)
1041 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001042 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001043 return NULL;
1044 }
1045 forscope = &scope->se_u.se_for;
1046 cctx->ctx_scope = scope->se_outer;
1047 if (cctx->ctx_skip != SKIP_YES)
1048 {
1049 unwind_locals(cctx, scope->se_local_count);
1050
1051 // At end of ":for" scope jump back to the FOR instruction.
1052 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1053
1054 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001055 // In debug mode an ISN_DEBUG was inserted.
1056 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1057 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001058 isn->isn_arg.forloop.for_end = instr->ga_len;
1059
1060 // Fill in the "end" label any BREAK statements
1061 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1062
1063 // Below the ":for" scope drop the "expr" list from the stack.
1064 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1065 return NULL;
1066 }
1067
1068 vim_free(scope);
1069
1070 return arg;
1071}
1072
1073/*
1074 * compile "while expr"
1075 *
1076 * Produces instructions:
1077 * top: EVAL expr Push result of "expr"
1078 * JUMP_IF_FALSE end jump if false
1079 * ... body ...
1080 * JUMP top Jump back to repeat
1081 * end:
1082 *
1083 */
1084 char_u *
1085compile_while(char_u *arg, cctx_T *cctx)
1086{
1087 char_u *p = arg;
1088 scope_T *scope;
1089
1090 scope = new_scope(cctx, WHILE_SCOPE);
1091 if (scope == NULL)
1092 return NULL;
1093
1094 // "endwhile" jumps back here, one before when profiling or using cmdmods
1095 scope->se_u.se_while.ws_top_label = current_instr_idx(cctx);
1096
1097 // compile "expr"
1098 if (compile_expr0(&p, cctx) == FAIL)
1099 return NULL;
1100
1101 if (!ends_excmd2(arg, skipwhite(p)))
1102 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001103 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001104 return NULL;
1105 }
1106
1107 if (cctx->ctx_skip != SKIP_YES)
1108 {
1109 if (bool_on_stack(cctx) == FAIL)
1110 return FAIL;
1111
1112 // CMDMOD_REV must come before the jump
1113 generate_undo_cmdmods(cctx);
1114
1115 // "while_end" is set when ":endwhile" is found
1116 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
1117 JUMP_IF_FALSE, cctx) == FAIL)
1118 return FAIL;
1119 }
1120
1121 return p;
1122}
1123
1124/*
1125 * compile "endwhile"
1126 */
1127 char_u *
1128compile_endwhile(char_u *arg, cctx_T *cctx)
1129{
1130 scope_T *scope = cctx->ctx_scope;
1131 garray_T *instr = &cctx->ctx_instr;
1132
1133 if (misplaced_cmdmod(cctx))
1134 return NULL;
1135 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1136 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001137 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001138 return NULL;
1139 }
1140 cctx->ctx_scope = scope->se_outer;
1141 if (cctx->ctx_skip != SKIP_YES)
1142 {
1143 unwind_locals(cctx, scope->se_local_count);
1144
1145#ifdef FEAT_PROFILE
1146 // count the endwhile before jumping
1147 may_generate_prof_end(cctx, cctx->ctx_lnum);
1148#endif
1149
1150 // At end of ":for" scope jump back to the FOR instruction.
1151 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1152
1153 // Fill in the "end" label in the WHILE statement so it can jump here.
1154 // And in any jumps for ":break"
1155 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1156 instr->ga_len, cctx);
1157 }
1158
1159 vim_free(scope);
1160
1161 return arg;
1162}
1163
1164/*
1165 * compile "continue"
1166 */
1167 char_u *
1168compile_continue(char_u *arg, cctx_T *cctx)
1169{
1170 scope_T *scope = cctx->ctx_scope;
1171 int try_scopes = 0;
1172 int loop_label;
1173
1174 for (;;)
1175 {
1176 if (scope == NULL)
1177 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +00001178 emsg(_(e_continue_without_while_or_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001179 return NULL;
1180 }
1181 if (scope->se_type == FOR_SCOPE)
1182 {
1183 loop_label = scope->se_u.se_for.fs_top_label;
1184 break;
1185 }
1186 if (scope->se_type == WHILE_SCOPE)
1187 {
1188 loop_label = scope->se_u.se_while.ws_top_label;
1189 break;
1190 }
1191 if (scope->se_type == TRY_SCOPE)
1192 ++try_scopes;
1193 scope = scope->se_outer;
1194 }
1195
1196 if (try_scopes > 0)
1197 // Inside one or more try/catch blocks we first need to jump to the
1198 // "finally" or "endtry" to cleanup.
1199 generate_TRYCONT(cctx, try_scopes, loop_label);
1200 else
1201 // Jump back to the FOR or WHILE instruction.
1202 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1203
1204 return arg;
1205}
1206
1207/*
1208 * compile "break"
1209 */
1210 char_u *
1211compile_break(char_u *arg, cctx_T *cctx)
1212{
1213 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar873f8242022-03-10 21:53:44 +00001214 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001215 endlabel_T **el;
1216
1217 for (;;)
1218 {
1219 if (scope == NULL)
1220 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +00001221 emsg(_(e_break_without_while_or_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001222 return NULL;
1223 }
Bram Moolenaar873f8242022-03-10 21:53:44 +00001224 if (scope->se_type == FOR_SCOPE)
1225 {
1226 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001227 break;
Bram Moolenaar873f8242022-03-10 21:53:44 +00001228 }
1229 if (scope->se_type == WHILE_SCOPE)
1230 {
1231 el = &scope->se_u.se_while.ws_end_label;
1232 break;
1233 }
1234 if (scope->se_type == TRY_SCOPE)
1235 ++try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001236 scope = scope->se_outer;
1237 }
1238
Bram Moolenaar873f8242022-03-10 21:53:44 +00001239 if (try_scopes > 0)
1240 // Inside one or more try/catch blocks we first need to jump to the
1241 // "finally" or "endtry" to cleanup. Then come to the next JUMP
1242 // intruction, which we don't know the index of yet.
1243 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1244
1245 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1246 // filled in later.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001247 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
1248 return FAIL;
1249
1250 return arg;
1251}
1252
1253/*
1254 * compile "{" start of block
1255 */
1256 char_u *
1257compile_block(char_u *arg, cctx_T *cctx)
1258{
1259 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1260 return NULL;
1261 return skipwhite(arg + 1);
1262}
1263
1264/*
1265 * compile end of block: drop one scope
1266 */
1267 void
1268compile_endblock(cctx_T *cctx)
1269{
1270 scope_T *scope = cctx->ctx_scope;
1271
1272 cctx->ctx_scope = scope->se_outer;
1273 unwind_locals(cctx, scope->se_local_count);
1274 vim_free(scope);
1275}
1276
1277/*
1278 * Compile "try".
1279 * Creates a new scope for the try-endtry, pointing to the first catch and
1280 * finally.
1281 * Creates another scope for the "try" block itself.
1282 * TRY instruction sets up exception handling at runtime.
1283 *
1284 * "try"
1285 * TRY -> catch1, -> finally push trystack entry
1286 * ... try block
1287 * "throw {exception}"
1288 * EVAL {exception}
1289 * THROW create exception
1290 * ... try block
1291 * " catch {expr}"
1292 * JUMP -> finally
1293 * catch1: PUSH exception
1294 * EVAL {expr}
1295 * MATCH
1296 * JUMP nomatch -> catch2
1297 * CATCH remove exception
1298 * ... catch block
1299 * " catch"
1300 * JUMP -> finally
1301 * catch2: CATCH remove exception
1302 * ... catch block
1303 * " finally"
1304 * finally:
1305 * ... finally block
1306 * " endtry"
1307 * ENDTRY pop trystack entry, may rethrow
1308 */
1309 char_u *
1310compile_try(char_u *arg, cctx_T *cctx)
1311{
1312 garray_T *instr = &cctx->ctx_instr;
1313 scope_T *try_scope;
1314 scope_T *scope;
1315
1316 if (misplaced_cmdmod(cctx))
1317 return NULL;
1318
1319 // scope that holds the jumps that go to catch/finally/endtry
1320 try_scope = new_scope(cctx, TRY_SCOPE);
1321 if (try_scope == NULL)
1322 return NULL;
1323
1324 if (cctx->ctx_skip != SKIP_YES)
1325 {
1326 isn_T *isn;
1327
1328 // "try_catch" is set when the first ":catch" is found or when no catch
1329 // is found and ":finally" is found.
1330 // "try_finally" is set when ":finally" is found
1331 // "try_endtry" is set when ":endtry" is found
1332 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1333 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1334 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001335 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1336 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001337 return NULL;
1338 }
1339
1340 // scope for the try block itself
1341 scope = new_scope(cctx, BLOCK_SCOPE);
1342 if (scope == NULL)
1343 return NULL;
1344
1345 return arg;
1346}
1347
1348/*
1349 * Compile "catch {expr}".
1350 */
1351 char_u *
1352compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1353{
1354 scope_T *scope = cctx->ctx_scope;
1355 garray_T *instr = &cctx->ctx_instr;
1356 char_u *p;
1357 isn_T *isn;
1358
1359 if (misplaced_cmdmod(cctx))
1360 return NULL;
1361
1362 // end block scope from :try or :catch
1363 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1364 compile_endblock(cctx);
1365 scope = cctx->ctx_scope;
1366
1367 // Error if not in a :try scope
1368 if (scope == NULL || scope->se_type != TRY_SCOPE)
1369 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001370 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001371 return NULL;
1372 }
1373
1374 if (scope->se_u.se_try.ts_caught_all)
1375 {
1376 emsg(_(e_catch_unreachable_after_catch_all));
1377 return NULL;
1378 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001379 if (!cctx->ctx_had_return)
1380 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001381
1382 if (cctx->ctx_skip != SKIP_YES)
1383 {
1384#ifdef FEAT_PROFILE
1385 // the profile-start should be after the jump
1386 if (cctx->ctx_compile_type == CT_PROFILE
1387 && instr->ga_len > 0
1388 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1389 .isn_type == ISN_PROF_START)
1390 --instr->ga_len;
1391#endif
1392 // Jump from end of previous block to :finally or :endtry
1393 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
1394 JUMP_ALWAYS, cctx) == FAIL)
1395 return NULL;
1396
1397 // End :try or :catch scope: set value in ISN_TRY instruction
1398 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001399 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1400 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001401 if (scope->se_u.se_try.ts_catch_label != 0)
1402 {
1403 // Previous catch without match jumps here
1404 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1405 isn->isn_arg.jump.jump_where = instr->ga_len;
1406 }
1407#ifdef FEAT_PROFILE
1408 if (cctx->ctx_compile_type == CT_PROFILE)
1409 {
1410 // a "throw" that jumps here needs to be counted
1411 generate_instr(cctx, ISN_PROF_END);
1412 // the "catch" is also counted
1413 generate_instr(cctx, ISN_PROF_START);
1414 }
1415#endif
1416 if (cctx->ctx_compile_type == CT_DEBUG)
1417 generate_instr_debug(cctx);
1418 }
1419
1420 p = skipwhite(arg);
1421 if (ends_excmd2(arg, p))
1422 {
1423 scope->se_u.se_try.ts_caught_all = TRUE;
1424 scope->se_u.se_try.ts_catch_label = 0;
1425 }
1426 else
1427 {
1428 char_u *end;
1429 char_u *pat;
1430 char_u *tofree = NULL;
1431 int dropped = 0;
1432 int len;
1433
1434 // Push v:exception, push {expr} and MATCH
1435 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1436
1437 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1438 if (*end != *p)
1439 {
1440 semsg(_(e_separator_mismatch_str), p);
1441 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001442 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001443 }
1444 if (tofree == NULL)
1445 len = (int)(end - (p + 1));
1446 else
1447 len = (int)(end - tofree);
1448 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1449 vim_free(tofree);
1450 p += len + 2 + dropped;
1451 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001452 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001453 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001454 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001455
1456 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1457 return NULL;
1458
1459 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1460 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1461 return NULL;
1462 }
1463
1464 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1465 return NULL;
1466
1467 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1468 return NULL;
1469 return p;
1470}
1471
1472 char_u *
1473compile_finally(char_u *arg, cctx_T *cctx)
1474{
1475 scope_T *scope = cctx->ctx_scope;
1476 garray_T *instr = &cctx->ctx_instr;
1477 isn_T *isn;
1478 int this_instr;
1479
1480 if (misplaced_cmdmod(cctx))
1481 return NULL;
1482
1483 // end block scope from :try or :catch
1484 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1485 compile_endblock(cctx);
1486 scope = cctx->ctx_scope;
1487
1488 // Error if not in a :try scope
1489 if (scope == NULL || scope->se_type != TRY_SCOPE)
1490 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001491 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001492 return NULL;
1493 }
1494
1495 if (cctx->ctx_skip != SKIP_YES)
1496 {
1497 // End :catch or :finally scope: set value in ISN_TRY instruction
1498 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001499 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001500 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001501 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001502 return NULL;
1503 }
1504
1505 this_instr = instr->ga_len;
1506#ifdef FEAT_PROFILE
1507 if (cctx->ctx_compile_type == CT_PROFILE
1508 && ((isn_T *)instr->ga_data)[this_instr - 1]
1509 .isn_type == ISN_PROF_START)
1510 {
1511 // jump to the profile start of the "finally"
1512 --this_instr;
1513
1514 // jump to the profile end above it
1515 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1516 .isn_type == ISN_PROF_END)
1517 --this_instr;
1518 }
1519#endif
1520
1521 // Fill in the "end" label in jumps at the end of the blocks.
1522 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1523 this_instr, cctx);
1524
1525 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001526 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1527 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1528 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001529 if (scope->se_u.se_try.ts_catch_label != 0)
1530 {
1531 // Previous catch without match jumps here
1532 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1533 isn->isn_arg.jump.jump_where = this_instr;
1534 scope->se_u.se_try.ts_catch_label = 0;
1535 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001536 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001537 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1538 return NULL;
1539 }
1540
1541 return arg;
1542}
1543
1544 char_u *
1545compile_endtry(char_u *arg, cctx_T *cctx)
1546{
1547 scope_T *scope = cctx->ctx_scope;
1548 garray_T *instr = &cctx->ctx_instr;
1549 isn_T *try_isn;
1550
1551 if (misplaced_cmdmod(cctx))
1552 return NULL;
1553
1554 // end block scope from :catch or :finally
1555 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1556 compile_endblock(cctx);
1557 scope = cctx->ctx_scope;
1558
1559 // Error if not in a :try scope
1560 if (scope == NULL || scope->se_type != TRY_SCOPE)
1561 {
1562 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001563 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001564 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001565 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001566 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001567 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001568 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001569 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001570 return NULL;
1571 }
1572
1573 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1574 if (cctx->ctx_skip != SKIP_YES)
1575 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001576 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1577 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001578 {
1579 emsg(_(e_missing_catch_or_finally));
1580 return NULL;
1581 }
1582
1583#ifdef FEAT_PROFILE
1584 if (cctx->ctx_compile_type == CT_PROFILE
1585 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1586 .isn_type == ISN_PROF_START)
1587 // move the profile start after "endtry" so that it's not counted when
1588 // the exception is rethrown.
1589 --instr->ga_len;
1590#endif
1591
1592 // Fill in the "end" label in jumps at the end of the blocks, if not
1593 // done by ":finally".
1594 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1595 instr->ga_len, cctx);
1596
1597 if (scope->se_u.se_try.ts_catch_label != 0)
1598 {
1599 // Last catch without match jumps here
1600 isn_T *isn = ((isn_T *)instr->ga_data)
1601 + scope->se_u.se_try.ts_catch_label;
1602 isn->isn_arg.jump.jump_where = instr->ga_len;
1603 }
1604 }
1605
Bram Moolenaar53c29612022-01-12 16:18:18 +00001606 // If there is a finally clause that ends in return then we will return.
1607 // If one of the blocks didn't end in "return" or we did not catch all
1608 // exceptions reset the had_return flag.
1609 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1610 && (scope->se_u.se_try.ts_no_return
1611 || !scope->se_u.se_try.ts_caught_all))
1612 cctx->ctx_had_return = FALSE;
1613
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001614 compile_endblock(cctx);
1615
1616 if (cctx->ctx_skip != SKIP_YES)
1617 {
1618 // End :catch or :finally scope: set instruction index in ISN_TRY
1619 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001620 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001621 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001622 return NULL;
1623#ifdef FEAT_PROFILE
1624 if (cctx->ctx_compile_type == CT_PROFILE)
1625 generate_instr(cctx, ISN_PROF_START);
1626#endif
1627 }
1628 return arg;
1629}
1630
1631/*
1632 * compile "throw {expr}"
1633 */
1634 char_u *
1635compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1636{
1637 char_u *p = skipwhite(arg);
1638
1639 if (compile_expr0(&p, cctx) == FAIL)
1640 return NULL;
1641 if (cctx->ctx_skip == SKIP_YES)
1642 return p;
1643 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1644 return NULL;
1645 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1646 return NULL;
1647
1648 return p;
1649}
1650
1651 char_u *
1652compile_eval(char_u *arg, cctx_T *cctx)
1653{
1654 char_u *p = arg;
1655 int name_only;
1656 long lnum = SOURCING_LNUM;
1657
1658 // find_ex_command() will consider a variable name an expression, assuming
1659 // that something follows on the next line. Check that something actually
1660 // follows, otherwise it's probably a misplaced command.
1661 name_only = cmd_is_name_only(arg);
1662
1663 if (compile_expr0(&p, cctx) == FAIL)
1664 return NULL;
1665
1666 if (name_only && lnum == SOURCING_LNUM)
1667 {
1668 semsg(_(e_expression_without_effect_str), arg);
1669 return NULL;
1670 }
1671
1672 // drop the result
1673 generate_instr_drop(cctx, ISN_DROP, 1);
1674
1675 return skipwhite(p);
1676}
1677
1678/*
1679 * compile "echo expr"
1680 * compile "echomsg expr"
1681 * compile "echoerr expr"
1682 * compile "echoconsole expr"
1683 * compile "execute expr"
1684 */
1685 char_u *
1686compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
1687{
1688 char_u *p = arg;
1689 char_u *prev = arg;
1690 char_u *expr_start;
1691 int count = 0;
1692 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001693 type_T *type;
1694
1695 for (;;)
1696 {
1697 if (ends_excmd2(prev, p))
1698 break;
1699 expr_start = p;
1700 if (compile_expr0(&p, cctx) == FAIL)
1701 return NULL;
1702
1703 if (cctx->ctx_skip != SKIP_YES)
1704 {
1705 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001706 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001707 if (type->tt_type == VAR_VOID)
1708 {
1709 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
1710 return NULL;
1711 }
1712 }
1713
1714 ++count;
1715 prev = p;
1716 p = skipwhite(p);
1717 }
1718
1719 if (count > 0)
1720 {
1721 long save_lnum = cctx->ctx_lnum;
1722
1723 // Use the line number where the command started.
1724 cctx->ctx_lnum = start_ctx_lnum;
1725
1726 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
1727 generate_ECHO(cctx, cmdidx == CMD_echo, count);
1728 else if (cmdidx == CMD_execute)
1729 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
1730 else if (cmdidx == CMD_echomsg)
1731 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
1732 else if (cmdidx == CMD_echoconsole)
1733 generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
1734 else
1735 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
1736
1737 cctx->ctx_lnum = save_lnum;
1738 }
1739 return p;
1740}
1741
1742/*
1743 * If "eap" has a range that is not a constant generate an ISN_RANGE
1744 * instruction to compute it and return OK.
1745 * Otherwise return FAIL, the caller must deal with any range.
1746 */
1747 static int
1748compile_variable_range(exarg_T *eap, cctx_T *cctx)
1749{
1750 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
1751 char_u *p = skipdigits(eap->cmd);
1752
1753 if (p == range_end)
1754 return FAIL;
1755 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
1756}
1757
1758/*
1759 * :put r
1760 * :put ={expr}
1761 */
1762 char_u *
1763compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
1764{
1765 char_u *line = arg;
1766 linenr_T lnum;
1767 char *errormsg;
1768 int above = eap->forceit;
1769
1770 eap->regname = *line;
1771
1772 if (eap->regname == '=')
1773 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00001774 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001775
1776 if (compile_expr0(&p, cctx) == FAIL)
1777 return NULL;
1778 line = p;
1779 }
1780 else if (eap->regname != NUL)
1781 ++line;
1782
1783 if (compile_variable_range(eap, cctx) == OK)
1784 {
1785 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
1786 }
1787 else
1788 {
1789 // Either no range or a number.
1790 // "errormsg" will not be set because the range is ADDR_LINES.
1791 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
1792 // cannot happen
1793 return NULL;
1794 if (eap->addr_count == 0)
1795 lnum = -1;
1796 else
1797 lnum = eap->line2;
1798 if (above)
1799 --lnum;
1800 }
1801
1802 generate_PUT(cctx, eap->regname, lnum);
1803 return line;
1804}
1805
1806/*
1807 * A command that is not compiled, execute with legacy code.
1808 */
1809 char_u *
1810compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
1811{
1812 char_u *line = line_arg;
1813 char_u *p;
1814 int has_expr = FALSE;
1815 char_u *nextcmd = (char_u *)"";
1816 char_u *tofree = NULL;
1817 char_u *cmd_arg = NULL;
1818
1819 if (cctx->ctx_skip == SKIP_YES)
1820 goto theend;
1821
1822 // If there was a prececing command modifier, drop it and include it in the
1823 // EXEC command.
1824 if (cctx->ctx_has_cmdmod)
1825 {
1826 garray_T *instr = &cctx->ctx_instr;
1827 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
1828
1829 if (isn->isn_type == ISN_CMDMOD)
1830 {
1831 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
1832 ->cmod_filter_regmatch.regprog);
1833 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
1834 --instr->ga_len;
1835 cctx->ctx_has_cmdmod = FALSE;
1836 }
1837 }
1838
1839 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
1840 {
1841 long argt = eap->argt;
1842 int usefilter = FALSE;
1843
1844 has_expr = argt & (EX_XFILE | EX_EXPAND);
1845
1846 // If the command can be followed by a bar, find the bar and truncate
1847 // it, so that the following command can be compiled.
1848 // The '|' is overwritten with a NUL, it is put back below.
1849 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
1850 && *eap->arg == '!')
1851 // :w !filter or :r !filter or :r! filter
1852 usefilter = TRUE;
1853 if ((argt & EX_TRLBAR) && !usefilter)
1854 {
1855 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00001856 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001857 if (eap->nextcmd != NULL)
1858 nextcmd = eap->nextcmd;
1859 }
1860 else if (eap->cmdidx == CMD_wincmd)
1861 {
1862 p = eap->arg;
1863 if (*p != NUL)
1864 ++p;
1865 if (*p == 'g' || *p == Ctrl_G)
1866 ++p;
1867 p = skipwhite(p);
1868 if (*p == '|')
1869 {
1870 *p = NUL;
1871 nextcmd = p + 1;
1872 }
1873 }
1874 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
1875 {
1876 // If there is a trailing '{' read lines until the '}'
1877 p = eap->arg + STRLEN(eap->arg) - 1;
1878 while (p > eap->arg && VIM_ISWHITE(*p))
1879 --p;
1880 if (*p == '{')
1881 {
1882 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00001883 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001884 int start_lnum = SOURCING_LNUM;
1885
1886 CLEAR_FIELD(ea);
1887 ea.arg = eap->arg;
1888 fill_exarg_from_cctx(&ea, cctx);
1889 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
1890 if (tofree != NULL)
1891 {
1892 *p = NUL;
1893 line = concat_str(line, tofree);
1894 if (line == NULL)
1895 goto theend;
1896 vim_free(tofree);
1897 tofree = line;
1898 SOURCING_LNUM = start_lnum;
1899 }
1900 }
1901 }
1902 }
1903
1904 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
1905 {
1906 // expand filename in "syntax include [@group] filename"
1907 has_expr = TRUE;
1908 eap->arg = skipwhite(eap->arg + 7);
1909 if (*eap->arg == '@')
1910 eap->arg = skiptowhite(eap->arg);
1911 }
1912
1913 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
1914 && STRLEN(eap->arg) > 4)
1915 {
1916 int delim = *eap->arg;
1917
1918 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
1919 if (*p == delim)
1920 cmd_arg = p + 1;
1921 }
1922
1923 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
1924 cmd_arg = eap->arg;
1925
1926 if (cmd_arg != NULL)
1927 {
1928 exarg_T nea;
1929
1930 CLEAR_FIELD(nea);
1931 nea.cmd = cmd_arg;
1932 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
1933 if (nea.cmdidx < CMD_SIZE)
1934 {
1935 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
1936 if (has_expr)
1937 eap->arg = skiptowhite(eap->arg);
1938 }
1939 }
1940
1941 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
1942 {
1943 int count = 0;
1944 char_u *start = skipwhite(line);
1945
1946 // :cmd xxx`=expr1`yyy`=expr2`zzz
1947 // PUSHS ":cmd xxx"
1948 // eval expr1
1949 // PUSHS "yyy"
1950 // eval expr2
1951 // PUSHS "zzz"
1952 // EXECCONCAT 5
1953 for (;;)
1954 {
1955 if (p > start)
1956 {
1957 char_u *val = vim_strnsave(start, p - start);
1958
1959 generate_PUSHS(cctx, &val);
1960 ++count;
1961 }
1962 p += 2;
1963 if (compile_expr0(&p, cctx) == FAIL)
1964 return NULL;
1965 may_generate_2STRING(-1, TRUE, cctx);
1966 ++count;
1967 p = skipwhite(p);
1968 if (*p != '`')
1969 {
1970 emsg(_(e_missing_backtick));
1971 return NULL;
1972 }
1973 start = p + 1;
1974
1975 p = (char_u *)strstr((char *)start, "`=");
1976 if (p == NULL)
1977 {
1978 if (*skipwhite(start) != NUL)
1979 {
1980 char_u *val = vim_strsave(start);
1981
1982 generate_PUSHS(cctx, &val);
1983 ++count;
1984 }
1985 break;
1986 }
1987 }
1988 generate_EXECCONCAT(cctx, count);
1989 }
1990 else
1991 generate_EXEC_copy(cctx, ISN_EXEC, line);
1992
1993theend:
1994 if (*nextcmd != NUL)
1995 {
1996 // the parser expects a pointer to the bar, put it back
1997 --nextcmd;
1998 *nextcmd = '|';
1999 }
2000 vim_free(tofree);
2001
2002 return nextcmd;
2003}
2004
2005/*
2006 * A script command with heredoc, e.g.
2007 * ruby << EOF
2008 * command
2009 * EOF
2010 * Has been turned into one long line with NL characters by
2011 * get_function_body():
2012 * ruby << EOF<NL> command<NL>EOF
2013 */
2014 char_u *
2015compile_script(char_u *line, cctx_T *cctx)
2016{
2017 if (cctx->ctx_skip != SKIP_YES)
2018 {
2019 isn_T *isn;
2020
2021 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2022 return NULL;
2023 isn->isn_arg.string = vim_strsave(line);
2024 }
2025 return (char_u *)"";
2026}
2027
2028
2029/*
2030 * :s/pat/repl/
2031 */
2032 char_u *
2033compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2034{
2035 char_u *cmd = eap->arg;
2036 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2037
2038 if (expr != NULL)
2039 {
2040 int delimiter = *cmd++;
2041
2042 // There is a \=expr, find it in the substitute part.
2043 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2044 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2045 {
2046 garray_T save_ga = cctx->ctx_instr;
2047 char_u *end;
2048 int expr_res;
2049 int trailing_error;
2050 int instr_count;
2051 isn_T *instr;
2052 isn_T *isn;
2053
2054 cmd += 3;
2055 end = skip_substitute(cmd, delimiter);
2056
2057 // Temporarily reset the list of instructions so that the jump
2058 // labels are correct.
2059 cctx->ctx_instr.ga_len = 0;
2060 cctx->ctx_instr.ga_maxlen = 0;
2061 cctx->ctx_instr.ga_data = NULL;
2062 expr_res = compile_expr0(&cmd, cctx);
2063 if (end[-1] == NUL)
2064 end[-1] = delimiter;
2065 cmd = skipwhite(cmd);
2066 trailing_error = *cmd != delimiter && *cmd != NUL;
2067
2068 if (expr_res == FAIL || trailing_error
2069 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2070 {
2071 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002072 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002073 clear_instr_ga(&cctx->ctx_instr);
2074 cctx->ctx_instr = save_ga;
2075 return NULL;
2076 }
2077
2078 // Move the generated instructions into the ISN_SUBSTITUTE
2079 // instructions, then restore the list of instructions before
2080 // adding the ISN_SUBSTITUTE instruction.
2081 instr_count = cctx->ctx_instr.ga_len;
2082 instr = cctx->ctx_instr.ga_data;
2083 instr[instr_count].isn_type = ISN_FINISH;
2084
2085 cctx->ctx_instr = save_ga;
2086 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2087 {
2088 int idx;
2089
2090 for (idx = 0; idx < instr_count; ++idx)
2091 delete_instr(instr + idx);
2092 vim_free(instr);
2093 return NULL;
2094 }
2095 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2096 isn->isn_arg.subs.subs_instr = instr;
2097
2098 // skip over flags
2099 if (*end == '&')
2100 ++end;
2101 while (ASCII_ISALPHA(*end) || *end == '#')
2102 ++end;
2103 return end;
2104 }
2105 }
2106
2107 return compile_exec(arg, eap, cctx);
2108}
2109
2110 char_u *
2111compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2112{
2113 char_u *arg = eap->arg;
2114 lhs_T *lhs = &cctx->ctx_redir_lhs;
2115
2116 if (lhs->lhs_name != NULL)
2117 {
2118 if (STRNCMP(arg, "END", 3) == 0)
2119 {
2120 if (lhs->lhs_append)
2121 {
2122 // First load the current variable value.
2123 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
2124 cctx) == FAIL)
2125 return NULL;
2126 }
2127
2128 // Gets the redirected text and put it on the stack, then store it
2129 // in the variable.
2130 generate_instr_type(cctx, ISN_REDIREND, &t_string);
2131
2132 if (lhs->lhs_append)
LemonBoy372bcce2022-04-25 12:43:20 +01002133 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002134
2135 if (lhs->lhs_has_index)
2136 {
2137 // Use the info in "lhs" to store the value at the index in the
2138 // list or dict.
2139 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
2140 &t_string, cctx) == FAIL)
2141 return NULL;
2142 }
Bram Moolenaar5cd64792021-12-25 18:23:24 +00002143 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002144 return NULL;
2145
2146 VIM_CLEAR(lhs->lhs_name);
2147 VIM_CLEAR(lhs->lhs_whole);
2148 return arg + 3;
2149 }
2150 emsg(_(e_cannot_nest_redir));
2151 return NULL;
2152 }
2153
2154 if (arg[0] == '=' && arg[1] == '>')
2155 {
2156 int append = FALSE;
2157
2158 // redirect to a variable is compiled
2159 arg += 2;
2160 if (*arg == '>')
2161 {
2162 ++arg;
2163 append = TRUE;
2164 }
2165 arg = skipwhite(arg);
2166
2167 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002168 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002169 return NULL;
2170 if (need_type(&t_string, lhs->lhs_member_type,
2171 -1, 0, cctx, FALSE, FALSE) == FAIL)
2172 return NULL;
2173 generate_instr(cctx, ISN_REDIRSTART);
2174 lhs->lhs_append = append;
2175 if (lhs->lhs_has_index)
2176 {
2177 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2178 if (lhs->lhs_whole == NULL)
2179 return NULL;
2180 }
2181
2182 return arg + lhs->lhs_varlen_total;
2183 }
2184
2185 // other redirects are handled like at script level
2186 return compile_exec(line, eap, cctx);
2187}
2188
2189#if defined(FEAT_QUICKFIX) || defined(PROTO)
2190 char_u *
2191compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2192{
2193 isn_T *isn;
2194 char_u *p;
2195
2196 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2197 if (isn == NULL)
2198 return NULL;
2199 isn->isn_arg.number = eap->cmdidx;
2200
2201 p = eap->arg;
2202 if (compile_expr0(&p, cctx) == FAIL)
2203 return NULL;
2204
2205 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2206 if (isn == NULL)
2207 return NULL;
2208 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2209 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2210 return NULL;
2211 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2212 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2213 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2214
2215 return p;
2216}
2217#endif
2218
2219/*
2220 * Compile "return [expr]".
2221 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2222 */
2223 char_u *
2224compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2225{
2226 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002227 type_T *stack_type;
2228
2229 if (*p != NUL && *p != '|' && *p != '\n')
2230 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002231 // For a lambda, "return expr" is always used, also when "expr" results
2232 // in a void.
2233 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2234 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002235 {
2236 emsg(_(e_returning_value_in_function_without_return_type));
2237 return NULL;
2238 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002239 if (legacy)
2240 {
2241 int save_flags = cmdmod.cmod_flags;
2242
2243 generate_LEGACY_EVAL(cctx, p);
2244 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
2245 0, cctx, FALSE, FALSE) == FAIL)
2246 return NULL;
2247 cmdmod.cmod_flags |= CMOD_LEGACY;
2248 (void)skip_expr(&p, NULL);
2249 cmdmod.cmod_flags = save_flags;
2250 }
2251 else
2252 {
2253 // compile return argument into instructions
2254 if (compile_expr0(&p, cctx) == FAIL)
2255 return NULL;
2256 }
2257
2258 if (cctx->ctx_skip != SKIP_YES)
2259 {
2260 // "check_return_type" with uf_ret_type set to &t_unknown is used
2261 // for an inline function without a specified return type. Set the
2262 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002263 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002264 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002265 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002266 || (!check_return_type
2267 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2268 {
2269 cctx->ctx_ufunc->uf_ret_type = stack_type;
2270 }
2271 else
2272 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002273 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
2274 0, cctx, FALSE, FALSE) == FAIL)
2275 return NULL;
2276 }
2277 }
2278 }
2279 else
2280 {
2281 // "check_return_type" cannot be TRUE, only used for a lambda which
2282 // always has an argument.
2283 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2284 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2285 {
2286 emsg(_(e_missing_return_value));
2287 return NULL;
2288 }
2289
2290 // No argument, return zero.
2291 generate_PUSHNR(cctx, 0);
2292 }
2293
2294 // Undo any command modifiers.
2295 generate_undo_cmdmods(cctx);
2296
2297 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2298 return NULL;
2299
2300 // "return val | endif" is possible
2301 return skipwhite(p);
2302}
2303
2304/*
2305 * Check if the separator for a :global or :substitute command is OK.
2306 */
2307 int
2308check_global_and_subst(char_u *cmd, char_u *arg)
2309{
2310 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2311 {
2312 semsg(_(e_separator_not_supported_str), arg);
2313 return FAIL;
2314 }
2315 if (VIM_ISWHITE(cmd[1]))
2316 {
2317 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2318 return FAIL;
2319 }
2320 return OK;
2321}
2322
2323
2324#endif // defined(FEAT_EVAL)