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