blob: 08f11a688e9a286b53329e1b8af3c1d24d1d2b69 [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{
Bram Moolenaardbdd16b2022-08-14 21:46:07 +010095 if (*name == NUL)
96 {
97 semsg(_(e_argument_required_for_str), "unlet");
98 return FAIL;
99 }
100
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000101 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
102 {
103 // "unlet s:var" is allowed in legacy script.
104 if (*name == 's' && !script_is_vim9())
105 return OK;
106 semsg(_(e_cannot_unlet_str), name);
107 return FAIL;
108 }
109 return OK;
110}
111
112/*
113 * Callback passed to ex_unletlock().
114 */
115 static int
116compile_unlet(
117 lval_T *lvp,
118 char_u *name_end,
119 exarg_T *eap,
120 int deep UNUSED,
121 void *coookie)
122{
123 cctx_T *cctx = coookie;
124 char_u *p = lvp->ll_name;
125 int cc = *name_end;
126 int ret = OK;
127
128 if (cctx->ctx_skip == SKIP_YES)
129 return OK;
130
131 *name_end = NUL;
132 if (*p == '$')
133 {
134 // :unlet $ENV_VAR
135 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
136 }
137 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
138 {
139 lhs_T lhs;
140
141 // This is similar to assigning: lookup the list/dict, compile the
142 // idx/key. Then instead of storing the value unlet the item.
143 // unlet {list}[idx]
144 // unlet {dict}[key] dict.key
145 //
146 // Figure out the LHS type and other properties.
147 //
Bram Moolenaar97f8c102022-04-02 19:43:57 +0100148 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, FALSE, 0, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000149
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000150 // Use the info in "lhs" to unlet the item at the index in the
151 // list or dict.
152 if (ret == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000153 {
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000154 if (!lhs.lhs_has_index)
155 {
156 semsg(_(e_cannot_unlet_imported_item_str), p);
157 ret = FAIL;
158 }
159 else
160 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000161 }
162
163 vim_free(lhs.lhs_name);
164 }
165 else if (check_vim9_unlet(p) == FAIL)
166 {
167 ret = FAIL;
168 }
169 else
170 {
171 // Normal name. Only supports g:, w:, t: and b: namespaces.
172 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
173 }
174
175 *name_end = cc;
176 return ret;
177}
178
179/*
180 * Callback passed to ex_unletlock().
181 */
182 static int
183compile_lock_unlock(
184 lval_T *lvp,
185 char_u *name_end,
186 exarg_T *eap,
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000187 int deep,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000188 void *coookie)
189{
190 cctx_T *cctx = coookie;
191 int cc = *name_end;
192 char_u *p = lvp->ll_name;
193 int ret = OK;
194 size_t len;
195 char_u *buf;
196 isntype_T isn = ISN_EXEC;
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100197 char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000198
199 if (cctx->ctx_skip == SKIP_YES)
200 return OK;
201
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100202 if (*p == NUL)
203 {
204 semsg(_(e_argument_required_for_str), cmd);
205 return FAIL;
206 }
207
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000208 // Cannot use :lockvar and :unlockvar on local variables.
209 if (p[1] != ':')
210 {
211 char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
212
213 if (lookup_local(p, end - p, NULL, cctx) == OK)
214 {
215 char_u *s = p;
216
217 if (*end != '.' && *end != '[')
218 {
219 emsg(_(e_cannot_lock_unlock_local_variable));
220 return FAIL;
221 }
222
223 // For "d.member" put the local variable on the stack, it will be
224 // passed to ex_lockvar() indirectly.
225 if (compile_load(&s, end, cctx, FALSE, FALSE) == FAIL)
226 return FAIL;
227 isn = ISN_LOCKUNLOCK;
228 }
229 }
230
231 // Checking is done at runtime.
232 *name_end = NUL;
233 len = name_end - p + 20;
234 buf = alloc(len);
235 if (buf == NULL)
236 ret = FAIL;
237 else
238 {
Bram Moolenaare939f5e2022-01-26 21:32:59 +0000239 if (deep < 0)
240 vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
241 else
242 vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000243 ret = generate_EXEC_copy(cctx, isn, buf);
244
245 vim_free(buf);
246 *name_end = cc;
247 }
248 return ret;
249}
250
251/*
252 * compile "unlet var", "lock var" and "unlock var"
253 * "arg" points to "var".
254 */
255 char_u *
256compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
257{
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000258 int deep = 0;
259 char_u *p = arg;
260
261 if (eap->cmdidx != CMD_unlet)
262 {
263 if (eap->forceit)
264 deep = -1;
265 else if (vim_isdigit(*p))
266 {
267 deep = getdigits(&p);
268 p = skipwhite(p);
269 }
270 else
271 deep = 2;
272 }
273
274 ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000275 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
276 cctx);
277 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
278}
279
280/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100281 * Generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
282 * "funcref_idx" is used for JUMP_WHILE_FALSE
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000283 */
284 static int
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100285compile_jump_to_end(
286 endlabel_T **el,
287 jumpwhen_T when,
288 int funcref_idx,
289 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000290{
291 garray_T *instr = &cctx->ctx_instr;
292 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
293
294 if (endlabel == NULL)
295 return FAIL;
296 endlabel->el_next = *el;
297 *el = endlabel;
298 endlabel->el_end_label = instr->ga_len;
299
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100300 if (when == JUMP_WHILE_FALSE)
301 generate_WHILE(cctx, funcref_idx);
302 else
303 generate_JUMP(cctx, when, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000304 return OK;
305}
306
307 static void
308compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
309{
310 garray_T *instr = &cctx->ctx_instr;
311
312 while (*el != NULL)
313 {
314 endlabel_T *cur = (*el);
315 isn_T *isn;
316
317 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
318 isn->isn_arg.jump.jump_where = jump_where;
319 *el = cur->el_next;
320 vim_free(cur);
321 }
322}
323
324 static void
325compile_free_jump_to_end(endlabel_T **el)
326{
327 while (*el != NULL)
328 {
329 endlabel_T *cur = (*el);
330
331 *el = cur->el_next;
332 vim_free(cur);
333 }
334}
335
336/*
337 * Create a new scope and set up the generic items.
338 */
339 static scope_T *
340new_scope(cctx_T *cctx, scopetype_T type)
341{
342 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
343
344 if (scope == NULL)
345 return NULL;
346 scope->se_outer = cctx->ctx_scope;
347 cctx->ctx_scope = scope;
348 scope->se_type = type;
349 scope->se_local_count = cctx->ctx_locals.ga_len;
350 return scope;
351}
352
353/*
354 * Free the current scope and go back to the outer scope.
355 */
356 void
357drop_scope(cctx_T *cctx)
358{
359 scope_T *scope = cctx->ctx_scope;
360
361 if (scope == NULL)
362 {
363 iemsg("calling drop_scope() without a scope");
364 return;
365 }
366 cctx->ctx_scope = scope->se_outer;
367 switch (scope->se_type)
368 {
369 case IF_SCOPE:
370 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
371 case FOR_SCOPE:
372 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
373 case WHILE_SCOPE:
374 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
375 case TRY_SCOPE:
376 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
377 case NO_SCOPE:
378 case BLOCK_SCOPE:
379 break;
380 }
381 vim_free(scope);
382}
383
384 static int
385misplaced_cmdmod(cctx_T *cctx)
386{
387 garray_T *instr = &cctx->ctx_instr;
388
389 if (cctx->ctx_has_cmdmod
390 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
391 == ISN_CMDMOD)
392 {
393 emsg(_(e_misplaced_command_modifier));
394 return TRUE;
395 }
396 return FALSE;
397}
398
399/*
400 * compile "if expr"
401 *
402 * "if expr" Produces instructions:
403 * EVAL expr Push result of "expr"
404 * JUMP_IF_FALSE end
405 * ... body ...
406 * end:
407 *
408 * "if expr | else" Produces instructions:
409 * EVAL expr Push result of "expr"
410 * JUMP_IF_FALSE else
411 * ... body ...
412 * JUMP_ALWAYS end
413 * else:
414 * ... body ...
415 * end:
416 *
417 * "if expr1 | elseif expr2 | else" Produces instructions:
418 * EVAL expr Push result of "expr"
419 * JUMP_IF_FALSE elseif
420 * ... body ...
421 * JUMP_ALWAYS end
422 * elseif:
423 * EVAL expr Push result of "expr"
424 * JUMP_IF_FALSE else
425 * ... body ...
426 * JUMP_ALWAYS end
427 * else:
428 * ... body ...
429 * end:
430 */
431 char_u *
432compile_if(char_u *arg, cctx_T *cctx)
433{
434 char_u *p = arg;
435 garray_T *instr = &cctx->ctx_instr;
436 int instr_count = instr->ga_len;
437 scope_T *scope;
438 skip_T skip_save = cctx->ctx_skip;
439 ppconst_T ppconst;
440
441 CLEAR_FIELD(ppconst);
442 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
443 {
444 clear_ppconst(&ppconst);
445 return NULL;
446 }
447 if (!ends_excmd2(arg, skipwhite(p)))
448 {
Bram Moolenaar74409f62022-01-01 15:58:22 +0000449 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000450 return NULL;
451 }
452 if (cctx->ctx_skip == SKIP_YES)
453 clear_ppconst(&ppconst);
454 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
455 {
456 int error = FALSE;
457 int v;
458
459 // The expression results in a constant.
460 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
461 clear_ppconst(&ppconst);
462 if (error)
463 return NULL;
464 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
465 }
466 else
467 {
468 // Not a constant, generate instructions for the expression.
469 cctx->ctx_skip = SKIP_UNKNOWN;
470 if (generate_ppconst(cctx, &ppconst) == FAIL)
471 return NULL;
472 if (bool_on_stack(cctx) == FAIL)
473 return NULL;
474 }
475
476 // CMDMOD_REV must come before the jump
477 generate_undo_cmdmods(cctx);
478
479 scope = new_scope(cctx, IF_SCOPE);
480 if (scope == NULL)
481 return NULL;
482 scope->se_skip_save = skip_save;
483 // "is_had_return" will be reset if any block does not end in :return
484 scope->se_u.se_if.is_had_return = TRUE;
485
486 if (cctx->ctx_skip == SKIP_UNKNOWN)
487 {
488 // "where" is set when ":elseif", "else" or ":endif" is found
489 scope->se_u.se_if.is_if_label = instr->ga_len;
490 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
491 }
492 else
493 scope->se_u.se_if.is_if_label = -1;
494
495#ifdef FEAT_PROFILE
496 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
497 && skip_save != SKIP_YES)
498 {
499 // generated a profile start, need to generate a profile end, since it
500 // won't be done after returning
501 cctx->ctx_skip = SKIP_NOT;
502 generate_instr(cctx, ISN_PROF_END);
503 cctx->ctx_skip = SKIP_YES;
504 }
505#endif
506
507 return p;
508}
509
510 char_u *
511compile_elseif(char_u *arg, cctx_T *cctx)
512{
513 char_u *p = arg;
514 garray_T *instr = &cctx->ctx_instr;
515 int instr_count;
516 isn_T *isn;
517 scope_T *scope = cctx->ctx_scope;
518 ppconst_T ppconst;
519 skip_T save_skip = cctx->ctx_skip;
520
521 if (scope == NULL || scope->se_type != IF_SCOPE)
522 {
523 emsg(_(e_elseif_without_if));
524 return NULL;
525 }
526 unwind_locals(cctx, scope->se_local_count);
527 if (!cctx->ctx_had_return)
528 scope->se_u.se_if.is_had_return = FALSE;
529
530 if (cctx->ctx_skip == SKIP_NOT)
531 {
532 // previous block was executed, this one and following will not
533 cctx->ctx_skip = SKIP_YES;
534 scope->se_u.se_if.is_seen_skip_not = TRUE;
535 }
536 if (scope->se_u.se_if.is_seen_skip_not)
537 {
538 // A previous block was executed, skip over expression and bail out.
539 // Do not count the "elseif" for profiling and cmdmod
540 instr->ga_len = current_instr_idx(cctx);
541
542 skip_expr_cctx(&p, cctx);
543 return p;
544 }
545
546 if (cctx->ctx_skip == SKIP_UNKNOWN)
547 {
548 int moved_cmdmod = FALSE;
549 int saved_debug = FALSE;
550 isn_T debug_isn;
551
552 // Move any CMDMOD instruction to after the jump
553 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
554 {
555 if (GA_GROW_FAILS(instr, 1))
556 return NULL;
557 ((isn_T *)instr->ga_data)[instr->ga_len] =
558 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
559 --instr->ga_len;
560 moved_cmdmod = TRUE;
561 }
562
563 // Remove the already generated ISN_DEBUG, it is written below the
564 // ISN_FOR instruction.
565 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
566 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
567 .isn_type == ISN_DEBUG)
568 {
569 --instr->ga_len;
570 debug_isn = ((isn_T *)instr->ga_data)[instr->ga_len];
571 saved_debug = TRUE;
572 }
573
574 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100575 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000576 return NULL;
577 // previous "if" or "elseif" jumps here
578 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
579 isn->isn_arg.jump.jump_where = instr->ga_len;
580
581 if (moved_cmdmod)
582 ++instr->ga_len;
583
584 if (saved_debug)
585 {
586 // move the debug instruction here
587 if (GA_GROW_FAILS(instr, 1))
588 return NULL;
589 ((isn_T *)instr->ga_data)[instr->ga_len] = debug_isn;
590 ++instr->ga_len;
591 }
592 }
593
594 // compile "expr"; if we know it evaluates to FALSE skip the block
595 CLEAR_FIELD(ppconst);
596 if (cctx->ctx_skip == SKIP_YES)
597 {
598 cctx->ctx_skip = SKIP_UNKNOWN;
599#ifdef FEAT_PROFILE
600 if (cctx->ctx_compile_type == CT_PROFILE)
601 // the previous block was skipped, need to profile this line
602 generate_instr(cctx, ISN_PROF_START);
603#endif
604 if (cctx->ctx_compile_type == CT_DEBUG)
605 // the previous block was skipped, may want to debug this line
606 generate_instr_debug(cctx);
607 }
608
609 instr_count = instr->ga_len;
610 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
611 {
612 clear_ppconst(&ppconst);
613 return NULL;
614 }
615 cctx->ctx_skip = save_skip;
616 if (!ends_excmd2(arg, skipwhite(p)))
617 {
618 clear_ppconst(&ppconst);
Bram Moolenaar74409f62022-01-01 15:58:22 +0000619 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000620 return NULL;
621 }
622 if (scope->se_skip_save == SKIP_YES)
623 clear_ppconst(&ppconst);
624 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
625 {
626 int error = FALSE;
627 int v;
628
629 // The expression result is a constant.
630 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
631 if (error)
632 {
633 clear_ppconst(&ppconst);
634 return NULL;
635 }
636 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
637 clear_ppconst(&ppconst);
638 scope->se_u.se_if.is_if_label = -1;
639 }
640 else
641 {
642 // Not a constant, generate instructions for the expression.
643 cctx->ctx_skip = SKIP_UNKNOWN;
644 if (generate_ppconst(cctx, &ppconst) == FAIL)
645 return NULL;
646 if (bool_on_stack(cctx) == FAIL)
647 return NULL;
648
649 // CMDMOD_REV must come before the jump
650 generate_undo_cmdmods(cctx);
651
652 // "where" is set when ":elseif", "else" or ":endif" is found
653 scope->se_u.se_if.is_if_label = instr->ga_len;
654 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
655 }
656
657 return p;
658}
659
660 char_u *
661compile_else(char_u *arg, cctx_T *cctx)
662{
663 char_u *p = arg;
664 garray_T *instr = &cctx->ctx_instr;
665 isn_T *isn;
666 scope_T *scope = cctx->ctx_scope;
667
668 if (scope == NULL || scope->se_type != IF_SCOPE)
669 {
670 emsg(_(e_else_without_if));
671 return NULL;
672 }
673 unwind_locals(cctx, scope->se_local_count);
674 if (!cctx->ctx_had_return)
675 scope->se_u.se_if.is_had_return = FALSE;
676 scope->se_u.se_if.is_seen_else = TRUE;
677
678#ifdef FEAT_PROFILE
679 if (cctx->ctx_compile_type == CT_PROFILE)
680 {
681 if (cctx->ctx_skip == SKIP_NOT
682 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
683 .isn_type == ISN_PROF_START)
684 // the previous block was executed, do not count "else" for
685 // profiling
686 --instr->ga_len;
687 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
688 {
689 // the previous block was not executed, this one will, do count the
690 // "else" for profiling
691 cctx->ctx_skip = SKIP_NOT;
692 generate_instr(cctx, ISN_PROF_END);
693 generate_instr(cctx, ISN_PROF_START);
694 cctx->ctx_skip = SKIP_YES;
695 }
696 }
697#endif
698
699 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
700 {
701 // jump from previous block to the end, unless the else block is empty
702 if (cctx->ctx_skip == SKIP_UNKNOWN)
703 {
704 if (!cctx->ctx_had_return
705 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100706 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000707 return NULL;
708 }
709
710 if (cctx->ctx_skip == SKIP_UNKNOWN)
711 {
712 if (scope->se_u.se_if.is_if_label >= 0)
713 {
714 // previous "if" or "elseif" jumps here
715 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
716 isn->isn_arg.jump.jump_where = instr->ga_len;
717 scope->se_u.se_if.is_if_label = -1;
718 }
719 }
720
721 if (cctx->ctx_skip != SKIP_UNKNOWN)
722 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
723 }
724
725 return p;
726}
727
728 char_u *
729compile_endif(char_u *arg, cctx_T *cctx)
730{
731 scope_T *scope = cctx->ctx_scope;
732 ifscope_T *ifscope;
733 garray_T *instr = &cctx->ctx_instr;
734 isn_T *isn;
735
736 if (misplaced_cmdmod(cctx))
737 return NULL;
738
739 if (scope == NULL || scope->se_type != IF_SCOPE)
740 {
741 emsg(_(e_endif_without_if));
742 return NULL;
743 }
744 ifscope = &scope->se_u.se_if;
745 unwind_locals(cctx, scope->se_local_count);
746 if (!cctx->ctx_had_return)
747 ifscope->is_had_return = FALSE;
748
749 if (scope->se_u.se_if.is_if_label >= 0)
750 {
751 // previous "if" or "elseif" jumps here
752 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
753 isn->isn_arg.jump.jump_where = instr->ga_len;
754 }
755 // Fill in the "end" label in jumps at the end of the blocks.
756 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
757
758#ifdef FEAT_PROFILE
759 // even when skipping we count the endif as executed, unless the block it's
760 // in is skipped
761 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
762 && scope->se_skip_save != SKIP_YES)
763 {
764 cctx->ctx_skip = SKIP_NOT;
765 generate_instr(cctx, ISN_PROF_START);
766 }
767#endif
768 cctx->ctx_skip = scope->se_skip_save;
769
770 // If all the blocks end in :return and there is an :else then the
771 // had_return flag is set.
772 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
773
774 drop_scope(cctx);
775 return arg;
776}
777
778/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +0100779 * Save the info needed for ENDLOOP. Used by :for and :while.
780 */
781 static void
782compile_fill_loop_info(loop_info_T *loop_info, int funcref_idx, cctx_T *cctx)
783{
784 loop_info->li_funcref_idx = funcref_idx;
785 loop_info->li_local_count = cctx->ctx_locals.ga_len;
786 loop_info->li_closure_count = cctx->ctx_closure_count;
787}
788
789/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000790 * Compile "for var in expr":
791 *
792 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100793 * STORE -1 in loop-idx Set index to -1
794 * EVAL expr Result of "expr" on top of stack
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000795 * top: FOR loop-idx, end Increment index, use list on bottom of stack
796 * - if beyond end, jump to "end"
797 * - otherwise get item from list and push it
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100798 * - store ec_funcrefs in var "loop-idx" + 1
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000799 * STORE var Store item in "var"
800 * ... body ...
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100801 * ENDLOOP funcref-idx off count Only if closure uses local var
802 * JUMP top Jump back to repeat
803 * end: DROP Drop the result of "expr"
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000804 *
805 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
806 * UNPACK 2 Split item in 2
807 * STORE var1 Store item in "var1"
808 * STORE var2 Store item in "var2"
809 */
810 char_u *
811compile_for(char_u *arg_start, cctx_T *cctx)
812{
813 char_u *arg;
814 char_u *arg_end;
815 char_u *name = NULL;
816 char_u *p;
817 char_u *wp;
818 int var_count = 0;
819 int var_list = FALSE;
820 int semicolon = FALSE;
821 size_t varlen;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000822 garray_T *instr = &cctx->ctx_instr;
823 scope_T *scope;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100824 forscope_T *forscope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000825 lvar_T *loop_lvar; // loop iteration variable
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100826 lvar_T *funcref_lvar;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000827 lvar_T *var_lvar; // variable for "var"
828 type_T *vartype;
829 type_T *item_type = &t_any;
830 int idx;
831 int prev_lnum = cctx->ctx_prev_lnum;
832
833 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
834 if (p == NULL)
835 return NULL;
836 if (var_count == 0)
837 var_count = 1;
838 else
839 var_list = TRUE; // can also be a list of one variable
840
841 // consume "in"
842 wp = p;
843 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
844 return NULL;
845 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
846 {
847 if (*p == ':' && wp != p)
848 semsg(_(e_no_white_space_allowed_before_colon_str), p);
849 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000850 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000851 return NULL;
852 }
853 wp = p + 2;
854 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
855 return NULL;
856
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000857 // Find the already generated ISN_DEBUG to get the line number for the
858 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000859 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
860 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
861 .isn_type == ISN_DEBUG)
862 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000863 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000864 .isn_arg.debug.dbg_break_lnum;
865 }
866
867 scope = new_scope(cctx, FOR_SCOPE);
868 if (scope == NULL)
869 return NULL;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100870 forscope = &scope->se_u.se_for;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000871
872 // Reserve a variable to store the loop iteration counter and initialize it
873 // to -1.
874 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
875 if (loop_lvar == NULL)
876 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000877 drop_scope(cctx);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100878 return NULL; // out of memory
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000879 }
880 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
881
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100882 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
883 // The variable index is always the loop var index plus one.
884 // It is not used when no closures are encountered, we don't know yet.
885 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
886 if (funcref_lvar == NULL)
887 {
888 drop_scope(cctx);
889 return NULL; // out of memory
890 }
891
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000892 // compile "expr", it remains on the stack until "endfor"
893 arg = p;
894 if (compile_expr0(&arg, cctx) == FAIL)
895 {
896 drop_scope(cctx);
897 return NULL;
898 }
899 arg_end = arg;
900
901 if (cctx->ctx_skip != SKIP_YES)
902 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000903 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000904 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000905 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000906 if (vartype->tt_type != VAR_LIST
907 && vartype->tt_type != VAR_STRING
908 && vartype->tt_type != VAR_BLOB
909 && vartype->tt_type != VAR_ANY
910 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000911 {
912 semsg(_(e_for_loop_on_str_not_supported),
913 vartype_name(vartype->tt_type));
914 drop_scope(cctx);
915 return NULL;
916 }
917
918 if (vartype->tt_type == VAR_STRING)
919 item_type = &t_string;
920 else if (vartype->tt_type == VAR_BLOB)
921 item_type = &t_number;
922 else if (vartype->tt_type == VAR_LIST
923 && vartype->tt_member->tt_type != VAR_ANY)
924 {
925 if (!var_list)
926 item_type = vartype->tt_member;
927 else if (vartype->tt_member->tt_type == VAR_LIST
928 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
929 item_type = vartype->tt_member->tt_member;
930 }
931
932 // CMDMOD_REV must come before the FOR instruction.
933 generate_undo_cmdmods(cctx);
934
935 // "for_end" is set when ":endfor" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100936 forscope->fs_top_label = current_instr_idx(cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000937
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000938 if (cctx->ctx_compile_type == CT_DEBUG)
939 {
940 int save_prev_lnum = cctx->ctx_prev_lnum;
941 isn_T *isn;
942
943 // Add ISN_DEBUG here, before deciding to end the loop. There will
944 // be another ISN_DEBUG before the next instruction.
945 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
946 // Increment the variable count so that the loop variable can be
947 // inspected.
948 cctx->ctx_prev_lnum = prev_lnum;
949 isn = generate_instr_debug(cctx);
950 ++isn->isn_arg.debug.dbg_var_names_len;
951 cctx->ctx_prev_lnum = save_prev_lnum;
952 }
953
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000954 generate_FOR(cctx, loop_lvar->lv_idx);
955
956 arg = arg_start;
957 if (var_list)
958 {
959 generate_UNPACK(cctx, var_count, semicolon);
960 arg = skipwhite(arg + 1); // skip white after '['
961
Bram Moolenaar078a4612022-01-04 15:17:03 +0000962 // drop the list item
963 --cctx->ctx_type_stack.ga_len;
964
965 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000966 for (idx = 0; idx < var_count; ++idx)
967 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000968 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
969
970 if (push_type_stack(cctx, type) == FAIL)
971 {
972 drop_scope(cctx);
973 return NULL;
974 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000975 }
976 }
977
978 for (idx = 0; idx < var_count; ++idx)
979 {
980 assign_dest_T dest = dest_local;
981 int opt_flags = 0;
982 int vimvaridx = -1;
983 type_T *type = &t_any;
984 type_T *lhs_type = &t_any;
985 where_T where = WHERE_INIT;
986
987 p = skip_var_one(arg, FALSE);
988 varlen = p - arg;
989 name = vim_strnsave(arg, varlen);
990 if (name == NULL)
991 goto failed;
992 if (*p == ':')
993 {
994 p = skipwhite(p + 1);
995 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
996 }
997
998 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
999 &vimvaridx, &type, cctx) == FAIL)
1000 goto failed;
1001 if (dest != dest_local)
1002 {
1003 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
1004 0, 0, type, name) == FAIL)
1005 goto failed;
1006 }
1007 else if (varlen == 1 && *arg == '_')
1008 {
1009 // Assigning to "_": drop the value.
1010 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1011 goto failed;
1012 }
1013 else
1014 {
1015 // Script var is not supported.
1016 if (STRNCMP(name, "s:", 2) == 0)
1017 {
1018 emsg(_(e_cannot_use_script_variable_in_for_loop));
1019 goto failed;
1020 }
1021
1022 if (!valid_varname(arg, (int)varlen, FALSE))
1023 goto failed;
1024 if (lookup_local(arg, varlen, NULL, cctx) == OK)
1025 {
1026 semsg(_(e_variable_already_declared), arg);
1027 goto failed;
1028 }
1029
1030 // Reserve a variable to store "var".
1031 where.wt_index = var_list ? idx + 1 : 0;
1032 where.wt_variable = TRUE;
1033 if (lhs_type == &t_any)
1034 lhs_type = item_type;
1035 else if (item_type != &t_unknown
Bram Moolenaara1c51952022-02-02 16:20:26 +00001036 && need_type_where(item_type, lhs_type, -1,
1037 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001038 goto failed;
1039 var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
1040 if (var_lvar == NULL)
1041 // out of memory or used as an argument
1042 goto failed;
1043
1044 if (semicolon && idx == var_count - 1)
1045 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001046 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1047 }
1048
1049 if (*p == ',' || *p == ';')
1050 ++p;
1051 arg = skipwhite(p);
1052 vim_free(name);
1053 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001054
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001055 // remember the number of variables and closures, used for ENDLOOP
1056 compile_fill_loop_info(&forscope->fs_loop_info,
1057 funcref_lvar->lv_idx, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001058 }
1059
1060 return arg_end;
1061
1062failed:
1063 vim_free(name);
1064 drop_scope(cctx);
1065 return NULL;
1066}
1067
1068/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001069 * Used when ending a loop of :for and :while: Generate an ISN_ENDLOOP
1070 * instruction if any variable was declared that could be used by a new
1071 * closure.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001072 */
1073 static int
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001074compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001075{
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001076 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1077 && cctx->ctx_closure_count > loop_info->li_closure_count)
1078 return generate_ENDLOOP(cctx, loop_info->li_funcref_idx,
1079 loop_info->li_local_count);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001080 return OK;
1081}
1082
1083/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001084 * compile "endfor"
1085 */
1086 char_u *
1087compile_endfor(char_u *arg, cctx_T *cctx)
1088{
1089 garray_T *instr = &cctx->ctx_instr;
1090 scope_T *scope = cctx->ctx_scope;
1091 forscope_T *forscope;
1092 isn_T *isn;
1093
1094 if (misplaced_cmdmod(cctx))
1095 return NULL;
1096
1097 if (scope == NULL || scope->se_type != FOR_SCOPE)
1098 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001099 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001100 return NULL;
1101 }
1102 forscope = &scope->se_u.se_for;
1103 cctx->ctx_scope = scope->se_outer;
1104 if (cctx->ctx_skip != SKIP_YES)
1105 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001106 // Handle the case that any local variables were declared that might be
1107 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001108 if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001109 return NULL;
1110
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001111 unwind_locals(cctx, scope->se_local_count);
1112
1113 // At end of ":for" scope jump back to the FOR instruction.
1114 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1115
1116 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001117 // In debug mode an ISN_DEBUG was inserted.
1118 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1119 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001120 isn->isn_arg.forloop.for_end = instr->ga_len;
1121
1122 // Fill in the "end" label any BREAK statements
1123 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1124
1125 // Below the ":for" scope drop the "expr" list from the stack.
1126 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1127 return NULL;
1128 }
1129
1130 vim_free(scope);
1131
1132 return arg;
1133}
1134
1135/*
1136 * compile "while expr"
1137 *
1138 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001139 * top: EVAL expr Push result of "expr"
1140 * WHILE funcref-idx end Jump if false
1141 * ... body ...
1142 * ENDLOOP funcref-idx off count only if closure uses local var
1143 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001144 * end:
1145 *
1146 */
1147 char_u *
1148compile_while(char_u *arg, cctx_T *cctx)
1149{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001150 char_u *p = arg;
1151 scope_T *scope;
1152 whilescope_T *whilescope;
1153 lvar_T *funcref_lvar;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001154
1155 scope = new_scope(cctx, WHILE_SCOPE);
1156 if (scope == NULL)
1157 return NULL;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001158 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001159
1160 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001161 whilescope->ws_top_label = current_instr_idx(cctx);
1162
1163 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1164 // It is not used when no closures are encountered, we don't know yet.
1165 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
1166 if (funcref_lvar == NULL)
1167 {
1168 drop_scope(cctx);
1169 return NULL; // out of memory
1170 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001171
1172 // remember the number of variables and closures, used for ENDLOOP
1173 compile_fill_loop_info(&whilescope->ws_loop_info,
1174 funcref_lvar->lv_idx, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001175
1176 // compile "expr"
1177 if (compile_expr0(&p, cctx) == FAIL)
1178 return NULL;
1179
1180 if (!ends_excmd2(arg, skipwhite(p)))
1181 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001182 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001183 return NULL;
1184 }
1185
1186 if (cctx->ctx_skip != SKIP_YES)
1187 {
1188 if (bool_on_stack(cctx) == FAIL)
1189 return FAIL;
1190
1191 // CMDMOD_REV must come before the jump
1192 generate_undo_cmdmods(cctx);
1193
1194 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001195 if (compile_jump_to_end(&whilescope->ws_end_label,
1196 JUMP_WHILE_FALSE, funcref_lvar->lv_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001197 return FAIL;
1198 }
1199
1200 return p;
1201}
1202
1203/*
1204 * compile "endwhile"
1205 */
1206 char_u *
1207compile_endwhile(char_u *arg, cctx_T *cctx)
1208{
1209 scope_T *scope = cctx->ctx_scope;
1210 garray_T *instr = &cctx->ctx_instr;
1211
1212 if (misplaced_cmdmod(cctx))
1213 return NULL;
1214 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1215 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001216 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001217 return NULL;
1218 }
1219 cctx->ctx_scope = scope->se_outer;
1220 if (cctx->ctx_skip != SKIP_YES)
1221 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001222 whilescope_T *whilescope = &scope->se_u.se_while;
1223
1224 // Handle the case that any local variables were declared that might be
1225 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001226 if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001227 return NULL;
1228
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001229 unwind_locals(cctx, scope->se_local_count);
1230
1231#ifdef FEAT_PROFILE
1232 // count the endwhile before jumping
1233 may_generate_prof_end(cctx, cctx->ctx_lnum);
1234#endif
1235
1236 // At end of ":for" scope jump back to the FOR instruction.
1237 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1238
1239 // Fill in the "end" label in the WHILE statement so it can jump here.
1240 // And in any jumps for ":break"
1241 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1242 instr->ga_len, cctx);
1243 }
1244
1245 vim_free(scope);
1246
1247 return arg;
1248}
1249
1250/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001251 * Get the current information about variables declared inside a loop.
1252 * Returns zero if there are none, otherwise the count.
1253 * "loop_var_idx" is then set to the index of the first variable.
1254 */
1255 short
1256get_loop_var_info(cctx_T *cctx, short *loop_var_idx)
1257{
1258 scope_T *scope = cctx->ctx_scope;
1259 int start_local_count;
1260
1261 while (scope != NULL && scope->se_type != WHILE_SCOPE
1262 && scope->se_type != FOR_SCOPE)
1263 scope = scope->se_outer;
1264 if (scope == NULL)
1265 return 0;
1266
1267 if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001268 start_local_count = scope->se_u.se_while.ws_loop_info.li_local_count;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001269 else
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001270 start_local_count = scope->se_u.se_for.fs_loop_info.li_local_count;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001271 if (cctx->ctx_locals.ga_len > start_local_count)
1272 {
1273 *loop_var_idx = (short)start_local_count;
1274 return (short)(cctx->ctx_locals.ga_len - start_local_count);
1275 }
1276 return 0;
1277}
1278
1279/*
1280 * Get the index of the first variable in a loop, if any.
1281 * Returns -1 if none.
1282 */
1283 int
1284get_loop_var_idx(cctx_T *cctx)
1285{
1286 short loop_var_idx;
1287
1288 if (get_loop_var_info(cctx, &loop_var_idx) > 0)
1289 return loop_var_idx;
1290 return -1;
1291}
1292
1293/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001294 * Common for :break, :continue and :return
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001295 */
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001296 static int
1297compile_find_scope(
1298 int *loop_label, // where to jump to or NULL
1299 endlabel_T ***el, // end label or NULL
1300 int *try_scopes, // :try scopes encountered or NULL
1301 char *error, // error to use when no scope found
1302 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001303{
1304 scope_T *scope = cctx->ctx_scope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001305
1306 for (;;)
1307 {
1308 if (scope == NULL)
1309 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001310 if (error != NULL)
1311 emsg(_(error));
1312 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001313 }
1314 if (scope->se_type == FOR_SCOPE)
1315 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001316 if (compile_loop_end(&scope->se_u.se_for.fs_loop_info, cctx)
1317 == FAIL)
1318 return FAIL;
1319 if (loop_label != NULL)
1320 *loop_label = scope->se_u.se_for.fs_top_label;
1321 if (el != NULL)
1322 *el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001323 break;
1324 }
1325 if (scope->se_type == WHILE_SCOPE)
1326 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001327 if (compile_loop_end(&scope->se_u.se_while.ws_loop_info, cctx)
1328 == FAIL)
1329 return FAIL;
1330 if (loop_label != NULL)
1331 *loop_label = scope->se_u.se_while.ws_top_label;
1332 if (el != NULL)
1333 *el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001334 break;
1335 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001336 if (try_scopes != NULL && scope->se_type == TRY_SCOPE)
1337 ++*try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001338 scope = scope->se_outer;
1339 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001340 return OK;
1341}
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001342
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001343/*
1344 * compile "continue"
1345 */
1346 char_u *
1347compile_continue(char_u *arg, cctx_T *cctx)
1348{
1349 int try_scopes = 0;
1350 int loop_label;
1351
1352 if (compile_find_scope(&loop_label, NULL, &try_scopes,
1353 e_continue_without_while_or_for, cctx) == FAIL)
1354 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001355 if (try_scopes > 0)
1356 // Inside one or more try/catch blocks we first need to jump to the
1357 // "finally" or "endtry" to cleanup.
1358 generate_TRYCONT(cctx, try_scopes, loop_label);
1359 else
1360 // Jump back to the FOR or WHILE instruction.
1361 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1362
1363 return arg;
1364}
1365
1366/*
1367 * compile "break"
1368 */
1369 char_u *
1370compile_break(char_u *arg, cctx_T *cctx)
1371{
Bram Moolenaar873f8242022-03-10 21:53:44 +00001372 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001373 endlabel_T **el;
1374
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001375 if (compile_find_scope(NULL, &el, &try_scopes,
1376 e_break_without_while_or_for, cctx) == FAIL)
1377 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001378
Bram Moolenaar873f8242022-03-10 21:53:44 +00001379 if (try_scopes > 0)
1380 // Inside one or more try/catch blocks we first need to jump to the
1381 // "finally" or "endtry" to cleanup. Then come to the next JUMP
1382 // intruction, which we don't know the index of yet.
1383 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1384
1385 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1386 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001387 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001388 return FAIL;
1389
1390 return arg;
1391}
1392
1393/*
1394 * compile "{" start of block
1395 */
1396 char_u *
1397compile_block(char_u *arg, cctx_T *cctx)
1398{
1399 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1400 return NULL;
1401 return skipwhite(arg + 1);
1402}
1403
1404/*
1405 * compile end of block: drop one scope
1406 */
1407 void
1408compile_endblock(cctx_T *cctx)
1409{
1410 scope_T *scope = cctx->ctx_scope;
1411
1412 cctx->ctx_scope = scope->se_outer;
1413 unwind_locals(cctx, scope->se_local_count);
1414 vim_free(scope);
1415}
1416
1417/*
1418 * Compile "try".
1419 * Creates a new scope for the try-endtry, pointing to the first catch and
1420 * finally.
1421 * Creates another scope for the "try" block itself.
1422 * TRY instruction sets up exception handling at runtime.
1423 *
1424 * "try"
1425 * TRY -> catch1, -> finally push trystack entry
1426 * ... try block
1427 * "throw {exception}"
1428 * EVAL {exception}
1429 * THROW create exception
1430 * ... try block
1431 * " catch {expr}"
1432 * JUMP -> finally
1433 * catch1: PUSH exception
1434 * EVAL {expr}
1435 * MATCH
1436 * JUMP nomatch -> catch2
1437 * CATCH remove exception
1438 * ... catch block
1439 * " catch"
1440 * JUMP -> finally
1441 * catch2: CATCH remove exception
1442 * ... catch block
1443 * " finally"
1444 * finally:
1445 * ... finally block
1446 * " endtry"
1447 * ENDTRY pop trystack entry, may rethrow
1448 */
1449 char_u *
1450compile_try(char_u *arg, cctx_T *cctx)
1451{
1452 garray_T *instr = &cctx->ctx_instr;
1453 scope_T *try_scope;
1454 scope_T *scope;
1455
1456 if (misplaced_cmdmod(cctx))
1457 return NULL;
1458
1459 // scope that holds the jumps that go to catch/finally/endtry
1460 try_scope = new_scope(cctx, TRY_SCOPE);
1461 if (try_scope == NULL)
1462 return NULL;
1463
1464 if (cctx->ctx_skip != SKIP_YES)
1465 {
1466 isn_T *isn;
1467
1468 // "try_catch" is set when the first ":catch" is found or when no catch
1469 // is found and ":finally" is found.
1470 // "try_finally" is set when ":finally" is found
1471 // "try_endtry" is set when ":endtry" is found
1472 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1473 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1474 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001475 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1476 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001477 return NULL;
1478 }
1479
1480 // scope for the try block itself
1481 scope = new_scope(cctx, BLOCK_SCOPE);
1482 if (scope == NULL)
1483 return NULL;
1484
1485 return arg;
1486}
1487
1488/*
1489 * Compile "catch {expr}".
1490 */
1491 char_u *
1492compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1493{
1494 scope_T *scope = cctx->ctx_scope;
1495 garray_T *instr = &cctx->ctx_instr;
1496 char_u *p;
1497 isn_T *isn;
1498
1499 if (misplaced_cmdmod(cctx))
1500 return NULL;
1501
1502 // end block scope from :try or :catch
1503 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1504 compile_endblock(cctx);
1505 scope = cctx->ctx_scope;
1506
1507 // Error if not in a :try scope
1508 if (scope == NULL || scope->se_type != TRY_SCOPE)
1509 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001510 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001511 return NULL;
1512 }
1513
1514 if (scope->se_u.se_try.ts_caught_all)
1515 {
1516 emsg(_(e_catch_unreachable_after_catch_all));
1517 return NULL;
1518 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001519 if (!cctx->ctx_had_return)
1520 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001521
1522 if (cctx->ctx_skip != SKIP_YES)
1523 {
1524#ifdef FEAT_PROFILE
1525 // the profile-start should be after the jump
1526 if (cctx->ctx_compile_type == CT_PROFILE
1527 && instr->ga_len > 0
1528 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1529 .isn_type == ISN_PROF_START)
1530 --instr->ga_len;
1531#endif
1532 // Jump from end of previous block to :finally or :endtry
1533 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001534 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001535 return NULL;
1536
1537 // End :try or :catch scope: set value in ISN_TRY instruction
1538 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001539 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1540 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001541 if (scope->se_u.se_try.ts_catch_label != 0)
1542 {
1543 // Previous catch without match jumps here
1544 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1545 isn->isn_arg.jump.jump_where = instr->ga_len;
1546 }
1547#ifdef FEAT_PROFILE
1548 if (cctx->ctx_compile_type == CT_PROFILE)
1549 {
1550 // a "throw" that jumps here needs to be counted
1551 generate_instr(cctx, ISN_PROF_END);
1552 // the "catch" is also counted
1553 generate_instr(cctx, ISN_PROF_START);
1554 }
1555#endif
1556 if (cctx->ctx_compile_type == CT_DEBUG)
1557 generate_instr_debug(cctx);
1558 }
1559
1560 p = skipwhite(arg);
1561 if (ends_excmd2(arg, p))
1562 {
1563 scope->se_u.se_try.ts_caught_all = TRUE;
1564 scope->se_u.se_try.ts_catch_label = 0;
1565 }
1566 else
1567 {
1568 char_u *end;
1569 char_u *pat;
1570 char_u *tofree = NULL;
1571 int dropped = 0;
1572 int len;
1573
1574 // Push v:exception, push {expr} and MATCH
1575 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1576
1577 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1578 if (*end != *p)
1579 {
1580 semsg(_(e_separator_mismatch_str), p);
1581 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001582 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001583 }
1584 if (tofree == NULL)
1585 len = (int)(end - (p + 1));
1586 else
1587 len = (int)(end - tofree);
1588 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1589 vim_free(tofree);
1590 p += len + 2 + dropped;
1591 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001592 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001593 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001594 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001595
1596 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1597 return NULL;
1598
1599 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1600 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1601 return NULL;
1602 }
1603
1604 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1605 return NULL;
1606
1607 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1608 return NULL;
1609 return p;
1610}
1611
1612 char_u *
1613compile_finally(char_u *arg, cctx_T *cctx)
1614{
1615 scope_T *scope = cctx->ctx_scope;
1616 garray_T *instr = &cctx->ctx_instr;
1617 isn_T *isn;
1618 int this_instr;
1619
1620 if (misplaced_cmdmod(cctx))
1621 return NULL;
1622
1623 // end block scope from :try or :catch
1624 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1625 compile_endblock(cctx);
1626 scope = cctx->ctx_scope;
1627
1628 // Error if not in a :try scope
1629 if (scope == NULL || scope->se_type != TRY_SCOPE)
1630 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001631 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001632 return NULL;
1633 }
1634
1635 if (cctx->ctx_skip != SKIP_YES)
1636 {
1637 // End :catch or :finally scope: set value in ISN_TRY instruction
1638 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001639 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001640 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001641 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001642 return NULL;
1643 }
1644
1645 this_instr = instr->ga_len;
1646#ifdef FEAT_PROFILE
1647 if (cctx->ctx_compile_type == CT_PROFILE
1648 && ((isn_T *)instr->ga_data)[this_instr - 1]
1649 .isn_type == ISN_PROF_START)
1650 {
1651 // jump to the profile start of the "finally"
1652 --this_instr;
1653
1654 // jump to the profile end above it
1655 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1656 .isn_type == ISN_PROF_END)
1657 --this_instr;
1658 }
1659#endif
1660
1661 // Fill in the "end" label in jumps at the end of the blocks.
1662 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1663 this_instr, cctx);
1664
1665 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001666 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1667 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1668 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001669 if (scope->se_u.se_try.ts_catch_label != 0)
1670 {
1671 // Previous catch without match jumps here
1672 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1673 isn->isn_arg.jump.jump_where = this_instr;
1674 scope->se_u.se_try.ts_catch_label = 0;
1675 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001676 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001677 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1678 return NULL;
1679 }
1680
1681 return arg;
1682}
1683
1684 char_u *
1685compile_endtry(char_u *arg, cctx_T *cctx)
1686{
1687 scope_T *scope = cctx->ctx_scope;
1688 garray_T *instr = &cctx->ctx_instr;
1689 isn_T *try_isn;
1690
1691 if (misplaced_cmdmod(cctx))
1692 return NULL;
1693
1694 // end block scope from :catch or :finally
1695 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1696 compile_endblock(cctx);
1697 scope = cctx->ctx_scope;
1698
1699 // Error if not in a :try scope
1700 if (scope == NULL || scope->se_type != TRY_SCOPE)
1701 {
1702 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001703 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001704 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001705 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001706 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001707 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001708 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001709 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001710 return NULL;
1711 }
1712
1713 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1714 if (cctx->ctx_skip != SKIP_YES)
1715 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001716 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1717 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001718 {
1719 emsg(_(e_missing_catch_or_finally));
1720 return NULL;
1721 }
1722
1723#ifdef FEAT_PROFILE
1724 if (cctx->ctx_compile_type == CT_PROFILE
1725 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1726 .isn_type == ISN_PROF_START)
1727 // move the profile start after "endtry" so that it's not counted when
1728 // the exception is rethrown.
1729 --instr->ga_len;
1730#endif
1731
1732 // Fill in the "end" label in jumps at the end of the blocks, if not
1733 // done by ":finally".
1734 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1735 instr->ga_len, cctx);
1736
1737 if (scope->se_u.se_try.ts_catch_label != 0)
1738 {
1739 // Last catch without match jumps here
1740 isn_T *isn = ((isn_T *)instr->ga_data)
1741 + scope->se_u.se_try.ts_catch_label;
1742 isn->isn_arg.jump.jump_where = instr->ga_len;
1743 }
1744 }
1745
Bram Moolenaar53c29612022-01-12 16:18:18 +00001746 // If there is a finally clause that ends in return then we will return.
1747 // If one of the blocks didn't end in "return" or we did not catch all
1748 // exceptions reset the had_return flag.
1749 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1750 && (scope->se_u.se_try.ts_no_return
1751 || !scope->se_u.se_try.ts_caught_all))
1752 cctx->ctx_had_return = FALSE;
1753
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001754 compile_endblock(cctx);
1755
1756 if (cctx->ctx_skip != SKIP_YES)
1757 {
1758 // End :catch or :finally scope: set instruction index in ISN_TRY
1759 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001760 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001761 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001762 return NULL;
1763#ifdef FEAT_PROFILE
1764 if (cctx->ctx_compile_type == CT_PROFILE)
1765 generate_instr(cctx, ISN_PROF_START);
1766#endif
1767 }
1768 return arg;
1769}
1770
1771/*
1772 * compile "throw {expr}"
1773 */
1774 char_u *
1775compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1776{
1777 char_u *p = skipwhite(arg);
1778
1779 if (compile_expr0(&p, cctx) == FAIL)
1780 return NULL;
1781 if (cctx->ctx_skip == SKIP_YES)
1782 return p;
1783 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1784 return NULL;
1785 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1786 return NULL;
1787
1788 return p;
1789}
1790
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001791/*
1792 * Compile an expression or function call.
1793 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001794 char_u *
1795compile_eval(char_u *arg, cctx_T *cctx)
1796{
1797 char_u *p = arg;
1798 int name_only;
1799 long lnum = SOURCING_LNUM;
1800
1801 // find_ex_command() will consider a variable name an expression, assuming
1802 // that something follows on the next line. Check that something actually
1803 // follows, otherwise it's probably a misplaced command.
1804 name_only = cmd_is_name_only(arg);
1805
1806 if (compile_expr0(&p, cctx) == FAIL)
1807 return NULL;
1808
1809 if (name_only && lnum == SOURCING_LNUM)
1810 {
1811 semsg(_(e_expression_without_effect_str), arg);
1812 return NULL;
1813 }
1814
1815 // drop the result
1816 generate_instr_drop(cctx, ISN_DROP, 1);
1817
1818 return skipwhite(p);
1819}
1820
1821/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001822 * Get the local variable index for deferred function calls.
1823 * Reserve it when not done already.
1824 * Returns zero for failure.
1825 */
1826 int
1827get_defer_var_idx(cctx_T *cctx)
1828{
1829 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1830 + cctx->ctx_ufunc->uf_dfunc_idx;
1831 if (dfunc->df_defer_var_idx == 0)
1832 {
1833 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1834 TRUE, &t_list_any);
1835 if (lvar == NULL)
1836 return 0;
1837 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1838 }
1839 return dfunc->df_defer_var_idx;
1840}
1841
1842/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001843 * Compile "defer func(arg)".
1844 */
1845 char_u *
1846compile_defer(char_u *arg_start, cctx_T *cctx)
1847{
Bram Moolenaar16900322022-09-08 19:51:45 +01001848 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001849 char_u *arg = arg_start;
1850 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001851 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001852 type_T *type;
1853 int func_idx;
1854
1855 // Get a funcref for the function name.
1856 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01001857 paren = vim_strchr(arg, '(');
1858 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001859 {
1860 semsg(_(e_missing_parenthesis_str), arg);
1861 return NULL;
1862 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001863 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001864 func_idx = find_internal_func(arg);
1865 if (func_idx >= 0)
1866 // TODO: better type
1867 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1868 &t_func_any, FALSE);
1869 else if (compile_expr0(&arg, cctx) == FAIL)
1870 return NULL;
Bram Moolenaar16900322022-09-08 19:51:45 +01001871 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001872
1873 // check for function type
1874 type = get_type_on_stack(cctx, 0);
1875 if (type->tt_type != VAR_FUNC)
1876 {
1877 emsg(_(e_function_name_required));
1878 return NULL;
1879 }
1880
1881 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01001882 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001883 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1884 return NULL;
1885
Bram Moolenaar16900322022-09-08 19:51:45 +01001886 if (func_idx >= 0)
1887 {
1888 type2_T *argtypes = NULL;
1889 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1890
1891 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
1892 &argtypes, shuffled_argtypes) == FAIL)
1893 return NULL;
1894 }
1895 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
1896 arg_start) == FAIL)
1897 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001898
Bram Moolenaar806a2732022-09-04 15:40:36 +01001899 defer_var_idx = get_defer_var_idx(cctx);
1900 if (defer_var_idx == 0)
1901 return NULL;
1902 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001903 return NULL;
1904
1905 return skipwhite(arg);
1906}
1907
1908/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001909 * compile "echo expr"
1910 * compile "echomsg expr"
1911 * compile "echoerr expr"
1912 * compile "echoconsole expr"
1913 * compile "execute expr"
1914 */
1915 char_u *
1916compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
1917{
1918 char_u *p = arg;
1919 char_u *prev = arg;
1920 char_u *expr_start;
1921 int count = 0;
1922 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001923 type_T *type;
1924
1925 for (;;)
1926 {
1927 if (ends_excmd2(prev, p))
1928 break;
1929 expr_start = p;
1930 if (compile_expr0(&p, cctx) == FAIL)
1931 return NULL;
1932
1933 if (cctx->ctx_skip != SKIP_YES)
1934 {
1935 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001936 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001937 if (type->tt_type == VAR_VOID)
1938 {
1939 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
1940 return NULL;
1941 }
1942 }
1943
1944 ++count;
1945 prev = p;
1946 p = skipwhite(p);
1947 }
1948
1949 if (count > 0)
1950 {
1951 long save_lnum = cctx->ctx_lnum;
1952
1953 // Use the line number where the command started.
1954 cctx->ctx_lnum = start_ctx_lnum;
1955
1956 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
1957 generate_ECHO(cctx, cmdidx == CMD_echo, count);
1958 else if (cmdidx == CMD_execute)
1959 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
1960 else if (cmdidx == CMD_echomsg)
1961 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01001962#ifdef HAS_MESSAGE_WINDOW
1963 else if (cmdidx == CMD_echowindow)
1964 generate_MULT_EXPR(cctx, ISN_ECHOWINDOW, count);
1965#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001966 else if (cmdidx == CMD_echoconsole)
1967 generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
1968 else
1969 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
1970
1971 cctx->ctx_lnum = save_lnum;
1972 }
1973 return p;
1974}
1975
1976/*
1977 * If "eap" has a range that is not a constant generate an ISN_RANGE
1978 * instruction to compute it and return OK.
1979 * Otherwise return FAIL, the caller must deal with any range.
1980 */
1981 static int
1982compile_variable_range(exarg_T *eap, cctx_T *cctx)
1983{
1984 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
1985 char_u *p = skipdigits(eap->cmd);
1986
1987 if (p == range_end)
1988 return FAIL;
1989 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
1990}
1991
1992/*
1993 * :put r
1994 * :put ={expr}
1995 */
1996 char_u *
1997compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
1998{
1999 char_u *line = arg;
2000 linenr_T lnum;
2001 char *errormsg;
2002 int above = eap->forceit;
2003
2004 eap->regname = *line;
2005
2006 if (eap->regname == '=')
2007 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002008 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002009
2010 if (compile_expr0(&p, cctx) == FAIL)
2011 return NULL;
2012 line = p;
2013 }
2014 else if (eap->regname != NUL)
2015 ++line;
2016
2017 if (compile_variable_range(eap, cctx) == OK)
2018 {
2019 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2020 }
2021 else
2022 {
2023 // Either no range or a number.
2024 // "errormsg" will not be set because the range is ADDR_LINES.
2025 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2026 // cannot happen
2027 return NULL;
2028 if (eap->addr_count == 0)
2029 lnum = -1;
2030 else
2031 lnum = eap->line2;
2032 if (above)
2033 --lnum;
2034 }
2035
2036 generate_PUT(cctx, eap->regname, lnum);
2037 return line;
2038}
2039
2040/*
2041 * A command that is not compiled, execute with legacy code.
2042 */
2043 char_u *
2044compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2045{
2046 char_u *line = line_arg;
2047 char_u *p;
2048 int has_expr = FALSE;
2049 char_u *nextcmd = (char_u *)"";
2050 char_u *tofree = NULL;
2051 char_u *cmd_arg = NULL;
2052
2053 if (cctx->ctx_skip == SKIP_YES)
2054 goto theend;
2055
2056 // If there was a prececing command modifier, drop it and include it in the
2057 // EXEC command.
2058 if (cctx->ctx_has_cmdmod)
2059 {
2060 garray_T *instr = &cctx->ctx_instr;
2061 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2062
2063 if (isn->isn_type == ISN_CMDMOD)
2064 {
2065 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2066 ->cmod_filter_regmatch.regprog);
2067 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2068 --instr->ga_len;
2069 cctx->ctx_has_cmdmod = FALSE;
2070 }
2071 }
2072
2073 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2074 {
2075 long argt = eap->argt;
2076 int usefilter = FALSE;
2077
2078 has_expr = argt & (EX_XFILE | EX_EXPAND);
2079
2080 // If the command can be followed by a bar, find the bar and truncate
2081 // it, so that the following command can be compiled.
2082 // The '|' is overwritten with a NUL, it is put back below.
2083 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2084 && *eap->arg == '!')
2085 // :w !filter or :r !filter or :r! filter
2086 usefilter = TRUE;
2087 if ((argt & EX_TRLBAR) && !usefilter)
2088 {
2089 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002090 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002091 if (eap->nextcmd != NULL)
2092 nextcmd = eap->nextcmd;
2093 }
2094 else if (eap->cmdidx == CMD_wincmd)
2095 {
2096 p = eap->arg;
2097 if (*p != NUL)
2098 ++p;
2099 if (*p == 'g' || *p == Ctrl_G)
2100 ++p;
2101 p = skipwhite(p);
2102 if (*p == '|')
2103 {
2104 *p = NUL;
2105 nextcmd = p + 1;
2106 }
2107 }
2108 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2109 {
2110 // If there is a trailing '{' read lines until the '}'
2111 p = eap->arg + STRLEN(eap->arg) - 1;
2112 while (p > eap->arg && VIM_ISWHITE(*p))
2113 --p;
2114 if (*p == '{')
2115 {
2116 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002117 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002118 int start_lnum = SOURCING_LNUM;
2119
2120 CLEAR_FIELD(ea);
2121 ea.arg = eap->arg;
2122 fill_exarg_from_cctx(&ea, cctx);
2123 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2124 if (tofree != NULL)
2125 {
2126 *p = NUL;
2127 line = concat_str(line, tofree);
2128 if (line == NULL)
2129 goto theend;
2130 vim_free(tofree);
2131 tofree = line;
2132 SOURCING_LNUM = start_lnum;
2133 }
2134 }
2135 }
2136 }
2137
2138 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2139 {
2140 // expand filename in "syntax include [@group] filename"
2141 has_expr = TRUE;
2142 eap->arg = skipwhite(eap->arg + 7);
2143 if (*eap->arg == '@')
2144 eap->arg = skiptowhite(eap->arg);
2145 }
2146
2147 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2148 && STRLEN(eap->arg) > 4)
2149 {
2150 int delim = *eap->arg;
2151
2152 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2153 if (*p == delim)
2154 cmd_arg = p + 1;
2155 }
2156
2157 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2158 cmd_arg = eap->arg;
2159
2160 if (cmd_arg != NULL)
2161 {
2162 exarg_T nea;
2163
2164 CLEAR_FIELD(nea);
2165 nea.cmd = cmd_arg;
2166 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2167 if (nea.cmdidx < CMD_SIZE)
2168 {
2169 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2170 if (has_expr)
2171 eap->arg = skiptowhite(eap->arg);
2172 }
2173 }
2174
2175 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2176 {
2177 int count = 0;
2178 char_u *start = skipwhite(line);
2179
2180 // :cmd xxx`=expr1`yyy`=expr2`zzz
2181 // PUSHS ":cmd xxx"
2182 // eval expr1
2183 // PUSHS "yyy"
2184 // eval expr2
2185 // PUSHS "zzz"
2186 // EXECCONCAT 5
2187 for (;;)
2188 {
2189 if (p > start)
2190 {
2191 char_u *val = vim_strnsave(start, p - start);
2192
2193 generate_PUSHS(cctx, &val);
2194 ++count;
2195 }
2196 p += 2;
2197 if (compile_expr0(&p, cctx) == FAIL)
2198 return NULL;
2199 may_generate_2STRING(-1, TRUE, cctx);
2200 ++count;
2201 p = skipwhite(p);
2202 if (*p != '`')
2203 {
2204 emsg(_(e_missing_backtick));
2205 return NULL;
2206 }
2207 start = p + 1;
2208
2209 p = (char_u *)strstr((char *)start, "`=");
2210 if (p == NULL)
2211 {
2212 if (*skipwhite(start) != NUL)
2213 {
2214 char_u *val = vim_strsave(start);
2215
2216 generate_PUSHS(cctx, &val);
2217 ++count;
2218 }
2219 break;
2220 }
2221 }
2222 generate_EXECCONCAT(cctx, count);
2223 }
2224 else
2225 generate_EXEC_copy(cctx, ISN_EXEC, line);
2226
2227theend:
2228 if (*nextcmd != NUL)
2229 {
2230 // the parser expects a pointer to the bar, put it back
2231 --nextcmd;
2232 *nextcmd = '|';
2233 }
2234 vim_free(tofree);
2235
2236 return nextcmd;
2237}
2238
2239/*
2240 * A script command with heredoc, e.g.
2241 * ruby << EOF
2242 * command
2243 * EOF
2244 * Has been turned into one long line with NL characters by
2245 * get_function_body():
2246 * ruby << EOF<NL> command<NL>EOF
2247 */
2248 char_u *
2249compile_script(char_u *line, cctx_T *cctx)
2250{
2251 if (cctx->ctx_skip != SKIP_YES)
2252 {
2253 isn_T *isn;
2254
2255 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2256 return NULL;
2257 isn->isn_arg.string = vim_strsave(line);
2258 }
2259 return (char_u *)"";
2260}
2261
2262
2263/*
2264 * :s/pat/repl/
2265 */
2266 char_u *
2267compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2268{
2269 char_u *cmd = eap->arg;
2270 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2271
2272 if (expr != NULL)
2273 {
2274 int delimiter = *cmd++;
2275
2276 // There is a \=expr, find it in the substitute part.
2277 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2278 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2279 {
2280 garray_T save_ga = cctx->ctx_instr;
2281 char_u *end;
2282 int expr_res;
2283 int trailing_error;
2284 int instr_count;
2285 isn_T *instr;
2286 isn_T *isn;
2287
2288 cmd += 3;
2289 end = skip_substitute(cmd, delimiter);
2290
2291 // Temporarily reset the list of instructions so that the jump
2292 // labels are correct.
2293 cctx->ctx_instr.ga_len = 0;
2294 cctx->ctx_instr.ga_maxlen = 0;
2295 cctx->ctx_instr.ga_data = NULL;
2296 expr_res = compile_expr0(&cmd, cctx);
2297 if (end[-1] == NUL)
2298 end[-1] = delimiter;
2299 cmd = skipwhite(cmd);
2300 trailing_error = *cmd != delimiter && *cmd != NUL;
2301
2302 if (expr_res == FAIL || trailing_error
2303 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2304 {
2305 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002306 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002307 clear_instr_ga(&cctx->ctx_instr);
2308 cctx->ctx_instr = save_ga;
2309 return NULL;
2310 }
2311
2312 // Move the generated instructions into the ISN_SUBSTITUTE
2313 // instructions, then restore the list of instructions before
2314 // adding the ISN_SUBSTITUTE instruction.
2315 instr_count = cctx->ctx_instr.ga_len;
2316 instr = cctx->ctx_instr.ga_data;
2317 instr[instr_count].isn_type = ISN_FINISH;
2318
2319 cctx->ctx_instr = save_ga;
2320 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2321 {
2322 int idx;
2323
2324 for (idx = 0; idx < instr_count; ++idx)
2325 delete_instr(instr + idx);
2326 vim_free(instr);
2327 return NULL;
2328 }
2329 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2330 isn->isn_arg.subs.subs_instr = instr;
2331
2332 // skip over flags
2333 if (*end == '&')
2334 ++end;
2335 while (ASCII_ISALPHA(*end) || *end == '#')
2336 ++end;
2337 return end;
2338 }
2339 }
2340
2341 return compile_exec(arg, eap, cctx);
2342}
2343
2344 char_u *
2345compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2346{
2347 char_u *arg = eap->arg;
2348 lhs_T *lhs = &cctx->ctx_redir_lhs;
2349
2350 if (lhs->lhs_name != NULL)
2351 {
2352 if (STRNCMP(arg, "END", 3) == 0)
2353 {
2354 if (lhs->lhs_append)
2355 {
2356 // First load the current variable value.
2357 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
2358 cctx) == FAIL)
2359 return NULL;
2360 }
2361
2362 // Gets the redirected text and put it on the stack, then store it
2363 // in the variable.
2364 generate_instr_type(cctx, ISN_REDIREND, &t_string);
2365
2366 if (lhs->lhs_append)
LemonBoy372bcce2022-04-25 12:43:20 +01002367 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002368
2369 if (lhs->lhs_has_index)
2370 {
2371 // Use the info in "lhs" to store the value at the index in the
2372 // list or dict.
2373 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
2374 &t_string, cctx) == FAIL)
2375 return NULL;
2376 }
Bram Moolenaar5cd64792021-12-25 18:23:24 +00002377 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002378 return NULL;
2379
2380 VIM_CLEAR(lhs->lhs_name);
2381 VIM_CLEAR(lhs->lhs_whole);
2382 return arg + 3;
2383 }
2384 emsg(_(e_cannot_nest_redir));
2385 return NULL;
2386 }
2387
2388 if (arg[0] == '=' && arg[1] == '>')
2389 {
2390 int append = FALSE;
2391
2392 // redirect to a variable is compiled
2393 arg += 2;
2394 if (*arg == '>')
2395 {
2396 ++arg;
2397 append = TRUE;
2398 }
2399 arg = skipwhite(arg);
2400
2401 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002402 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002403 return NULL;
2404 if (need_type(&t_string, lhs->lhs_member_type,
2405 -1, 0, cctx, FALSE, FALSE) == FAIL)
2406 return NULL;
2407 generate_instr(cctx, ISN_REDIRSTART);
2408 lhs->lhs_append = append;
2409 if (lhs->lhs_has_index)
2410 {
2411 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2412 if (lhs->lhs_whole == NULL)
2413 return NULL;
2414 }
2415
2416 return arg + lhs->lhs_varlen_total;
2417 }
2418
2419 // other redirects are handled like at script level
2420 return compile_exec(line, eap, cctx);
2421}
2422
2423#if defined(FEAT_QUICKFIX) || defined(PROTO)
2424 char_u *
2425compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2426{
2427 isn_T *isn;
2428 char_u *p;
2429
2430 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2431 if (isn == NULL)
2432 return NULL;
2433 isn->isn_arg.number = eap->cmdidx;
2434
2435 p = eap->arg;
2436 if (compile_expr0(&p, cctx) == FAIL)
2437 return NULL;
2438
2439 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2440 if (isn == NULL)
2441 return NULL;
2442 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2443 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2444 return NULL;
2445 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2446 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2447 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2448
2449 return p;
2450}
2451#endif
2452
2453/*
2454 * Compile "return [expr]".
2455 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2456 */
2457 char_u *
2458compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2459{
2460 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002461 type_T *stack_type;
2462
2463 if (*p != NUL && *p != '|' && *p != '\n')
2464 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002465 // For a lambda, "return expr" is always used, also when "expr" results
2466 // in a void.
2467 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2468 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002469 {
2470 emsg(_(e_returning_value_in_function_without_return_type));
2471 return NULL;
2472 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002473 if (legacy)
2474 {
2475 int save_flags = cmdmod.cmod_flags;
2476
2477 generate_LEGACY_EVAL(cctx, p);
2478 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
2479 0, cctx, FALSE, FALSE) == FAIL)
2480 return NULL;
2481 cmdmod.cmod_flags |= CMOD_LEGACY;
2482 (void)skip_expr(&p, NULL);
2483 cmdmod.cmod_flags = save_flags;
2484 }
2485 else
2486 {
2487 // compile return argument into instructions
2488 if (compile_expr0(&p, cctx) == FAIL)
2489 return NULL;
2490 }
2491
2492 if (cctx->ctx_skip != SKIP_YES)
2493 {
2494 // "check_return_type" with uf_ret_type set to &t_unknown is used
2495 // for an inline function without a specified return type. Set the
2496 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002497 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002498 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002499 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002500 || (!check_return_type
2501 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2502 {
2503 cctx->ctx_ufunc->uf_ret_type = stack_type;
2504 }
2505 else
2506 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002507 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
2508 0, cctx, FALSE, FALSE) == FAIL)
2509 return NULL;
2510 }
2511 }
2512 }
2513 else
2514 {
2515 // "check_return_type" cannot be TRUE, only used for a lambda which
2516 // always has an argument.
2517 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2518 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2519 {
2520 emsg(_(e_missing_return_value));
2521 return NULL;
2522 }
2523
2524 // No argument, return zero.
2525 generate_PUSHNR(cctx, 0);
2526 }
2527
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002528 // may need ENDLOOP when inside a :for or :while loop
2529 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2530
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002531 // Undo any command modifiers.
2532 generate_undo_cmdmods(cctx);
2533
2534 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2535 return NULL;
2536
2537 // "return val | endif" is possible
2538 return skipwhite(p);
2539}
2540
2541/*
2542 * Check if the separator for a :global or :substitute command is OK.
2543 */
2544 int
2545check_global_and_subst(char_u *cmd, char_u *arg)
2546{
2547 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2548 {
2549 semsg(_(e_separator_not_supported_str), arg);
2550 return FAIL;
2551 }
2552 if (VIM_ISWHITE(cmd[1]))
2553 {
2554 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2555 return FAIL;
2556 }
2557 return OK;
2558}
2559
2560
2561#endif // defined(FEAT_EVAL)