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