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