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