blob: 90758f24f6ed39c0c97676aaecf4a58a1b3b04c0 [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/*
779 * Compile "for var in expr":
780 *
781 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100782 * STORE -1 in loop-idx Set index to -1
783 * EVAL expr Result of "expr" on top of stack
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000784 * top: FOR loop-idx, end Increment index, use list on bottom of stack
785 * - if beyond end, jump to "end"
786 * - otherwise get item from list and push it
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100787 * - store ec_funcrefs in var "loop-idx" + 1
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000788 * STORE var Store item in "var"
789 * ... body ...
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100790 * ENDLOOP funcref-idx off count Only if closure uses local var
791 * JUMP top Jump back to repeat
792 * end: DROP Drop the result of "expr"
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000793 *
794 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
795 * UNPACK 2 Split item in 2
796 * STORE var1 Store item in "var1"
797 * STORE var2 Store item in "var2"
798 */
799 char_u *
800compile_for(char_u *arg_start, cctx_T *cctx)
801{
802 char_u *arg;
803 char_u *arg_end;
804 char_u *name = NULL;
805 char_u *p;
806 char_u *wp;
807 int var_count = 0;
808 int var_list = FALSE;
809 int semicolon = FALSE;
810 size_t varlen;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000811 garray_T *instr = &cctx->ctx_instr;
812 scope_T *scope;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100813 forscope_T *forscope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000814 lvar_T *loop_lvar; // loop iteration variable
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100815 lvar_T *funcref_lvar;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000816 lvar_T *var_lvar; // variable for "var"
817 type_T *vartype;
818 type_T *item_type = &t_any;
819 int idx;
820 int prev_lnum = cctx->ctx_prev_lnum;
821
822 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
823 if (p == NULL)
824 return NULL;
825 if (var_count == 0)
826 var_count = 1;
827 else
828 var_list = TRUE; // can also be a list of one variable
829
830 // consume "in"
831 wp = p;
832 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
833 return NULL;
834 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
835 {
836 if (*p == ':' && wp != p)
837 semsg(_(e_no_white_space_allowed_before_colon_str), p);
838 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000839 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000840 return NULL;
841 }
842 wp = p + 2;
843 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
844 return NULL;
845
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000846 // Find the already generated ISN_DEBUG to get the line number for the
847 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000848 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
849 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
850 .isn_type == ISN_DEBUG)
851 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000852 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000853 .isn_arg.debug.dbg_break_lnum;
854 }
855
856 scope = new_scope(cctx, FOR_SCOPE);
857 if (scope == NULL)
858 return NULL;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100859 forscope = &scope->se_u.se_for;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000860
861 // Reserve a variable to store the loop iteration counter and initialize it
862 // to -1.
863 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
864 if (loop_lvar == NULL)
865 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000866 drop_scope(cctx);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100867 return NULL; // out of memory
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000868 }
869 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
870
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100871 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
872 // The variable index is always the loop var index plus one.
873 // It is not used when no closures are encountered, we don't know yet.
874 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
875 if (funcref_lvar == NULL)
876 {
877 drop_scope(cctx);
878 return NULL; // out of memory
879 }
880
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000881 // compile "expr", it remains on the stack until "endfor"
882 arg = p;
883 if (compile_expr0(&arg, cctx) == FAIL)
884 {
885 drop_scope(cctx);
886 return NULL;
887 }
888 arg_end = arg;
889
890 if (cctx->ctx_skip != SKIP_YES)
891 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000892 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000893 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000894 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000895 if (vartype->tt_type != VAR_LIST
896 && vartype->tt_type != VAR_STRING
897 && vartype->tt_type != VAR_BLOB
898 && vartype->tt_type != VAR_ANY
899 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000900 {
901 semsg(_(e_for_loop_on_str_not_supported),
902 vartype_name(vartype->tt_type));
903 drop_scope(cctx);
904 return NULL;
905 }
906
907 if (vartype->tt_type == VAR_STRING)
908 item_type = &t_string;
909 else if (vartype->tt_type == VAR_BLOB)
910 item_type = &t_number;
911 else if (vartype->tt_type == VAR_LIST
912 && vartype->tt_member->tt_type != VAR_ANY)
913 {
914 if (!var_list)
915 item_type = vartype->tt_member;
916 else if (vartype->tt_member->tt_type == VAR_LIST
917 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
918 item_type = vartype->tt_member->tt_member;
919 }
920
921 // CMDMOD_REV must come before the FOR instruction.
922 generate_undo_cmdmods(cctx);
923
924 // "for_end" is set when ":endfor" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100925 forscope->fs_top_label = current_instr_idx(cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000926
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000927 if (cctx->ctx_compile_type == CT_DEBUG)
928 {
929 int save_prev_lnum = cctx->ctx_prev_lnum;
930 isn_T *isn;
931
932 // Add ISN_DEBUG here, before deciding to end the loop. There will
933 // be another ISN_DEBUG before the next instruction.
934 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
935 // Increment the variable count so that the loop variable can be
936 // inspected.
937 cctx->ctx_prev_lnum = prev_lnum;
938 isn = generate_instr_debug(cctx);
939 ++isn->isn_arg.debug.dbg_var_names_len;
940 cctx->ctx_prev_lnum = save_prev_lnum;
941 }
942
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000943 generate_FOR(cctx, loop_lvar->lv_idx);
944
945 arg = arg_start;
946 if (var_list)
947 {
948 generate_UNPACK(cctx, var_count, semicolon);
949 arg = skipwhite(arg + 1); // skip white after '['
950
Bram Moolenaar078a4612022-01-04 15:17:03 +0000951 // drop the list item
952 --cctx->ctx_type_stack.ga_len;
953
954 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000955 for (idx = 0; idx < var_count; ++idx)
956 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000957 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
958
959 if (push_type_stack(cctx, type) == FAIL)
960 {
961 drop_scope(cctx);
962 return NULL;
963 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000964 }
965 }
966
967 for (idx = 0; idx < var_count; ++idx)
968 {
969 assign_dest_T dest = dest_local;
970 int opt_flags = 0;
971 int vimvaridx = -1;
972 type_T *type = &t_any;
973 type_T *lhs_type = &t_any;
974 where_T where = WHERE_INIT;
975
976 p = skip_var_one(arg, FALSE);
977 varlen = p - arg;
978 name = vim_strnsave(arg, varlen);
979 if (name == NULL)
980 goto failed;
981 if (*p == ':')
982 {
983 p = skipwhite(p + 1);
984 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
985 }
986
987 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
988 &vimvaridx, &type, cctx) == FAIL)
989 goto failed;
990 if (dest != dest_local)
991 {
992 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
993 0, 0, type, name) == FAIL)
994 goto failed;
995 }
996 else if (varlen == 1 && *arg == '_')
997 {
998 // Assigning to "_": drop the value.
999 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1000 goto failed;
1001 }
1002 else
1003 {
1004 // Script var is not supported.
1005 if (STRNCMP(name, "s:", 2) == 0)
1006 {
1007 emsg(_(e_cannot_use_script_variable_in_for_loop));
1008 goto failed;
1009 }
1010
1011 if (!valid_varname(arg, (int)varlen, FALSE))
1012 goto failed;
1013 if (lookup_local(arg, varlen, NULL, cctx) == OK)
1014 {
1015 semsg(_(e_variable_already_declared), arg);
1016 goto failed;
1017 }
1018
1019 // Reserve a variable to store "var".
1020 where.wt_index = var_list ? idx + 1 : 0;
1021 where.wt_variable = TRUE;
1022 if (lhs_type == &t_any)
1023 lhs_type = item_type;
1024 else if (item_type != &t_unknown
Bram Moolenaara1c51952022-02-02 16:20:26 +00001025 && need_type_where(item_type, lhs_type, -1,
1026 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001027 goto failed;
1028 var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
1029 if (var_lvar == NULL)
1030 // out of memory or used as an argument
1031 goto failed;
1032
1033 if (semicolon && idx == var_count - 1)
1034 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001035 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1036 }
1037
1038 if (*p == ',' || *p == ';')
1039 ++p;
1040 arg = skipwhite(p);
1041 vim_free(name);
1042 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001043
1044 forscope->fs_funcref_idx = funcref_lvar->lv_idx;
1045 // remember the number of variables and closures, used in :endfor
1046 forscope->fs_local_count = cctx->ctx_locals.ga_len;
1047 forscope->fs_closure_count = cctx->ctx_closure_count;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001048 }
1049
1050 return arg_end;
1051
1052failed:
1053 vim_free(name);
1054 drop_scope(cctx);
1055 return NULL;
1056}
1057
1058/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001059 * At :endfor and :endwhile: Generate an ISN_ENDLOOP instruction if any
1060 * variable was declared that could be used by a new closure.
1061 */
1062 static int
1063compile_loop_end(
1064 int prev_local_count,
1065 int prev_closure_count,
1066 int funcref_idx,
1067 cctx_T *cctx)
1068{
1069 if (cctx->ctx_locals.ga_len > prev_local_count
1070 && cctx->ctx_closure_count > prev_closure_count)
1071 return generate_ENDLOOP(cctx, funcref_idx, prev_local_count);
1072 return OK;
1073}
1074
1075/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001076 * compile "endfor"
1077 */
1078 char_u *
1079compile_endfor(char_u *arg, cctx_T *cctx)
1080{
1081 garray_T *instr = &cctx->ctx_instr;
1082 scope_T *scope = cctx->ctx_scope;
1083 forscope_T *forscope;
1084 isn_T *isn;
1085
1086 if (misplaced_cmdmod(cctx))
1087 return NULL;
1088
1089 if (scope == NULL || scope->se_type != FOR_SCOPE)
1090 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001091 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001092 return NULL;
1093 }
1094 forscope = &scope->se_u.se_for;
1095 cctx->ctx_scope = scope->se_outer;
1096 if (cctx->ctx_skip != SKIP_YES)
1097 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001098 // Handle the case that any local variables were declared that might be
1099 // used in a closure.
1100 if (compile_loop_end(forscope->fs_local_count,
1101 forscope->fs_closure_count,
1102 forscope->fs_funcref_idx,
1103 cctx) == FAIL)
1104 return NULL;
1105
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001106 unwind_locals(cctx, scope->se_local_count);
1107
1108 // At end of ":for" scope jump back to the FOR instruction.
1109 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1110
1111 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001112 // In debug mode an ISN_DEBUG was inserted.
1113 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1114 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001115 isn->isn_arg.forloop.for_end = instr->ga_len;
1116
1117 // Fill in the "end" label any BREAK statements
1118 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1119
1120 // Below the ":for" scope drop the "expr" list from the stack.
1121 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1122 return NULL;
1123 }
1124
1125 vim_free(scope);
1126
1127 return arg;
1128}
1129
1130/*
1131 * compile "while expr"
1132 *
1133 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001134 * top: EVAL expr Push result of "expr"
1135 * WHILE funcref-idx end Jump if false
1136 * ... body ...
1137 * ENDLOOP funcref-idx off count only if closure uses local var
1138 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001139 * end:
1140 *
1141 */
1142 char_u *
1143compile_while(char_u *arg, cctx_T *cctx)
1144{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001145 char_u *p = arg;
1146 scope_T *scope;
1147 whilescope_T *whilescope;
1148 lvar_T *funcref_lvar;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001149
1150 scope = new_scope(cctx, WHILE_SCOPE);
1151 if (scope == NULL)
1152 return NULL;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001153 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001154
1155 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001156 whilescope->ws_top_label = current_instr_idx(cctx);
1157
1158 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1159 // It is not used when no closures are encountered, we don't know yet.
1160 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
1161 if (funcref_lvar == NULL)
1162 {
1163 drop_scope(cctx);
1164 return NULL; // out of memory
1165 }
1166 whilescope->ws_funcref_idx = funcref_lvar->lv_idx;
1167 // remember the number of variables and closures, used in :endwhile
1168 whilescope->ws_local_count = cctx->ctx_locals.ga_len;
1169 whilescope->ws_closure_count = cctx->ctx_closure_count;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001170
1171 // compile "expr"
1172 if (compile_expr0(&p, cctx) == FAIL)
1173 return NULL;
1174
1175 if (!ends_excmd2(arg, skipwhite(p)))
1176 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001177 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001178 return NULL;
1179 }
1180
1181 if (cctx->ctx_skip != SKIP_YES)
1182 {
1183 if (bool_on_stack(cctx) == FAIL)
1184 return FAIL;
1185
1186 // CMDMOD_REV must come before the jump
1187 generate_undo_cmdmods(cctx);
1188
1189 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001190 if (compile_jump_to_end(&whilescope->ws_end_label,
1191 JUMP_WHILE_FALSE, funcref_lvar->lv_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001192 return FAIL;
1193 }
1194
1195 return p;
1196}
1197
1198/*
1199 * compile "endwhile"
1200 */
1201 char_u *
1202compile_endwhile(char_u *arg, cctx_T *cctx)
1203{
1204 scope_T *scope = cctx->ctx_scope;
1205 garray_T *instr = &cctx->ctx_instr;
1206
1207 if (misplaced_cmdmod(cctx))
1208 return NULL;
1209 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1210 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001211 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001212 return NULL;
1213 }
1214 cctx->ctx_scope = scope->se_outer;
1215 if (cctx->ctx_skip != SKIP_YES)
1216 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001217 whilescope_T *whilescope = &scope->se_u.se_while;
1218
1219 // Handle the case that any local variables were declared that might be
1220 // used in a closure.
1221 if (compile_loop_end(whilescope->ws_local_count,
1222 whilescope->ws_closure_count,
1223 whilescope->ws_funcref_idx,
1224 cctx) == FAIL)
1225 return NULL;
1226
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001227 unwind_locals(cctx, scope->se_local_count);
1228
1229#ifdef FEAT_PROFILE
1230 // count the endwhile before jumping
1231 may_generate_prof_end(cctx, cctx->ctx_lnum);
1232#endif
1233
1234 // At end of ":for" scope jump back to the FOR instruction.
1235 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1236
1237 // Fill in the "end" label in the WHILE statement so it can jump here.
1238 // And in any jumps for ":break"
1239 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1240 instr->ga_len, cctx);
1241 }
1242
1243 vim_free(scope);
1244
1245 return arg;
1246}
1247
1248/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001249 * Get the current information about variables declared inside a loop.
1250 * Returns zero if there are none, otherwise the count.
1251 * "loop_var_idx" is then set to the index of the first variable.
1252 */
1253 short
1254get_loop_var_info(cctx_T *cctx, short *loop_var_idx)
1255{
1256 scope_T *scope = cctx->ctx_scope;
1257 int start_local_count;
1258
1259 while (scope != NULL && scope->se_type != WHILE_SCOPE
1260 && scope->se_type != FOR_SCOPE)
1261 scope = scope->se_outer;
1262 if (scope == NULL)
1263 return 0;
1264
1265 if (scope->se_type == WHILE_SCOPE)
1266 start_local_count = scope->se_u.se_while.ws_local_count;
1267 else
1268 start_local_count = scope->se_u.se_for.fs_local_count;
1269 if (cctx->ctx_locals.ga_len > start_local_count)
1270 {
1271 *loop_var_idx = (short)start_local_count;
1272 return (short)(cctx->ctx_locals.ga_len - start_local_count);
1273 }
1274 return 0;
1275}
1276
1277/*
1278 * Get the index of the first variable in a loop, if any.
1279 * Returns -1 if none.
1280 */
1281 int
1282get_loop_var_idx(cctx_T *cctx)
1283{
1284 short loop_var_idx;
1285
1286 if (get_loop_var_info(cctx, &loop_var_idx) > 0)
1287 return loop_var_idx;
1288 return -1;
1289}
1290
1291/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001292 * compile "continue"
1293 */
1294 char_u *
1295compile_continue(char_u *arg, cctx_T *cctx)
1296{
1297 scope_T *scope = cctx->ctx_scope;
1298 int try_scopes = 0;
1299 int loop_label;
1300
1301 for (;;)
1302 {
1303 if (scope == NULL)
1304 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +00001305 emsg(_(e_continue_without_while_or_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001306 return NULL;
1307 }
1308 if (scope->se_type == FOR_SCOPE)
1309 {
1310 loop_label = scope->se_u.se_for.fs_top_label;
1311 break;
1312 }
1313 if (scope->se_type == WHILE_SCOPE)
1314 {
1315 loop_label = scope->se_u.se_while.ws_top_label;
1316 break;
1317 }
1318 if (scope->se_type == TRY_SCOPE)
1319 ++try_scopes;
1320 scope = scope->se_outer;
1321 }
1322
1323 if (try_scopes > 0)
1324 // Inside one or more try/catch blocks we first need to jump to the
1325 // "finally" or "endtry" to cleanup.
1326 generate_TRYCONT(cctx, try_scopes, loop_label);
1327 else
1328 // Jump back to the FOR or WHILE instruction.
1329 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1330
1331 return arg;
1332}
1333
1334/*
1335 * compile "break"
1336 */
1337 char_u *
1338compile_break(char_u *arg, cctx_T *cctx)
1339{
1340 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar873f8242022-03-10 21:53:44 +00001341 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001342 endlabel_T **el;
1343
1344 for (;;)
1345 {
1346 if (scope == NULL)
1347 {
Bram Moolenaar3a846e62022-01-01 16:21:00 +00001348 emsg(_(e_break_without_while_or_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001349 return NULL;
1350 }
Bram Moolenaar873f8242022-03-10 21:53:44 +00001351 if (scope->se_type == FOR_SCOPE)
1352 {
1353 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001354 break;
Bram Moolenaar873f8242022-03-10 21:53:44 +00001355 }
1356 if (scope->se_type == WHILE_SCOPE)
1357 {
1358 el = &scope->se_u.se_while.ws_end_label;
1359 break;
1360 }
1361 if (scope->se_type == TRY_SCOPE)
1362 ++try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001363 scope = scope->se_outer;
1364 }
1365
Bram Moolenaar873f8242022-03-10 21:53:44 +00001366 if (try_scopes > 0)
1367 // Inside one or more try/catch blocks we first need to jump to the
1368 // "finally" or "endtry" to cleanup. Then come to the next JUMP
1369 // intruction, which we don't know the index of yet.
1370 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1371
1372 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1373 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001374 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001375 return FAIL;
1376
1377 return arg;
1378}
1379
1380/*
1381 * compile "{" start of block
1382 */
1383 char_u *
1384compile_block(char_u *arg, cctx_T *cctx)
1385{
1386 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1387 return NULL;
1388 return skipwhite(arg + 1);
1389}
1390
1391/*
1392 * compile end of block: drop one scope
1393 */
1394 void
1395compile_endblock(cctx_T *cctx)
1396{
1397 scope_T *scope = cctx->ctx_scope;
1398
1399 cctx->ctx_scope = scope->se_outer;
1400 unwind_locals(cctx, scope->se_local_count);
1401 vim_free(scope);
1402}
1403
1404/*
1405 * Compile "try".
1406 * Creates a new scope for the try-endtry, pointing to the first catch and
1407 * finally.
1408 * Creates another scope for the "try" block itself.
1409 * TRY instruction sets up exception handling at runtime.
1410 *
1411 * "try"
1412 * TRY -> catch1, -> finally push trystack entry
1413 * ... try block
1414 * "throw {exception}"
1415 * EVAL {exception}
1416 * THROW create exception
1417 * ... try block
1418 * " catch {expr}"
1419 * JUMP -> finally
1420 * catch1: PUSH exception
1421 * EVAL {expr}
1422 * MATCH
1423 * JUMP nomatch -> catch2
1424 * CATCH remove exception
1425 * ... catch block
1426 * " catch"
1427 * JUMP -> finally
1428 * catch2: CATCH remove exception
1429 * ... catch block
1430 * " finally"
1431 * finally:
1432 * ... finally block
1433 * " endtry"
1434 * ENDTRY pop trystack entry, may rethrow
1435 */
1436 char_u *
1437compile_try(char_u *arg, cctx_T *cctx)
1438{
1439 garray_T *instr = &cctx->ctx_instr;
1440 scope_T *try_scope;
1441 scope_T *scope;
1442
1443 if (misplaced_cmdmod(cctx))
1444 return NULL;
1445
1446 // scope that holds the jumps that go to catch/finally/endtry
1447 try_scope = new_scope(cctx, TRY_SCOPE);
1448 if (try_scope == NULL)
1449 return NULL;
1450
1451 if (cctx->ctx_skip != SKIP_YES)
1452 {
1453 isn_T *isn;
1454
1455 // "try_catch" is set when the first ":catch" is found or when no catch
1456 // is found and ":finally" is found.
1457 // "try_finally" is set when ":finally" is found
1458 // "try_endtry" is set when ":endtry" is found
1459 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1460 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1461 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001462 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1463 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001464 return NULL;
1465 }
1466
1467 // scope for the try block itself
1468 scope = new_scope(cctx, BLOCK_SCOPE);
1469 if (scope == NULL)
1470 return NULL;
1471
1472 return arg;
1473}
1474
1475/*
1476 * Compile "catch {expr}".
1477 */
1478 char_u *
1479compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1480{
1481 scope_T *scope = cctx->ctx_scope;
1482 garray_T *instr = &cctx->ctx_instr;
1483 char_u *p;
1484 isn_T *isn;
1485
1486 if (misplaced_cmdmod(cctx))
1487 return NULL;
1488
1489 // end block scope from :try or :catch
1490 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1491 compile_endblock(cctx);
1492 scope = cctx->ctx_scope;
1493
1494 // Error if not in a :try scope
1495 if (scope == NULL || scope->se_type != TRY_SCOPE)
1496 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001497 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001498 return NULL;
1499 }
1500
1501 if (scope->se_u.se_try.ts_caught_all)
1502 {
1503 emsg(_(e_catch_unreachable_after_catch_all));
1504 return NULL;
1505 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001506 if (!cctx->ctx_had_return)
1507 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001508
1509 if (cctx->ctx_skip != SKIP_YES)
1510 {
1511#ifdef FEAT_PROFILE
1512 // the profile-start should be after the jump
1513 if (cctx->ctx_compile_type == CT_PROFILE
1514 && instr->ga_len > 0
1515 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1516 .isn_type == ISN_PROF_START)
1517 --instr->ga_len;
1518#endif
1519 // Jump from end of previous block to :finally or :endtry
1520 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001521 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001522 return NULL;
1523
1524 // End :try or :catch scope: set value in ISN_TRY instruction
1525 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001526 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1527 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001528 if (scope->se_u.se_try.ts_catch_label != 0)
1529 {
1530 // Previous catch without match jumps here
1531 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1532 isn->isn_arg.jump.jump_where = instr->ga_len;
1533 }
1534#ifdef FEAT_PROFILE
1535 if (cctx->ctx_compile_type == CT_PROFILE)
1536 {
1537 // a "throw" that jumps here needs to be counted
1538 generate_instr(cctx, ISN_PROF_END);
1539 // the "catch" is also counted
1540 generate_instr(cctx, ISN_PROF_START);
1541 }
1542#endif
1543 if (cctx->ctx_compile_type == CT_DEBUG)
1544 generate_instr_debug(cctx);
1545 }
1546
1547 p = skipwhite(arg);
1548 if (ends_excmd2(arg, p))
1549 {
1550 scope->se_u.se_try.ts_caught_all = TRUE;
1551 scope->se_u.se_try.ts_catch_label = 0;
1552 }
1553 else
1554 {
1555 char_u *end;
1556 char_u *pat;
1557 char_u *tofree = NULL;
1558 int dropped = 0;
1559 int len;
1560
1561 // Push v:exception, push {expr} and MATCH
1562 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1563
1564 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1565 if (*end != *p)
1566 {
1567 semsg(_(e_separator_mismatch_str), p);
1568 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001569 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001570 }
1571 if (tofree == NULL)
1572 len = (int)(end - (p + 1));
1573 else
1574 len = (int)(end - tofree);
1575 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1576 vim_free(tofree);
1577 p += len + 2 + dropped;
1578 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001579 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001580 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001581 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001582
1583 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1584 return NULL;
1585
1586 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1587 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1588 return NULL;
1589 }
1590
1591 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1592 return NULL;
1593
1594 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1595 return NULL;
1596 return p;
1597}
1598
1599 char_u *
1600compile_finally(char_u *arg, cctx_T *cctx)
1601{
1602 scope_T *scope = cctx->ctx_scope;
1603 garray_T *instr = &cctx->ctx_instr;
1604 isn_T *isn;
1605 int this_instr;
1606
1607 if (misplaced_cmdmod(cctx))
1608 return NULL;
1609
1610 // end block scope from :try or :catch
1611 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1612 compile_endblock(cctx);
1613 scope = cctx->ctx_scope;
1614
1615 // Error if not in a :try scope
1616 if (scope == NULL || scope->se_type != TRY_SCOPE)
1617 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001618 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001619 return NULL;
1620 }
1621
1622 if (cctx->ctx_skip != SKIP_YES)
1623 {
1624 // End :catch or :finally scope: set value in ISN_TRY instruction
1625 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001626 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001627 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001628 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001629 return NULL;
1630 }
1631
1632 this_instr = instr->ga_len;
1633#ifdef FEAT_PROFILE
1634 if (cctx->ctx_compile_type == CT_PROFILE
1635 && ((isn_T *)instr->ga_data)[this_instr - 1]
1636 .isn_type == ISN_PROF_START)
1637 {
1638 // jump to the profile start of the "finally"
1639 --this_instr;
1640
1641 // jump to the profile end above it
1642 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1643 .isn_type == ISN_PROF_END)
1644 --this_instr;
1645 }
1646#endif
1647
1648 // Fill in the "end" label in jumps at the end of the blocks.
1649 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1650 this_instr, cctx);
1651
1652 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001653 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1654 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1655 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001656 if (scope->se_u.se_try.ts_catch_label != 0)
1657 {
1658 // Previous catch without match jumps here
1659 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1660 isn->isn_arg.jump.jump_where = this_instr;
1661 scope->se_u.se_try.ts_catch_label = 0;
1662 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001663 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001664 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1665 return NULL;
1666 }
1667
1668 return arg;
1669}
1670
1671 char_u *
1672compile_endtry(char_u *arg, cctx_T *cctx)
1673{
1674 scope_T *scope = cctx->ctx_scope;
1675 garray_T *instr = &cctx->ctx_instr;
1676 isn_T *try_isn;
1677
1678 if (misplaced_cmdmod(cctx))
1679 return NULL;
1680
1681 // end block scope from :catch or :finally
1682 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1683 compile_endblock(cctx);
1684 scope = cctx->ctx_scope;
1685
1686 // Error if not in a :try scope
1687 if (scope == NULL || scope->se_type != TRY_SCOPE)
1688 {
1689 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001690 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001691 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001692 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001693 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001694 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001695 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001696 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001697 return NULL;
1698 }
1699
1700 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1701 if (cctx->ctx_skip != SKIP_YES)
1702 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001703 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1704 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001705 {
1706 emsg(_(e_missing_catch_or_finally));
1707 return NULL;
1708 }
1709
1710#ifdef FEAT_PROFILE
1711 if (cctx->ctx_compile_type == CT_PROFILE
1712 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1713 .isn_type == ISN_PROF_START)
1714 // move the profile start after "endtry" so that it's not counted when
1715 // the exception is rethrown.
1716 --instr->ga_len;
1717#endif
1718
1719 // Fill in the "end" label in jumps at the end of the blocks, if not
1720 // done by ":finally".
1721 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1722 instr->ga_len, cctx);
1723
1724 if (scope->se_u.se_try.ts_catch_label != 0)
1725 {
1726 // Last catch without match jumps here
1727 isn_T *isn = ((isn_T *)instr->ga_data)
1728 + scope->se_u.se_try.ts_catch_label;
1729 isn->isn_arg.jump.jump_where = instr->ga_len;
1730 }
1731 }
1732
Bram Moolenaar53c29612022-01-12 16:18:18 +00001733 // If there is a finally clause that ends in return then we will return.
1734 // If one of the blocks didn't end in "return" or we did not catch all
1735 // exceptions reset the had_return flag.
1736 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1737 && (scope->se_u.se_try.ts_no_return
1738 || !scope->se_u.se_try.ts_caught_all))
1739 cctx->ctx_had_return = FALSE;
1740
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001741 compile_endblock(cctx);
1742
1743 if (cctx->ctx_skip != SKIP_YES)
1744 {
1745 // End :catch or :finally scope: set instruction index in ISN_TRY
1746 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001747 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001748 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001749 return NULL;
1750#ifdef FEAT_PROFILE
1751 if (cctx->ctx_compile_type == CT_PROFILE)
1752 generate_instr(cctx, ISN_PROF_START);
1753#endif
1754 }
1755 return arg;
1756}
1757
1758/*
1759 * compile "throw {expr}"
1760 */
1761 char_u *
1762compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1763{
1764 char_u *p = skipwhite(arg);
1765
1766 if (compile_expr0(&p, cctx) == FAIL)
1767 return NULL;
1768 if (cctx->ctx_skip == SKIP_YES)
1769 return p;
1770 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1771 return NULL;
1772 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1773 return NULL;
1774
1775 return p;
1776}
1777
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001778/*
1779 * Compile an expression or function call.
1780 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001781 char_u *
1782compile_eval(char_u *arg, cctx_T *cctx)
1783{
1784 char_u *p = arg;
1785 int name_only;
1786 long lnum = SOURCING_LNUM;
1787
1788 // find_ex_command() will consider a variable name an expression, assuming
1789 // that something follows on the next line. Check that something actually
1790 // follows, otherwise it's probably a misplaced command.
1791 name_only = cmd_is_name_only(arg);
1792
1793 if (compile_expr0(&p, cctx) == FAIL)
1794 return NULL;
1795
1796 if (name_only && lnum == SOURCING_LNUM)
1797 {
1798 semsg(_(e_expression_without_effect_str), arg);
1799 return NULL;
1800 }
1801
1802 // drop the result
1803 generate_instr_drop(cctx, ISN_DROP, 1);
1804
1805 return skipwhite(p);
1806}
1807
1808/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001809 * Get the local variable index for deferred function calls.
1810 * Reserve it when not done already.
1811 * Returns zero for failure.
1812 */
1813 int
1814get_defer_var_idx(cctx_T *cctx)
1815{
1816 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1817 + cctx->ctx_ufunc->uf_dfunc_idx;
1818 if (dfunc->df_defer_var_idx == 0)
1819 {
1820 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1821 TRUE, &t_list_any);
1822 if (lvar == NULL)
1823 return 0;
1824 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1825 }
1826 return dfunc->df_defer_var_idx;
1827}
1828
1829/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001830 * Compile "defer func(arg)".
1831 */
1832 char_u *
1833compile_defer(char_u *arg_start, cctx_T *cctx)
1834{
Bram Moolenaar16900322022-09-08 19:51:45 +01001835 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001836 char_u *arg = arg_start;
1837 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001838 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001839 type_T *type;
1840 int func_idx;
1841
1842 // Get a funcref for the function name.
1843 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01001844 paren = vim_strchr(arg, '(');
1845 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001846 {
1847 semsg(_(e_missing_parenthesis_str), arg);
1848 return NULL;
1849 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001850 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001851 func_idx = find_internal_func(arg);
1852 if (func_idx >= 0)
1853 // TODO: better type
1854 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1855 &t_func_any, FALSE);
1856 else if (compile_expr0(&arg, cctx) == FAIL)
1857 return NULL;
Bram Moolenaar16900322022-09-08 19:51:45 +01001858 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001859
1860 // check for function type
1861 type = get_type_on_stack(cctx, 0);
1862 if (type->tt_type != VAR_FUNC)
1863 {
1864 emsg(_(e_function_name_required));
1865 return NULL;
1866 }
1867
1868 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01001869 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001870 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1871 return NULL;
1872
Bram Moolenaar16900322022-09-08 19:51:45 +01001873 if (func_idx >= 0)
1874 {
1875 type2_T *argtypes = NULL;
1876 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1877
1878 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
1879 &argtypes, shuffled_argtypes) == FAIL)
1880 return NULL;
1881 }
1882 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
1883 arg_start) == FAIL)
1884 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001885
Bram Moolenaar806a2732022-09-04 15:40:36 +01001886 defer_var_idx = get_defer_var_idx(cctx);
1887 if (defer_var_idx == 0)
1888 return NULL;
1889 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001890 return NULL;
1891
1892 return skipwhite(arg);
1893}
1894
1895/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001896 * compile "echo expr"
1897 * compile "echomsg expr"
1898 * compile "echoerr expr"
1899 * compile "echoconsole expr"
1900 * compile "execute expr"
1901 */
1902 char_u *
1903compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
1904{
1905 char_u *p = arg;
1906 char_u *prev = arg;
1907 char_u *expr_start;
1908 int count = 0;
1909 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001910 type_T *type;
1911
1912 for (;;)
1913 {
1914 if (ends_excmd2(prev, p))
1915 break;
1916 expr_start = p;
1917 if (compile_expr0(&p, cctx) == FAIL)
1918 return NULL;
1919
1920 if (cctx->ctx_skip != SKIP_YES)
1921 {
1922 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001923 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001924 if (type->tt_type == VAR_VOID)
1925 {
1926 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
1927 return NULL;
1928 }
1929 }
1930
1931 ++count;
1932 prev = p;
1933 p = skipwhite(p);
1934 }
1935
1936 if (count > 0)
1937 {
1938 long save_lnum = cctx->ctx_lnum;
1939
1940 // Use the line number where the command started.
1941 cctx->ctx_lnum = start_ctx_lnum;
1942
1943 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
1944 generate_ECHO(cctx, cmdidx == CMD_echo, count);
1945 else if (cmdidx == CMD_execute)
1946 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
1947 else if (cmdidx == CMD_echomsg)
1948 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01001949#ifdef HAS_MESSAGE_WINDOW
1950 else if (cmdidx == CMD_echowindow)
1951 generate_MULT_EXPR(cctx, ISN_ECHOWINDOW, count);
1952#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001953 else if (cmdidx == CMD_echoconsole)
1954 generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
1955 else
1956 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
1957
1958 cctx->ctx_lnum = save_lnum;
1959 }
1960 return p;
1961}
1962
1963/*
1964 * If "eap" has a range that is not a constant generate an ISN_RANGE
1965 * instruction to compute it and return OK.
1966 * Otherwise return FAIL, the caller must deal with any range.
1967 */
1968 static int
1969compile_variable_range(exarg_T *eap, cctx_T *cctx)
1970{
1971 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
1972 char_u *p = skipdigits(eap->cmd);
1973
1974 if (p == range_end)
1975 return FAIL;
1976 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
1977}
1978
1979/*
1980 * :put r
1981 * :put ={expr}
1982 */
1983 char_u *
1984compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
1985{
1986 char_u *line = arg;
1987 linenr_T lnum;
1988 char *errormsg;
1989 int above = eap->forceit;
1990
1991 eap->regname = *line;
1992
1993 if (eap->regname == '=')
1994 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00001995 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001996
1997 if (compile_expr0(&p, cctx) == FAIL)
1998 return NULL;
1999 line = p;
2000 }
2001 else if (eap->regname != NUL)
2002 ++line;
2003
2004 if (compile_variable_range(eap, cctx) == OK)
2005 {
2006 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2007 }
2008 else
2009 {
2010 // Either no range or a number.
2011 // "errormsg" will not be set because the range is ADDR_LINES.
2012 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2013 // cannot happen
2014 return NULL;
2015 if (eap->addr_count == 0)
2016 lnum = -1;
2017 else
2018 lnum = eap->line2;
2019 if (above)
2020 --lnum;
2021 }
2022
2023 generate_PUT(cctx, eap->regname, lnum);
2024 return line;
2025}
2026
2027/*
2028 * A command that is not compiled, execute with legacy code.
2029 */
2030 char_u *
2031compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2032{
2033 char_u *line = line_arg;
2034 char_u *p;
2035 int has_expr = FALSE;
2036 char_u *nextcmd = (char_u *)"";
2037 char_u *tofree = NULL;
2038 char_u *cmd_arg = NULL;
2039
2040 if (cctx->ctx_skip == SKIP_YES)
2041 goto theend;
2042
2043 // If there was a prececing command modifier, drop it and include it in the
2044 // EXEC command.
2045 if (cctx->ctx_has_cmdmod)
2046 {
2047 garray_T *instr = &cctx->ctx_instr;
2048 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2049
2050 if (isn->isn_type == ISN_CMDMOD)
2051 {
2052 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2053 ->cmod_filter_regmatch.regprog);
2054 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2055 --instr->ga_len;
2056 cctx->ctx_has_cmdmod = FALSE;
2057 }
2058 }
2059
2060 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2061 {
2062 long argt = eap->argt;
2063 int usefilter = FALSE;
2064
2065 has_expr = argt & (EX_XFILE | EX_EXPAND);
2066
2067 // If the command can be followed by a bar, find the bar and truncate
2068 // it, so that the following command can be compiled.
2069 // The '|' is overwritten with a NUL, it is put back below.
2070 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2071 && *eap->arg == '!')
2072 // :w !filter or :r !filter or :r! filter
2073 usefilter = TRUE;
2074 if ((argt & EX_TRLBAR) && !usefilter)
2075 {
2076 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002077 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002078 if (eap->nextcmd != NULL)
2079 nextcmd = eap->nextcmd;
2080 }
2081 else if (eap->cmdidx == CMD_wincmd)
2082 {
2083 p = eap->arg;
2084 if (*p != NUL)
2085 ++p;
2086 if (*p == 'g' || *p == Ctrl_G)
2087 ++p;
2088 p = skipwhite(p);
2089 if (*p == '|')
2090 {
2091 *p = NUL;
2092 nextcmd = p + 1;
2093 }
2094 }
2095 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2096 {
2097 // If there is a trailing '{' read lines until the '}'
2098 p = eap->arg + STRLEN(eap->arg) - 1;
2099 while (p > eap->arg && VIM_ISWHITE(*p))
2100 --p;
2101 if (*p == '{')
2102 {
2103 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002104 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002105 int start_lnum = SOURCING_LNUM;
2106
2107 CLEAR_FIELD(ea);
2108 ea.arg = eap->arg;
2109 fill_exarg_from_cctx(&ea, cctx);
2110 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2111 if (tofree != NULL)
2112 {
2113 *p = NUL;
2114 line = concat_str(line, tofree);
2115 if (line == NULL)
2116 goto theend;
2117 vim_free(tofree);
2118 tofree = line;
2119 SOURCING_LNUM = start_lnum;
2120 }
2121 }
2122 }
2123 }
2124
2125 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2126 {
2127 // expand filename in "syntax include [@group] filename"
2128 has_expr = TRUE;
2129 eap->arg = skipwhite(eap->arg + 7);
2130 if (*eap->arg == '@')
2131 eap->arg = skiptowhite(eap->arg);
2132 }
2133
2134 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2135 && STRLEN(eap->arg) > 4)
2136 {
2137 int delim = *eap->arg;
2138
2139 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2140 if (*p == delim)
2141 cmd_arg = p + 1;
2142 }
2143
2144 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2145 cmd_arg = eap->arg;
2146
2147 if (cmd_arg != NULL)
2148 {
2149 exarg_T nea;
2150
2151 CLEAR_FIELD(nea);
2152 nea.cmd = cmd_arg;
2153 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2154 if (nea.cmdidx < CMD_SIZE)
2155 {
2156 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2157 if (has_expr)
2158 eap->arg = skiptowhite(eap->arg);
2159 }
2160 }
2161
2162 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2163 {
2164 int count = 0;
2165 char_u *start = skipwhite(line);
2166
2167 // :cmd xxx`=expr1`yyy`=expr2`zzz
2168 // PUSHS ":cmd xxx"
2169 // eval expr1
2170 // PUSHS "yyy"
2171 // eval expr2
2172 // PUSHS "zzz"
2173 // EXECCONCAT 5
2174 for (;;)
2175 {
2176 if (p > start)
2177 {
2178 char_u *val = vim_strnsave(start, p - start);
2179
2180 generate_PUSHS(cctx, &val);
2181 ++count;
2182 }
2183 p += 2;
2184 if (compile_expr0(&p, cctx) == FAIL)
2185 return NULL;
2186 may_generate_2STRING(-1, TRUE, cctx);
2187 ++count;
2188 p = skipwhite(p);
2189 if (*p != '`')
2190 {
2191 emsg(_(e_missing_backtick));
2192 return NULL;
2193 }
2194 start = p + 1;
2195
2196 p = (char_u *)strstr((char *)start, "`=");
2197 if (p == NULL)
2198 {
2199 if (*skipwhite(start) != NUL)
2200 {
2201 char_u *val = vim_strsave(start);
2202
2203 generate_PUSHS(cctx, &val);
2204 ++count;
2205 }
2206 break;
2207 }
2208 }
2209 generate_EXECCONCAT(cctx, count);
2210 }
2211 else
2212 generate_EXEC_copy(cctx, ISN_EXEC, line);
2213
2214theend:
2215 if (*nextcmd != NUL)
2216 {
2217 // the parser expects a pointer to the bar, put it back
2218 --nextcmd;
2219 *nextcmd = '|';
2220 }
2221 vim_free(tofree);
2222
2223 return nextcmd;
2224}
2225
2226/*
2227 * A script command with heredoc, e.g.
2228 * ruby << EOF
2229 * command
2230 * EOF
2231 * Has been turned into one long line with NL characters by
2232 * get_function_body():
2233 * ruby << EOF<NL> command<NL>EOF
2234 */
2235 char_u *
2236compile_script(char_u *line, cctx_T *cctx)
2237{
2238 if (cctx->ctx_skip != SKIP_YES)
2239 {
2240 isn_T *isn;
2241
2242 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2243 return NULL;
2244 isn->isn_arg.string = vim_strsave(line);
2245 }
2246 return (char_u *)"";
2247}
2248
2249
2250/*
2251 * :s/pat/repl/
2252 */
2253 char_u *
2254compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2255{
2256 char_u *cmd = eap->arg;
2257 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2258
2259 if (expr != NULL)
2260 {
2261 int delimiter = *cmd++;
2262
2263 // There is a \=expr, find it in the substitute part.
2264 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2265 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2266 {
2267 garray_T save_ga = cctx->ctx_instr;
2268 char_u *end;
2269 int expr_res;
2270 int trailing_error;
2271 int instr_count;
2272 isn_T *instr;
2273 isn_T *isn;
2274
2275 cmd += 3;
2276 end = skip_substitute(cmd, delimiter);
2277
2278 // Temporarily reset the list of instructions so that the jump
2279 // labels are correct.
2280 cctx->ctx_instr.ga_len = 0;
2281 cctx->ctx_instr.ga_maxlen = 0;
2282 cctx->ctx_instr.ga_data = NULL;
2283 expr_res = compile_expr0(&cmd, cctx);
2284 if (end[-1] == NUL)
2285 end[-1] = delimiter;
2286 cmd = skipwhite(cmd);
2287 trailing_error = *cmd != delimiter && *cmd != NUL;
2288
2289 if (expr_res == FAIL || trailing_error
2290 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2291 {
2292 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002293 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002294 clear_instr_ga(&cctx->ctx_instr);
2295 cctx->ctx_instr = save_ga;
2296 return NULL;
2297 }
2298
2299 // Move the generated instructions into the ISN_SUBSTITUTE
2300 // instructions, then restore the list of instructions before
2301 // adding the ISN_SUBSTITUTE instruction.
2302 instr_count = cctx->ctx_instr.ga_len;
2303 instr = cctx->ctx_instr.ga_data;
2304 instr[instr_count].isn_type = ISN_FINISH;
2305
2306 cctx->ctx_instr = save_ga;
2307 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2308 {
2309 int idx;
2310
2311 for (idx = 0; idx < instr_count; ++idx)
2312 delete_instr(instr + idx);
2313 vim_free(instr);
2314 return NULL;
2315 }
2316 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2317 isn->isn_arg.subs.subs_instr = instr;
2318
2319 // skip over flags
2320 if (*end == '&')
2321 ++end;
2322 while (ASCII_ISALPHA(*end) || *end == '#')
2323 ++end;
2324 return end;
2325 }
2326 }
2327
2328 return compile_exec(arg, eap, cctx);
2329}
2330
2331 char_u *
2332compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2333{
2334 char_u *arg = eap->arg;
2335 lhs_T *lhs = &cctx->ctx_redir_lhs;
2336
2337 if (lhs->lhs_name != NULL)
2338 {
2339 if (STRNCMP(arg, "END", 3) == 0)
2340 {
2341 if (lhs->lhs_append)
2342 {
2343 // First load the current variable value.
2344 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
2345 cctx) == FAIL)
2346 return NULL;
2347 }
2348
2349 // Gets the redirected text and put it on the stack, then store it
2350 // in the variable.
2351 generate_instr_type(cctx, ISN_REDIREND, &t_string);
2352
2353 if (lhs->lhs_append)
LemonBoy372bcce2022-04-25 12:43:20 +01002354 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002355
2356 if (lhs->lhs_has_index)
2357 {
2358 // Use the info in "lhs" to store the value at the index in the
2359 // list or dict.
2360 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
2361 &t_string, cctx) == FAIL)
2362 return NULL;
2363 }
Bram Moolenaar5cd64792021-12-25 18:23:24 +00002364 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002365 return NULL;
2366
2367 VIM_CLEAR(lhs->lhs_name);
2368 VIM_CLEAR(lhs->lhs_whole);
2369 return arg + 3;
2370 }
2371 emsg(_(e_cannot_nest_redir));
2372 return NULL;
2373 }
2374
2375 if (arg[0] == '=' && arg[1] == '>')
2376 {
2377 int append = FALSE;
2378
2379 // redirect to a variable is compiled
2380 arg += 2;
2381 if (*arg == '>')
2382 {
2383 ++arg;
2384 append = TRUE;
2385 }
2386 arg = skipwhite(arg);
2387
2388 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002389 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002390 return NULL;
2391 if (need_type(&t_string, lhs->lhs_member_type,
2392 -1, 0, cctx, FALSE, FALSE) == FAIL)
2393 return NULL;
2394 generate_instr(cctx, ISN_REDIRSTART);
2395 lhs->lhs_append = append;
2396 if (lhs->lhs_has_index)
2397 {
2398 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2399 if (lhs->lhs_whole == NULL)
2400 return NULL;
2401 }
2402
2403 return arg + lhs->lhs_varlen_total;
2404 }
2405
2406 // other redirects are handled like at script level
2407 return compile_exec(line, eap, cctx);
2408}
2409
2410#if defined(FEAT_QUICKFIX) || defined(PROTO)
2411 char_u *
2412compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2413{
2414 isn_T *isn;
2415 char_u *p;
2416
2417 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2418 if (isn == NULL)
2419 return NULL;
2420 isn->isn_arg.number = eap->cmdidx;
2421
2422 p = eap->arg;
2423 if (compile_expr0(&p, cctx) == FAIL)
2424 return NULL;
2425
2426 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2427 if (isn == NULL)
2428 return NULL;
2429 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2430 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2431 return NULL;
2432 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2433 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2434 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2435
2436 return p;
2437}
2438#endif
2439
2440/*
2441 * Compile "return [expr]".
2442 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2443 */
2444 char_u *
2445compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2446{
2447 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002448 type_T *stack_type;
2449
2450 if (*p != NUL && *p != '|' && *p != '\n')
2451 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002452 // For a lambda, "return expr" is always used, also when "expr" results
2453 // in a void.
2454 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2455 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002456 {
2457 emsg(_(e_returning_value_in_function_without_return_type));
2458 return NULL;
2459 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002460 if (legacy)
2461 {
2462 int save_flags = cmdmod.cmod_flags;
2463
2464 generate_LEGACY_EVAL(cctx, p);
2465 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
2466 0, cctx, FALSE, FALSE) == FAIL)
2467 return NULL;
2468 cmdmod.cmod_flags |= CMOD_LEGACY;
2469 (void)skip_expr(&p, NULL);
2470 cmdmod.cmod_flags = save_flags;
2471 }
2472 else
2473 {
2474 // compile return argument into instructions
2475 if (compile_expr0(&p, cctx) == FAIL)
2476 return NULL;
2477 }
2478
2479 if (cctx->ctx_skip != SKIP_YES)
2480 {
2481 // "check_return_type" with uf_ret_type set to &t_unknown is used
2482 // for an inline function without a specified return type. Set the
2483 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002484 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002485 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002486 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002487 || (!check_return_type
2488 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2489 {
2490 cctx->ctx_ufunc->uf_ret_type = stack_type;
2491 }
2492 else
2493 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002494 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
2495 0, cctx, FALSE, FALSE) == FAIL)
2496 return NULL;
2497 }
2498 }
2499 }
2500 else
2501 {
2502 // "check_return_type" cannot be TRUE, only used for a lambda which
2503 // always has an argument.
2504 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2505 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2506 {
2507 emsg(_(e_missing_return_value));
2508 return NULL;
2509 }
2510
2511 // No argument, return zero.
2512 generate_PUSHNR(cctx, 0);
2513 }
2514
2515 // Undo any command modifiers.
2516 generate_undo_cmdmods(cctx);
2517
2518 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2519 return NULL;
2520
2521 // "return val | endif" is possible
2522 return skipwhite(p);
2523}
2524
2525/*
2526 * Check if the separator for a :global or :substitute command is OK.
2527 */
2528 int
2529check_global_and_subst(char_u *cmd, char_u *arg)
2530{
2531 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2532 {
2533 semsg(_(e_separator_not_supported_str), arg);
2534 return FAIL;
2535 }
2536 if (VIM_ISWHITE(cmd[1]))
2537 {
2538 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2539 return FAIL;
2540 }
2541 return OK;
2542}
2543
2544
2545#endif // defined(FEAT_EVAL)