blob: 3f44b88733625191ecbd80c8a1601785fc502a57 [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".
Bram Moolenaara275f2c2022-10-11 20:04:09 +010060 * Do this by clearing the name. If "keep" is TRUE do not reset the length, a
61 * closure may still need location of the variable.
Bram Moolenaardc7c3662021-12-20 15:04:29 +000062 */
63 static void
Bram Moolenaara275f2c2022-10-11 20:04:09 +010064unwind_locals(cctx_T *cctx, int new_top, int keep)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000065{
66 if (cctx->ctx_locals.ga_len > new_top)
Bram Moolenaara275f2c2022-10-11 20:04:09 +010067 for (int idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000068 {
Bram Moolenaara275f2c2022-10-11 20:04:09 +010069 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
70 VIM_CLEAR(lvar->lv_name);
Bram Moolenaardc7c3662021-12-20 15:04:29 +000071 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +010072 if (!keep)
73 cctx->ctx_locals.ga_len = new_top;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000074}
75
76/*
77 * Free all local variables.
78 */
79 void
80free_locals(cctx_T *cctx)
81{
Bram Moolenaara275f2c2022-10-11 20:04:09 +010082 unwind_locals(cctx, 0, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +000083 ga_clear(&cctx->ctx_locals);
84}
85
86
87/*
88 * Check if "name" can be "unlet".
89 */
90 int
91check_vim9_unlet(char_u *name)
92{
Bram Moolenaardbdd16b2022-08-14 21:46:07 +010093 if (*name == NUL)
94 {
95 semsg(_(e_argument_required_for_str), "unlet");
96 return FAIL;
97 }
98
Bram Moolenaardc7c3662021-12-20 15:04:29 +000099 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
100 {
101 // "unlet s:var" is allowed in legacy script.
102 if (*name == 's' && !script_is_vim9())
103 return OK;
104 semsg(_(e_cannot_unlet_str), name);
105 return FAIL;
106 }
107 return OK;
108}
109
110/*
111 * Callback passed to ex_unletlock().
112 */
113 static int
114compile_unlet(
115 lval_T *lvp,
116 char_u *name_end,
117 exarg_T *eap,
118 int deep UNUSED,
119 void *coookie)
120{
121 cctx_T *cctx = coookie;
122 char_u *p = lvp->ll_name;
123 int cc = *name_end;
124 int ret = OK;
125
126 if (cctx->ctx_skip == SKIP_YES)
127 return OK;
128
129 *name_end = NUL;
130 if (*p == '$')
131 {
132 // :unlet $ENV_VAR
133 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
134 }
135 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
136 {
137 lhs_T lhs;
138
139 // This is similar to assigning: lookup the list/dict, compile the
140 // idx/key. Then instead of storing the value unlet the item.
141 // unlet {list}[idx]
142 // unlet {dict}[key] dict.key
143 //
144 // Figure out the LHS type and other properties.
145 //
Bram Moolenaar97f8c102022-04-02 19:43:57 +0100146 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, FALSE, 0, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000147
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000148 // Use the info in "lhs" to unlet the item at the index in the
149 // list or dict.
150 if (ret == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000151 {
Bram Moolenaar2ef01d92022-01-06 21:38:11 +0000152 if (!lhs.lhs_has_index)
153 {
154 semsg(_(e_cannot_unlet_imported_item_str), p);
155 ret = FAIL;
156 }
157 else
158 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000159 }
160
161 vim_free(lhs.lhs_name);
162 }
163 else if (check_vim9_unlet(p) == FAIL)
164 {
165 ret = FAIL;
166 }
167 else
168 {
169 // Normal name. Only supports g:, w:, t: and b: namespaces.
170 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
171 }
172
173 *name_end = cc;
174 return ret;
175}
176
177/*
178 * Callback passed to ex_unletlock().
179 */
180 static int
181compile_lock_unlock(
182 lval_T *lvp,
183 char_u *name_end,
184 exarg_T *eap,
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000185 int deep,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000186 void *coookie)
187{
188 cctx_T *cctx = coookie;
189 int cc = *name_end;
190 char_u *p = lvp->ll_name;
191 int ret = OK;
192 size_t len;
193 char_u *buf;
194 isntype_T isn = ISN_EXEC;
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100195 char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000196
197 if (cctx->ctx_skip == SKIP_YES)
198 return OK;
199
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100200 if (*p == NUL)
201 {
202 semsg(_(e_argument_required_for_str), cmd);
203 return FAIL;
204 }
205
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000206 // Cannot use :lockvar and :unlockvar on local variables.
207 if (p[1] != ':')
208 {
209 char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
210
211 if (lookup_local(p, end - p, NULL, cctx) == OK)
212 {
213 char_u *s = p;
214
215 if (*end != '.' && *end != '[')
216 {
217 emsg(_(e_cannot_lock_unlock_local_variable));
218 return FAIL;
219 }
220
221 // For "d.member" put the local variable on the stack, it will be
222 // passed to ex_lockvar() indirectly.
223 if (compile_load(&s, end, cctx, FALSE, FALSE) == FAIL)
224 return FAIL;
225 isn = ISN_LOCKUNLOCK;
226 }
227 }
228
229 // Checking is done at runtime.
230 *name_end = NUL;
231 len = name_end - p + 20;
232 buf = alloc(len);
233 if (buf == NULL)
234 ret = FAIL;
235 else
236 {
Bram Moolenaare939f5e2022-01-26 21:32:59 +0000237 if (deep < 0)
238 vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
239 else
240 vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000241 ret = generate_EXEC_copy(cctx, isn, buf);
242
243 vim_free(buf);
244 *name_end = cc;
245 }
246 return ret;
247}
248
249/*
250 * compile "unlet var", "lock var" and "unlock var"
251 * "arg" points to "var".
252 */
253 char_u *
254compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
255{
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000256 int deep = 0;
257 char_u *p = arg;
258
259 if (eap->cmdidx != CMD_unlet)
260 {
261 if (eap->forceit)
262 deep = -1;
263 else if (vim_isdigit(*p))
264 {
265 deep = getdigits(&p);
266 p = skipwhite(p);
267 }
268 else
269 deep = 2;
270 }
271
272 ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000273 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
274 cctx);
275 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
276}
277
278/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100279 * Generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
280 * "funcref_idx" is used for JUMP_WHILE_FALSE
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000281 */
282 static int
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100283compile_jump_to_end(
284 endlabel_T **el,
285 jumpwhen_T when,
286 int funcref_idx,
287 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000288{
289 garray_T *instr = &cctx->ctx_instr;
290 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
291
292 if (endlabel == NULL)
293 return FAIL;
294 endlabel->el_next = *el;
295 *el = endlabel;
296 endlabel->el_end_label = instr->ga_len;
297
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100298 if (when == JUMP_WHILE_FALSE)
299 generate_WHILE(cctx, funcref_idx);
300 else
301 generate_JUMP(cctx, when, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000302 return OK;
303}
304
305 static void
306compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
307{
308 garray_T *instr = &cctx->ctx_instr;
309
310 while (*el != NULL)
311 {
312 endlabel_T *cur = (*el);
313 isn_T *isn;
314
315 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
316 isn->isn_arg.jump.jump_where = jump_where;
317 *el = cur->el_next;
318 vim_free(cur);
319 }
320}
321
322 static void
323compile_free_jump_to_end(endlabel_T **el)
324{
325 while (*el != NULL)
326 {
327 endlabel_T *cur = (*el);
328
329 *el = cur->el_next;
330 vim_free(cur);
331 }
332}
333
334/*
335 * Create a new scope and set up the generic items.
336 */
337 static scope_T *
338new_scope(cctx_T *cctx, scopetype_T type)
339{
340 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
341
342 if (scope == NULL)
343 return NULL;
344 scope->se_outer = cctx->ctx_scope;
345 cctx->ctx_scope = scope;
346 scope->se_type = type;
347 scope->se_local_count = cctx->ctx_locals.ga_len;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100348 if (scope->se_outer != NULL)
349 scope->se_loop_depth = scope->se_outer->se_loop_depth;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000350 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 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100526 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000527 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 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100673 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000674 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;
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100745 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000746 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 Moolenaarcc341812022-09-19 15:54:34 +0100826 int loop_lvar_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100827 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100828 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000829 lvar_T *var_lvar; // variable for "var"
830 type_T *vartype;
831 type_T *item_type = &t_any;
832 int idx;
833 int prev_lnum = cctx->ctx_prev_lnum;
834
835 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
836 if (p == NULL)
837 return NULL;
838 if (var_count == 0)
839 var_count = 1;
840 else
841 var_list = TRUE; // can also be a list of one variable
842
843 // consume "in"
844 wp = p;
845 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
846 return NULL;
847 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
848 {
849 if (*p == ':' && wp != p)
850 semsg(_(e_no_white_space_allowed_before_colon_str), p);
851 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000852 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000853 return NULL;
854 }
855 wp = p + 2;
856 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
857 return NULL;
858
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000859 // Find the already generated ISN_DEBUG to get the line number for the
860 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000861 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
862 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
863 .isn_type == ISN_DEBUG)
864 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000865 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000866 .isn_arg.debug.dbg_break_lnum;
867 }
868
869 scope = new_scope(cctx, FOR_SCOPE);
870 if (scope == NULL)
871 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100872 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
873 {
874 emsg(_(e_loop_nesting_too_deep));
875 return NULL;
876 }
877 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100878 forscope = &scope->se_u.se_for;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000879
880 // Reserve a variable to store the loop iteration counter and initialize it
881 // to -1.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100882 loop_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000883 if (loop_lvar == NULL)
884 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000885 drop_scope(cctx);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100886 return NULL; // out of memory
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000887 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100888 // get the index before a following reserve_local() makes the lval invalid
889 loop_lvar_idx = loop_lvar->lv_idx;
890 generate_STORENR(cctx, loop_lvar_idx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000891
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100892 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
893 // The variable index is always the loop var index plus one.
894 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100895 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100896 if (funcref_lvar == NULL)
897 {
898 drop_scope(cctx);
899 return NULL; // out of memory
900 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100901 // get the index before a following reserve_local() makes the lval invalid
902 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100903
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000904 // compile "expr", it remains on the stack until "endfor"
905 arg = p;
906 if (compile_expr0(&arg, cctx) == FAIL)
907 {
908 drop_scope(cctx);
909 return NULL;
910 }
911 arg_end = arg;
912
913 if (cctx->ctx_skip != SKIP_YES)
914 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000915 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000916 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000917 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000918 if (vartype->tt_type != VAR_LIST
919 && vartype->tt_type != VAR_STRING
920 && vartype->tt_type != VAR_BLOB
921 && vartype->tt_type != VAR_ANY
922 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000923 {
924 semsg(_(e_for_loop_on_str_not_supported),
925 vartype_name(vartype->tt_type));
926 drop_scope(cctx);
927 return NULL;
928 }
929
930 if (vartype->tt_type == VAR_STRING)
931 item_type = &t_string;
932 else if (vartype->tt_type == VAR_BLOB)
933 item_type = &t_number;
934 else if (vartype->tt_type == VAR_LIST
935 && vartype->tt_member->tt_type != VAR_ANY)
936 {
937 if (!var_list)
938 item_type = vartype->tt_member;
939 else if (vartype->tt_member->tt_type == VAR_LIST
940 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
941 item_type = vartype->tt_member->tt_member;
942 }
943
944 // CMDMOD_REV must come before the FOR instruction.
945 generate_undo_cmdmods(cctx);
946
947 // "for_end" is set when ":endfor" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100948 forscope->fs_top_label = current_instr_idx(cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000949
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000950 if (cctx->ctx_compile_type == CT_DEBUG)
951 {
952 int save_prev_lnum = cctx->ctx_prev_lnum;
953 isn_T *isn;
954
955 // Add ISN_DEBUG here, before deciding to end the loop. There will
956 // be another ISN_DEBUG before the next instruction.
957 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
958 // Increment the variable count so that the loop variable can be
959 // inspected.
960 cctx->ctx_prev_lnum = prev_lnum;
961 isn = generate_instr_debug(cctx);
962 ++isn->isn_arg.debug.dbg_var_names_len;
963 cctx->ctx_prev_lnum = save_prev_lnum;
964 }
965
Bram Moolenaarcc341812022-09-19 15:54:34 +0100966 generate_FOR(cctx, loop_lvar_idx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000967
968 arg = arg_start;
969 if (var_list)
970 {
971 generate_UNPACK(cctx, var_count, semicolon);
972 arg = skipwhite(arg + 1); // skip white after '['
973
Bram Moolenaar078a4612022-01-04 15:17:03 +0000974 // drop the list item
975 --cctx->ctx_type_stack.ga_len;
976
977 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000978 for (idx = 0; idx < var_count; ++idx)
979 {
Bram Moolenaar078a4612022-01-04 15:17:03 +0000980 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
981
982 if (push_type_stack(cctx, type) == FAIL)
983 {
984 drop_scope(cctx);
985 return NULL;
986 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000987 }
988 }
989
990 for (idx = 0; idx < var_count; ++idx)
991 {
992 assign_dest_T dest = dest_local;
993 int opt_flags = 0;
994 int vimvaridx = -1;
995 type_T *type = &t_any;
996 type_T *lhs_type = &t_any;
997 where_T where = WHERE_INIT;
998
999 p = skip_var_one(arg, FALSE);
1000 varlen = p - arg;
1001 name = vim_strnsave(arg, varlen);
1002 if (name == NULL)
1003 goto failed;
Bram Moolenaarce93d162023-01-30 21:12:34 +00001004 if (*skipwhite(p) == ':')
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001005 {
Bram Moolenaarce93d162023-01-30 21:12:34 +00001006 if (VIM_ISWHITE(*p))
1007 {
1008 semsg(_(e_no_white_space_allowed_before_colon_str), p);
1009 goto failed;
1010 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001011 p = skipwhite(p + 1);
1012 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
1013 }
1014
1015 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
1016 &vimvaridx, &type, cctx) == FAIL)
1017 goto failed;
1018 if (dest != dest_local)
1019 {
1020 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
Bram Moolenaard505d172022-12-18 21:42:55 +00001021 type, name, NULL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001022 goto failed;
1023 }
1024 else if (varlen == 1 && *arg == '_')
1025 {
1026 // Assigning to "_": drop the value.
1027 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1028 goto failed;
1029 }
1030 else
1031 {
1032 // Script var is not supported.
1033 if (STRNCMP(name, "s:", 2) == 0)
1034 {
1035 emsg(_(e_cannot_use_script_variable_in_for_loop));
1036 goto failed;
1037 }
1038
1039 if (!valid_varname(arg, (int)varlen, FALSE))
1040 goto failed;
1041 if (lookup_local(arg, varlen, NULL, cctx) == OK)
1042 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001043 semsg(_(e_variable_already_declared_str), arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001044 goto failed;
1045 }
1046
1047 // Reserve a variable to store "var".
LemonBoyc5d27442023-08-19 13:02:35 +02001048 if (var_list)
1049 {
1050 where.wt_index = idx + 1;
1051 where.wt_kind = WT_VARIABLE;
1052 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001053 if (lhs_type == &t_any)
1054 lhs_type = item_type;
1055 else if (item_type != &t_unknown
Bram Moolenaarc6951a72022-12-29 20:56:24 +00001056 && need_type_where(item_type, lhs_type, FALSE, -1,
Bram Moolenaara1c51952022-02-02 16:20:26 +00001057 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001058 goto failed;
Bram Moolenaar159b2d52022-10-11 21:41:25 +01001059 var_lvar = reserve_local(cctx, arg, varlen, ASSIGN_FINAL,
Bram Moolenaar6586a012022-09-30 11:04:50 +01001060 lhs_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001061 if (var_lvar == NULL)
1062 // out of memory or used as an argument
1063 goto failed;
1064
1065 if (semicolon && idx == var_count - 1)
1066 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001067 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1068 }
1069
1070 if (*p == ',' || *p == ';')
1071 ++p;
1072 arg = skipwhite(p);
1073 vim_free(name);
1074 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001075
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001076 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001077 compile_fill_loop_info(&forscope->fs_loop_info, funcref_lvar_idx, cctx);
1078 forscope->fs_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001079 }
1080
1081 return arg_end;
1082
1083failed:
1084 vim_free(name);
1085 drop_scope(cctx);
1086 return NULL;
1087}
1088
1089/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001090 * Used when ending a loop of :for and :while: Generate an ISN_ENDLOOP
1091 * instruction if any variable was declared that could be used by a new
1092 * closure.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001093 */
1094 static int
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001095compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001096{
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001097 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1098 && cctx->ctx_closure_count > loop_info->li_closure_count)
Bram Moolenaarcc341812022-09-19 15:54:34 +01001099 return generate_ENDLOOP(cctx, loop_info);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001100 return OK;
1101}
1102
1103/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001104 * compile "endfor"
1105 */
1106 char_u *
1107compile_endfor(char_u *arg, cctx_T *cctx)
1108{
1109 garray_T *instr = &cctx->ctx_instr;
1110 scope_T *scope = cctx->ctx_scope;
1111 forscope_T *forscope;
1112 isn_T *isn;
1113
1114 if (misplaced_cmdmod(cctx))
1115 return NULL;
1116
1117 if (scope == NULL || scope->se_type != FOR_SCOPE)
1118 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001119 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001120 return NULL;
1121 }
1122 forscope = &scope->se_u.se_for;
1123 cctx->ctx_scope = scope->se_outer;
1124 if (cctx->ctx_skip != SKIP_YES)
1125 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001126 // Handle the case that any local variables were declared that might be
1127 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001128 if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001129 return NULL;
1130
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001131 unwind_locals(cctx, scope->se_local_count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001132
1133 // At end of ":for" scope jump back to the FOR instruction.
1134 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1135
1136 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001137 // In debug mode an ISN_DEBUG was inserted.
1138 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1139 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001140 isn->isn_arg.forloop.for_end = instr->ga_len;
1141
1142 // Fill in the "end" label any BREAK statements
1143 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1144
1145 // Below the ":for" scope drop the "expr" list from the stack.
1146 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1147 return NULL;
1148 }
1149
1150 vim_free(scope);
1151
1152 return arg;
1153}
1154
1155/*
1156 * compile "while expr"
1157 *
1158 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001159 * top: EVAL expr Push result of "expr"
1160 * WHILE funcref-idx end Jump if false
1161 * ... body ...
1162 * ENDLOOP funcref-idx off count only if closure uses local var
1163 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001164 * end:
1165 *
1166 */
1167 char_u *
1168compile_while(char_u *arg, cctx_T *cctx)
1169{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001170 char_u *p = arg;
1171 scope_T *scope;
1172 whilescope_T *whilescope;
1173 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001174 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001175
1176 scope = new_scope(cctx, WHILE_SCOPE);
1177 if (scope == NULL)
1178 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001179 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
1180 {
1181 emsg(_(e_loop_nesting_too_deep));
1182 return NULL;
1183 }
1184 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001185 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001186
1187 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001188 whilescope->ws_top_label = current_instr_idx(cctx);
1189
1190 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1191 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +01001192 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001193 if (funcref_lvar == NULL)
1194 {
1195 drop_scope(cctx);
1196 return NULL; // out of memory
1197 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001198 // get the index before a following reserve_local() makes the lval invalid
1199 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001200
1201 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001202 compile_fill_loop_info(&whilescope->ws_loop_info, funcref_lvar_idx, cctx);
1203 whilescope->ws_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001204
1205 // compile "expr"
1206 if (compile_expr0(&p, cctx) == FAIL)
1207 return NULL;
1208
1209 if (!ends_excmd2(arg, skipwhite(p)))
1210 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001211 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001212 return NULL;
1213 }
1214
1215 if (cctx->ctx_skip != SKIP_YES)
1216 {
1217 if (bool_on_stack(cctx) == FAIL)
1218 return FAIL;
1219
1220 // CMDMOD_REV must come before the jump
1221 generate_undo_cmdmods(cctx);
1222
1223 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001224 if (compile_jump_to_end(&whilescope->ws_end_label,
Bram Moolenaarcc341812022-09-19 15:54:34 +01001225 JUMP_WHILE_FALSE, funcref_lvar_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001226 return FAIL;
1227 }
1228
1229 return p;
1230}
1231
1232/*
1233 * compile "endwhile"
1234 */
1235 char_u *
1236compile_endwhile(char_u *arg, cctx_T *cctx)
1237{
1238 scope_T *scope = cctx->ctx_scope;
1239 garray_T *instr = &cctx->ctx_instr;
1240
1241 if (misplaced_cmdmod(cctx))
1242 return NULL;
1243 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1244 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001245 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001246 return NULL;
1247 }
1248 cctx->ctx_scope = scope->se_outer;
1249 if (cctx->ctx_skip != SKIP_YES)
1250 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001251 whilescope_T *whilescope = &scope->se_u.se_while;
1252
1253 // Handle the case that any local variables were declared that might be
1254 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001255 if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001256 return NULL;
1257
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001258 unwind_locals(cctx, scope->se_local_count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001259
1260#ifdef FEAT_PROFILE
1261 // count the endwhile before jumping
1262 may_generate_prof_end(cctx, cctx->ctx_lnum);
1263#endif
1264
1265 // At end of ":for" scope jump back to the FOR instruction.
1266 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1267
1268 // Fill in the "end" label in the WHILE statement so it can jump here.
1269 // And in any jumps for ":break"
1270 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1271 instr->ga_len, cctx);
1272 }
1273
1274 vim_free(scope);
1275
1276 return arg;
1277}
1278
1279/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001280 * Get the current information about variables declared inside a loop.
Bram Moolenaarcc341812022-09-19 15:54:34 +01001281 * Returns TRUE if there are any and fills "lvi".
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001282 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001283 int
1284get_loop_var_info(cctx_T *cctx, loopvarinfo_T *lvi)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001285{
1286 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001287 int prev_local_count = 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001288
Bram Moolenaarcc341812022-09-19 15:54:34 +01001289 CLEAR_POINTER(lvi);
1290 for (;;)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001291 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01001292 loop_info_T *loopinfo;
1293 int cur_local_last;
1294 int start_local_count;
1295
1296 while (scope != NULL && scope->se_type != WHILE_SCOPE
1297 && scope->se_type != FOR_SCOPE)
1298 scope = scope->se_outer;
1299 if (scope == NULL)
1300 break;
1301
1302 if (scope->se_type == WHILE_SCOPE)
1303 {
1304 loopinfo = &scope->se_u.se_while.ws_loop_info;
1305 // :while reserves one variable for funcref count
1306 cur_local_last = loopinfo->li_local_count - 1;
1307 }
1308 else
1309 {
1310 loopinfo = &scope->se_u.se_for.fs_loop_info;
1311 // :for reserves three variable: loop count, funcref count and loop
1312 // var
1313 cur_local_last = loopinfo->li_local_count - 3;
1314 }
1315
1316 start_local_count = loopinfo->li_local_count;
1317 if (cctx->ctx_locals.ga_len > start_local_count)
1318 {
1319 lvi->lvi_loop[loopinfo->li_depth].var_idx =
1320 (short)start_local_count;
1321 lvi->lvi_loop[loopinfo->li_depth].var_count =
1322 (short)(cctx->ctx_locals.ga_len - start_local_count
1323 - prev_local_count);
1324 if (lvi->lvi_depth == 0)
1325 lvi->lvi_depth = loopinfo->li_depth + 1;
1326 }
1327
1328 scope = scope->se_outer;
1329 prev_local_count = cctx->ctx_locals.ga_len - cur_local_last;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001330 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001331 return lvi->lvi_depth > 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001332}
1333
1334/*
Bram Moolenaarcc341812022-09-19 15:54:34 +01001335 * Get the index of the variable "idx" in a loop, if any.
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001336 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001337 void
1338get_loop_var_idx(cctx_T *cctx, int idx, lvar_T *lvar)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001339{
Bram Moolenaarcc341812022-09-19 15:54:34 +01001340 loopvarinfo_T lvi;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001341
Bram Moolenaarcc341812022-09-19 15:54:34 +01001342 lvar->lv_loop_depth = -1;
1343 lvar->lv_loop_idx = -1;
1344 if (get_loop_var_info(cctx, &lvi))
1345 {
1346 int depth;
1347
1348 for (depth = lvi.lvi_depth - 1; depth >= 0; --depth)
1349 if (idx >= lvi.lvi_loop[depth].var_idx
1350 && idx < lvi.lvi_loop[depth].var_idx
1351 + lvi.lvi_loop[depth].var_count)
1352 {
1353 lvar->lv_loop_depth = depth;
1354 lvar->lv_loop_idx = lvi.lvi_loop[depth].var_idx;
1355 return;
1356 }
1357 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001358}
1359
1360/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001361 * Common for :break, :continue and :return
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001362 */
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001363 static int
1364compile_find_scope(
1365 int *loop_label, // where to jump to or NULL
1366 endlabel_T ***el, // end label or NULL
1367 int *try_scopes, // :try scopes encountered or NULL
1368 char *error, // error to use when no scope found
1369 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001370{
1371 scope_T *scope = cctx->ctx_scope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001372
1373 for (;;)
1374 {
1375 if (scope == NULL)
1376 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001377 if (error != NULL)
1378 emsg(_(error));
1379 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001380 }
1381 if (scope->se_type == FOR_SCOPE)
1382 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001383 if (compile_loop_end(&scope->se_u.se_for.fs_loop_info, cctx)
1384 == FAIL)
1385 return FAIL;
1386 if (loop_label != NULL)
1387 *loop_label = scope->se_u.se_for.fs_top_label;
1388 if (el != NULL)
1389 *el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001390 break;
1391 }
1392 if (scope->se_type == WHILE_SCOPE)
1393 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001394 if (compile_loop_end(&scope->se_u.se_while.ws_loop_info, cctx)
1395 == FAIL)
1396 return FAIL;
1397 if (loop_label != NULL)
1398 *loop_label = scope->se_u.se_while.ws_top_label;
1399 if (el != NULL)
1400 *el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001401 break;
1402 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001403 if (try_scopes != NULL && scope->se_type == TRY_SCOPE)
1404 ++*try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001405 scope = scope->se_outer;
1406 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001407 return OK;
1408}
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001409
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001410/*
1411 * compile "continue"
1412 */
1413 char_u *
1414compile_continue(char_u *arg, cctx_T *cctx)
1415{
1416 int try_scopes = 0;
1417 int loop_label;
1418
1419 if (compile_find_scope(&loop_label, NULL, &try_scopes,
1420 e_continue_without_while_or_for, cctx) == FAIL)
1421 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001422 if (try_scopes > 0)
1423 // Inside one or more try/catch blocks we first need to jump to the
1424 // "finally" or "endtry" to cleanup.
1425 generate_TRYCONT(cctx, try_scopes, loop_label);
1426 else
1427 // Jump back to the FOR or WHILE instruction.
1428 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1429
1430 return arg;
1431}
1432
1433/*
1434 * compile "break"
1435 */
1436 char_u *
1437compile_break(char_u *arg, cctx_T *cctx)
1438{
Bram Moolenaar873f8242022-03-10 21:53:44 +00001439 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001440 endlabel_T **el;
1441
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001442 if (compile_find_scope(NULL, &el, &try_scopes,
1443 e_break_without_while_or_for, cctx) == FAIL)
1444 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001445
Bram Moolenaar3f45d672023-02-27 22:06:51 +00001446 if (cctx->ctx_skip == SKIP_YES)
1447 return arg;
1448
Bram Moolenaar873f8242022-03-10 21:53:44 +00001449 if (try_scopes > 0)
1450 // Inside one or more try/catch blocks we first need to jump to the
1451 // "finally" or "endtry" to cleanup. Then come to the next JUMP
dundargocc57b5bc2022-11-02 13:30:51 +00001452 // instruction, which we don't know the index of yet.
Bram Moolenaar873f8242022-03-10 21:53:44 +00001453 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1454
1455 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1456 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001457 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaar3f45d672023-02-27 22:06:51 +00001458 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001459
1460 return arg;
1461}
1462
1463/*
1464 * compile "{" start of block
1465 */
1466 char_u *
1467compile_block(char_u *arg, cctx_T *cctx)
1468{
1469 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1470 return NULL;
1471 return skipwhite(arg + 1);
1472}
1473
1474/*
1475 * compile end of block: drop one scope
1476 */
1477 void
1478compile_endblock(cctx_T *cctx)
1479{
1480 scope_T *scope = cctx->ctx_scope;
1481
1482 cctx->ctx_scope = scope->se_outer;
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001483 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001484 vim_free(scope);
1485}
1486
1487/*
1488 * Compile "try".
1489 * Creates a new scope for the try-endtry, pointing to the first catch and
1490 * finally.
1491 * Creates another scope for the "try" block itself.
1492 * TRY instruction sets up exception handling at runtime.
1493 *
1494 * "try"
1495 * TRY -> catch1, -> finally push trystack entry
1496 * ... try block
1497 * "throw {exception}"
1498 * EVAL {exception}
1499 * THROW create exception
1500 * ... try block
1501 * " catch {expr}"
1502 * JUMP -> finally
1503 * catch1: PUSH exception
1504 * EVAL {expr}
1505 * MATCH
1506 * JUMP nomatch -> catch2
1507 * CATCH remove exception
1508 * ... catch block
1509 * " catch"
1510 * JUMP -> finally
1511 * catch2: CATCH remove exception
1512 * ... catch block
1513 * " finally"
1514 * finally:
1515 * ... finally block
1516 * " endtry"
1517 * ENDTRY pop trystack entry, may rethrow
1518 */
1519 char_u *
1520compile_try(char_u *arg, cctx_T *cctx)
1521{
1522 garray_T *instr = &cctx->ctx_instr;
1523 scope_T *try_scope;
1524 scope_T *scope;
1525
1526 if (misplaced_cmdmod(cctx))
1527 return NULL;
1528
1529 // scope that holds the jumps that go to catch/finally/endtry
1530 try_scope = new_scope(cctx, TRY_SCOPE);
1531 if (try_scope == NULL)
1532 return NULL;
1533
1534 if (cctx->ctx_skip != SKIP_YES)
1535 {
1536 isn_T *isn;
1537
1538 // "try_catch" is set when the first ":catch" is found or when no catch
1539 // is found and ":finally" is found.
1540 // "try_finally" is set when ":finally" is found
1541 // "try_endtry" is set when ":endtry" is found
1542 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1543 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1544 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001545 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1546 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001547 return NULL;
1548 }
1549
1550 // scope for the try block itself
1551 scope = new_scope(cctx, BLOCK_SCOPE);
1552 if (scope == NULL)
1553 return NULL;
1554
1555 return arg;
1556}
1557
1558/*
1559 * Compile "catch {expr}".
1560 */
1561 char_u *
1562compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1563{
1564 scope_T *scope = cctx->ctx_scope;
1565 garray_T *instr = &cctx->ctx_instr;
1566 char_u *p;
1567 isn_T *isn;
1568
1569 if (misplaced_cmdmod(cctx))
1570 return NULL;
1571
1572 // end block scope from :try or :catch
1573 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1574 compile_endblock(cctx);
1575 scope = cctx->ctx_scope;
1576
1577 // Error if not in a :try scope
1578 if (scope == NULL || scope->se_type != TRY_SCOPE)
1579 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001580 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001581 return NULL;
1582 }
1583
Bram Moolenaar9d383f32023-05-14 21:38:12 +01001584 if (scope->se_u.se_try.ts_caught_all
1585 && !ignore_unreachable_code_for_testing)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001586 {
1587 emsg(_(e_catch_unreachable_after_catch_all));
1588 return NULL;
1589 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001590 if (!cctx->ctx_had_return)
1591 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001592
1593 if (cctx->ctx_skip != SKIP_YES)
1594 {
1595#ifdef FEAT_PROFILE
1596 // the profile-start should be after the jump
1597 if (cctx->ctx_compile_type == CT_PROFILE
1598 && instr->ga_len > 0
1599 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1600 .isn_type == ISN_PROF_START)
1601 --instr->ga_len;
1602#endif
1603 // Jump from end of previous block to :finally or :endtry
1604 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001605 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001606 return NULL;
1607
1608 // End :try or :catch scope: set value in ISN_TRY instruction
1609 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001610 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1611 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001612 if (scope->se_u.se_try.ts_catch_label != 0)
1613 {
1614 // Previous catch without match jumps here
1615 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1616 isn->isn_arg.jump.jump_where = instr->ga_len;
1617 }
1618#ifdef FEAT_PROFILE
1619 if (cctx->ctx_compile_type == CT_PROFILE)
1620 {
1621 // a "throw" that jumps here needs to be counted
1622 generate_instr(cctx, ISN_PROF_END);
1623 // the "catch" is also counted
1624 generate_instr(cctx, ISN_PROF_START);
1625 }
1626#endif
1627 if (cctx->ctx_compile_type == CT_DEBUG)
1628 generate_instr_debug(cctx);
1629 }
1630
1631 p = skipwhite(arg);
1632 if (ends_excmd2(arg, p))
1633 {
1634 scope->se_u.se_try.ts_caught_all = TRUE;
1635 scope->se_u.se_try.ts_catch_label = 0;
1636 }
1637 else
1638 {
1639 char_u *end;
1640 char_u *pat;
1641 char_u *tofree = NULL;
1642 int dropped = 0;
1643 int len;
1644
1645 // Push v:exception, push {expr} and MATCH
1646 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1647
1648 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1649 if (*end != *p)
1650 {
1651 semsg(_(e_separator_mismatch_str), p);
1652 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001653 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001654 }
1655 if (tofree == NULL)
1656 len = (int)(end - (p + 1));
1657 else
1658 len = (int)(end - tofree);
1659 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1660 vim_free(tofree);
1661 p += len + 2 + dropped;
1662 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001663 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001664 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001665 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001666
1667 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1668 return NULL;
1669
1670 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1671 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1672 return NULL;
1673 }
1674
1675 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1676 return NULL;
1677
1678 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1679 return NULL;
1680 return p;
1681}
1682
1683 char_u *
1684compile_finally(char_u *arg, cctx_T *cctx)
1685{
1686 scope_T *scope = cctx->ctx_scope;
1687 garray_T *instr = &cctx->ctx_instr;
1688 isn_T *isn;
1689 int this_instr;
1690
1691 if (misplaced_cmdmod(cctx))
1692 return NULL;
1693
1694 // end block scope from :try or :catch
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 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001702 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001703 return NULL;
1704 }
1705
1706 if (cctx->ctx_skip != SKIP_YES)
1707 {
1708 // End :catch or :finally scope: set value in ISN_TRY instruction
1709 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001710 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001711 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001712 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001713 return NULL;
1714 }
1715
1716 this_instr = instr->ga_len;
1717#ifdef FEAT_PROFILE
1718 if (cctx->ctx_compile_type == CT_PROFILE
1719 && ((isn_T *)instr->ga_data)[this_instr - 1]
1720 .isn_type == ISN_PROF_START)
1721 {
1722 // jump to the profile start of the "finally"
1723 --this_instr;
1724
1725 // jump to the profile end above it
1726 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1727 .isn_type == ISN_PROF_END)
1728 --this_instr;
1729 }
1730#endif
1731
1732 // Fill in the "end" label in jumps at the end of the blocks.
1733 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1734 this_instr, cctx);
1735
1736 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001737 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1738 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1739 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001740 if (scope->se_u.se_try.ts_catch_label != 0)
1741 {
1742 // Previous catch without match jumps here
1743 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1744 isn->isn_arg.jump.jump_where = this_instr;
1745 scope->se_u.se_try.ts_catch_label = 0;
1746 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001747 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001748 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1749 return NULL;
1750 }
1751
1752 return arg;
1753}
1754
1755 char_u *
1756compile_endtry(char_u *arg, cctx_T *cctx)
1757{
1758 scope_T *scope = cctx->ctx_scope;
1759 garray_T *instr = &cctx->ctx_instr;
1760 isn_T *try_isn;
1761
1762 if (misplaced_cmdmod(cctx))
1763 return NULL;
1764
1765 // end block scope from :catch or :finally
1766 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1767 compile_endblock(cctx);
1768 scope = cctx->ctx_scope;
1769
1770 // Error if not in a :try scope
1771 if (scope == NULL || scope->se_type != TRY_SCOPE)
1772 {
1773 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001774 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001775 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001776 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001777 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001778 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001779 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001780 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001781 return NULL;
1782 }
1783
1784 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1785 if (cctx->ctx_skip != SKIP_YES)
1786 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001787 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1788 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001789 {
1790 emsg(_(e_missing_catch_or_finally));
1791 return NULL;
1792 }
1793
1794#ifdef FEAT_PROFILE
1795 if (cctx->ctx_compile_type == CT_PROFILE
1796 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1797 .isn_type == ISN_PROF_START)
1798 // move the profile start after "endtry" so that it's not counted when
1799 // the exception is rethrown.
1800 --instr->ga_len;
1801#endif
1802
1803 // Fill in the "end" label in jumps at the end of the blocks, if not
1804 // done by ":finally".
1805 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1806 instr->ga_len, cctx);
1807
1808 if (scope->se_u.se_try.ts_catch_label != 0)
1809 {
1810 // Last catch without match jumps here
1811 isn_T *isn = ((isn_T *)instr->ga_data)
1812 + scope->se_u.se_try.ts_catch_label;
1813 isn->isn_arg.jump.jump_where = instr->ga_len;
1814 }
1815 }
1816
Bram Moolenaar53c29612022-01-12 16:18:18 +00001817 // If there is a finally clause that ends in return then we will return.
1818 // If one of the blocks didn't end in "return" or we did not catch all
1819 // exceptions reset the had_return flag.
1820 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1821 && (scope->se_u.se_try.ts_no_return
1822 || !scope->se_u.se_try.ts_caught_all))
1823 cctx->ctx_had_return = FALSE;
1824
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001825 compile_endblock(cctx);
1826
1827 if (cctx->ctx_skip != SKIP_YES)
1828 {
1829 // End :catch or :finally scope: set instruction index in ISN_TRY
1830 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001831 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001832 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001833 return NULL;
1834#ifdef FEAT_PROFILE
1835 if (cctx->ctx_compile_type == CT_PROFILE)
1836 generate_instr(cctx, ISN_PROF_START);
1837#endif
1838 }
1839 return arg;
1840}
1841
1842/*
1843 * compile "throw {expr}"
1844 */
1845 char_u *
1846compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1847{
1848 char_u *p = skipwhite(arg);
1849
1850 if (compile_expr0(&p, cctx) == FAIL)
1851 return NULL;
1852 if (cctx->ctx_skip == SKIP_YES)
1853 return p;
1854 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1855 return NULL;
1856 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1857 return NULL;
1858
1859 return p;
1860}
1861
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001862/*
1863 * Compile an expression or function call.
1864 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001865 char_u *
1866compile_eval(char_u *arg, cctx_T *cctx)
1867{
1868 char_u *p = arg;
1869 int name_only;
1870 long lnum = SOURCING_LNUM;
1871
1872 // find_ex_command() will consider a variable name an expression, assuming
1873 // that something follows on the next line. Check that something actually
1874 // follows, otherwise it's probably a misplaced command.
1875 name_only = cmd_is_name_only(arg);
1876
1877 if (compile_expr0(&p, cctx) == FAIL)
1878 return NULL;
1879
1880 if (name_only && lnum == SOURCING_LNUM)
1881 {
1882 semsg(_(e_expression_without_effect_str), arg);
1883 return NULL;
1884 }
1885
1886 // drop the result
1887 generate_instr_drop(cctx, ISN_DROP, 1);
1888
1889 return skipwhite(p);
1890}
1891
1892/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001893 * Get the local variable index for deferred function calls.
1894 * Reserve it when not done already.
1895 * Returns zero for failure.
1896 */
1897 int
1898get_defer_var_idx(cctx_T *cctx)
1899{
1900 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1901 + cctx->ctx_ufunc->uf_dfunc_idx;
1902 if (dfunc->df_defer_var_idx == 0)
1903 {
1904 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1905 TRUE, &t_list_any);
1906 if (lvar == NULL)
1907 return 0;
1908 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1909 }
1910 return dfunc->df_defer_var_idx;
1911}
1912
1913/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001914 * Compile "defer func(arg)".
1915 */
1916 char_u *
1917compile_defer(char_u *arg_start, cctx_T *cctx)
1918{
Bram Moolenaar16900322022-09-08 19:51:45 +01001919 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001920 char_u *arg = arg_start;
1921 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001922 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001923 type_T *type;
1924 int func_idx;
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001925 int obj_method = 0;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001926
1927 // Get a funcref for the function name.
1928 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01001929 paren = vim_strchr(arg, '(');
1930 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001931 {
1932 semsg(_(e_missing_parenthesis_str), arg);
1933 return NULL;
1934 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001935 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001936 func_idx = find_internal_func(arg);
1937 if (func_idx >= 0)
1938 // TODO: better type
1939 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1940 &t_func_any, FALSE);
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001941 else
1942 {
1943 int typecount = cctx->ctx_type_stack.ga_len;
1944 if (compile_expr0(&arg, cctx) == FAIL)
1945 return NULL;
1946 if (cctx->ctx_type_stack.ga_len >= typecount + 2)
1947 // must have seen "obj.Func", pushed an object and a function
1948 obj_method = 1;
1949 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001950 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001951
1952 // check for function type
1953 type = get_type_on_stack(cctx, 0);
1954 if (type->tt_type != VAR_FUNC)
1955 {
1956 emsg(_(e_function_name_required));
1957 return NULL;
1958 }
1959
1960 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01001961 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001962 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1963 return NULL;
1964
Bram Moolenaar16900322022-09-08 19:51:45 +01001965 if (func_idx >= 0)
1966 {
1967 type2_T *argtypes = NULL;
1968 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1969
1970 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
1971 &argtypes, shuffled_argtypes) == FAIL)
1972 return NULL;
1973 }
1974 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
1975 arg_start) == FAIL)
1976 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001977
Bram Moolenaar806a2732022-09-04 15:40:36 +01001978 defer_var_idx = get_defer_var_idx(cctx);
1979 if (defer_var_idx == 0)
1980 return NULL;
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001981 if (generate_DEFER(cctx, defer_var_idx - 1, obj_method, argcount) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001982 return NULL;
1983
1984 return skipwhite(arg);
1985}
1986
1987/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001988 * compile "echo expr"
1989 * compile "echomsg expr"
1990 * compile "echoerr expr"
1991 * compile "echoconsole expr"
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01001992 * compile "echowindow expr" - may have cmd_count set
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001993 * compile "execute expr"
1994 */
1995 char_u *
Bram Moolenaar9b994112022-12-25 15:59:25 +00001996compile_mult_expr(
1997 char_u *arg,
1998 int cmdidx,
1999 long cmd_count UNUSED,
2000 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002001{
2002 char_u *p = arg;
2003 char_u *prev = arg;
2004 char_u *expr_start;
2005 int count = 0;
2006 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002007 type_T *type;
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002008 int r = OK;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002009
2010 for (;;)
2011 {
2012 if (ends_excmd2(prev, p))
2013 break;
2014 expr_start = p;
2015 if (compile_expr0(&p, cctx) == FAIL)
2016 return NULL;
2017
2018 if (cctx->ctx_skip != SKIP_YES)
2019 {
2020 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00002021 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002022 if (type->tt_type == VAR_VOID)
2023 {
2024 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
2025 return NULL;
2026 }
2027 }
2028
2029 ++count;
2030 prev = p;
2031 p = skipwhite(p);
2032 }
2033
2034 if (count > 0)
2035 {
2036 long save_lnum = cctx->ctx_lnum;
2037
2038 // Use the line number where the command started.
2039 cctx->ctx_lnum = start_ctx_lnum;
2040
2041 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002042 r = generate_ECHO(cctx, cmdidx == CMD_echo, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002043 else if (cmdidx == CMD_execute)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002044 r = generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002045 else if (cmdidx == CMD_echomsg)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002046 r = generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002047#ifdef HAS_MESSAGE_WINDOW
2048 else if (cmdidx == CMD_echowindow)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002049 r = generate_ECHOWINDOW(cctx, count, cmd_count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002050#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002051 else if (cmdidx == CMD_echoconsole)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002052 r = generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002053 else
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002054 r = generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002055
2056 cctx->ctx_lnum = save_lnum;
2057 }
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002058 return r == OK ? p : NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002059}
2060
2061/*
2062 * If "eap" has a range that is not a constant generate an ISN_RANGE
2063 * instruction to compute it and return OK.
2064 * Otherwise return FAIL, the caller must deal with any range.
2065 */
2066 static int
2067compile_variable_range(exarg_T *eap, cctx_T *cctx)
2068{
2069 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
2070 char_u *p = skipdigits(eap->cmd);
2071
2072 if (p == range_end)
2073 return FAIL;
2074 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
2075}
2076
2077/*
2078 * :put r
2079 * :put ={expr}
2080 */
2081 char_u *
2082compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
2083{
2084 char_u *line = arg;
2085 linenr_T lnum;
2086 char *errormsg;
2087 int above = eap->forceit;
2088
2089 eap->regname = *line;
2090
2091 if (eap->regname == '=')
2092 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002093 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002094
2095 if (compile_expr0(&p, cctx) == FAIL)
2096 return NULL;
2097 line = p;
2098 }
2099 else if (eap->regname != NUL)
2100 ++line;
2101
2102 if (compile_variable_range(eap, cctx) == OK)
2103 {
2104 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2105 }
2106 else
2107 {
2108 // Either no range or a number.
2109 // "errormsg" will not be set because the range is ADDR_LINES.
2110 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2111 // cannot happen
2112 return NULL;
2113 if (eap->addr_count == 0)
2114 lnum = -1;
2115 else
2116 lnum = eap->line2;
2117 if (above)
2118 --lnum;
2119 }
2120
2121 generate_PUT(cctx, eap->regname, lnum);
2122 return line;
2123}
2124
2125/*
2126 * A command that is not compiled, execute with legacy code.
2127 */
2128 char_u *
2129compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2130{
2131 char_u *line = line_arg;
2132 char_u *p;
2133 int has_expr = FALSE;
2134 char_u *nextcmd = (char_u *)"";
2135 char_u *tofree = NULL;
2136 char_u *cmd_arg = NULL;
2137
2138 if (cctx->ctx_skip == SKIP_YES)
2139 goto theend;
2140
2141 // If there was a prececing command modifier, drop it and include it in the
2142 // EXEC command.
2143 if (cctx->ctx_has_cmdmod)
2144 {
2145 garray_T *instr = &cctx->ctx_instr;
2146 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2147
2148 if (isn->isn_type == ISN_CMDMOD)
2149 {
2150 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2151 ->cmod_filter_regmatch.regprog);
2152 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2153 --instr->ga_len;
2154 cctx->ctx_has_cmdmod = FALSE;
2155 }
2156 }
2157
2158 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2159 {
2160 long argt = eap->argt;
2161 int usefilter = FALSE;
2162
2163 has_expr = argt & (EX_XFILE | EX_EXPAND);
2164
2165 // If the command can be followed by a bar, find the bar and truncate
2166 // it, so that the following command can be compiled.
2167 // The '|' is overwritten with a NUL, it is put back below.
2168 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2169 && *eap->arg == '!')
2170 // :w !filter or :r !filter or :r! filter
2171 usefilter = TRUE;
2172 if ((argt & EX_TRLBAR) && !usefilter)
2173 {
2174 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002175 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002176 if (eap->nextcmd != NULL)
2177 nextcmd = eap->nextcmd;
2178 }
2179 else if (eap->cmdidx == CMD_wincmd)
2180 {
2181 p = eap->arg;
2182 if (*p != NUL)
2183 ++p;
2184 if (*p == 'g' || *p == Ctrl_G)
2185 ++p;
2186 p = skipwhite(p);
2187 if (*p == '|')
2188 {
2189 *p = NUL;
2190 nextcmd = p + 1;
2191 }
2192 }
2193 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2194 {
2195 // If there is a trailing '{' read lines until the '}'
2196 p = eap->arg + STRLEN(eap->arg) - 1;
2197 while (p > eap->arg && VIM_ISWHITE(*p))
2198 --p;
2199 if (*p == '{')
2200 {
2201 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002202 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002203 int start_lnum = SOURCING_LNUM;
2204
2205 CLEAR_FIELD(ea);
2206 ea.arg = eap->arg;
2207 fill_exarg_from_cctx(&ea, cctx);
2208 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2209 if (tofree != NULL)
2210 {
2211 *p = NUL;
2212 line = concat_str(line, tofree);
2213 if (line == NULL)
2214 goto theend;
2215 vim_free(tofree);
2216 tofree = line;
2217 SOURCING_LNUM = start_lnum;
2218 }
2219 }
2220 }
2221 }
2222
2223 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2224 {
2225 // expand filename in "syntax include [@group] filename"
2226 has_expr = TRUE;
2227 eap->arg = skipwhite(eap->arg + 7);
2228 if (*eap->arg == '@')
2229 eap->arg = skiptowhite(eap->arg);
2230 }
2231
2232 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2233 && STRLEN(eap->arg) > 4)
2234 {
2235 int delim = *eap->arg;
2236
2237 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2238 if (*p == delim)
2239 cmd_arg = p + 1;
2240 }
2241
2242 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2243 cmd_arg = eap->arg;
2244
2245 if (cmd_arg != NULL)
2246 {
2247 exarg_T nea;
2248
2249 CLEAR_FIELD(nea);
2250 nea.cmd = cmd_arg;
2251 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2252 if (nea.cmdidx < CMD_SIZE)
2253 {
2254 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2255 if (has_expr)
2256 eap->arg = skiptowhite(eap->arg);
2257 }
2258 }
2259
2260 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2261 {
2262 int count = 0;
2263 char_u *start = skipwhite(line);
2264
2265 // :cmd xxx`=expr1`yyy`=expr2`zzz
2266 // PUSHS ":cmd xxx"
2267 // eval expr1
2268 // PUSHS "yyy"
2269 // eval expr2
2270 // PUSHS "zzz"
2271 // EXECCONCAT 5
2272 for (;;)
2273 {
2274 if (p > start)
2275 {
2276 char_u *val = vim_strnsave(start, p - start);
2277
2278 generate_PUSHS(cctx, &val);
2279 ++count;
2280 }
2281 p += 2;
2282 if (compile_expr0(&p, cctx) == FAIL)
2283 return NULL;
2284 may_generate_2STRING(-1, TRUE, cctx);
2285 ++count;
2286 p = skipwhite(p);
2287 if (*p != '`')
2288 {
2289 emsg(_(e_missing_backtick));
2290 return NULL;
2291 }
2292 start = p + 1;
2293
2294 p = (char_u *)strstr((char *)start, "`=");
2295 if (p == NULL)
2296 {
2297 if (*skipwhite(start) != NUL)
2298 {
2299 char_u *val = vim_strsave(start);
2300
2301 generate_PUSHS(cctx, &val);
2302 ++count;
2303 }
2304 break;
2305 }
2306 }
2307 generate_EXECCONCAT(cctx, count);
2308 }
2309 else
2310 generate_EXEC_copy(cctx, ISN_EXEC, line);
2311
2312theend:
2313 if (*nextcmd != NUL)
2314 {
2315 // the parser expects a pointer to the bar, put it back
2316 --nextcmd;
2317 *nextcmd = '|';
2318 }
2319 vim_free(tofree);
2320
2321 return nextcmd;
2322}
2323
2324/*
2325 * A script command with heredoc, e.g.
2326 * ruby << EOF
2327 * command
2328 * EOF
2329 * Has been turned into one long line with NL characters by
2330 * get_function_body():
2331 * ruby << EOF<NL> command<NL>EOF
2332 */
2333 char_u *
2334compile_script(char_u *line, cctx_T *cctx)
2335{
2336 if (cctx->ctx_skip != SKIP_YES)
2337 {
2338 isn_T *isn;
2339
2340 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2341 return NULL;
2342 isn->isn_arg.string = vim_strsave(line);
2343 }
2344 return (char_u *)"";
2345}
2346
2347
2348/*
2349 * :s/pat/repl/
2350 */
2351 char_u *
2352compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2353{
2354 char_u *cmd = eap->arg;
2355 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2356
2357 if (expr != NULL)
2358 {
2359 int delimiter = *cmd++;
2360
2361 // There is a \=expr, find it in the substitute part.
2362 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2363 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2364 {
2365 garray_T save_ga = cctx->ctx_instr;
2366 char_u *end;
2367 int expr_res;
2368 int trailing_error;
2369 int instr_count;
2370 isn_T *instr;
2371 isn_T *isn;
2372
2373 cmd += 3;
2374 end = skip_substitute(cmd, delimiter);
2375
2376 // Temporarily reset the list of instructions so that the jump
2377 // labels are correct.
2378 cctx->ctx_instr.ga_len = 0;
2379 cctx->ctx_instr.ga_maxlen = 0;
2380 cctx->ctx_instr.ga_data = NULL;
2381 expr_res = compile_expr0(&cmd, cctx);
2382 if (end[-1] == NUL)
2383 end[-1] = delimiter;
2384 cmd = skipwhite(cmd);
2385 trailing_error = *cmd != delimiter && *cmd != NUL;
2386
2387 if (expr_res == FAIL || trailing_error
2388 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2389 {
2390 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002391 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002392 clear_instr_ga(&cctx->ctx_instr);
2393 cctx->ctx_instr = save_ga;
2394 return NULL;
2395 }
2396
2397 // Move the generated instructions into the ISN_SUBSTITUTE
2398 // instructions, then restore the list of instructions before
2399 // adding the ISN_SUBSTITUTE instruction.
2400 instr_count = cctx->ctx_instr.ga_len;
2401 instr = cctx->ctx_instr.ga_data;
2402 instr[instr_count].isn_type = ISN_FINISH;
2403
2404 cctx->ctx_instr = save_ga;
2405 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2406 {
2407 int idx;
2408
2409 for (idx = 0; idx < instr_count; ++idx)
2410 delete_instr(instr + idx);
2411 vim_free(instr);
2412 return NULL;
2413 }
2414 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2415 isn->isn_arg.subs.subs_instr = instr;
2416
2417 // skip over flags
2418 if (*end == '&')
2419 ++end;
2420 while (ASCII_ISALPHA(*end) || *end == '#')
2421 ++end;
2422 return end;
2423 }
2424 }
2425
2426 return compile_exec(arg, eap, cctx);
2427}
2428
2429 char_u *
2430compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2431{
2432 char_u *arg = eap->arg;
2433 lhs_T *lhs = &cctx->ctx_redir_lhs;
2434
2435 if (lhs->lhs_name != NULL)
2436 {
2437 if (STRNCMP(arg, "END", 3) == 0)
2438 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002439 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002440 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002441 if (lhs->lhs_append)
2442 {
2443 // First load the current variable value.
2444 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002445 cctx) == FAIL)
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002446 return NULL;
2447 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002448
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002449 // Gets the redirected text and put it on the stack, then store
2450 // it in the variable.
2451 generate_instr_type(cctx, ISN_REDIREND, &t_string);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002452
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002453 if (lhs->lhs_append)
2454 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002455
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002456 if (lhs->lhs_has_index)
2457 {
2458 // Use the info in "lhs" to store the value at the index in
2459 // the list or dict.
2460 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002461 &t_string, cctx) == FAIL)
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002462 return NULL;
2463 }
2464 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002465 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002466
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002467 VIM_CLEAR(lhs->lhs_name);
2468 VIM_CLEAR(lhs->lhs_whole);
2469 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002470 return arg + 3;
2471 }
2472 emsg(_(e_cannot_nest_redir));
2473 return NULL;
2474 }
2475
2476 if (arg[0] == '=' && arg[1] == '>')
2477 {
2478 int append = FALSE;
2479
2480 // redirect to a variable is compiled
2481 arg += 2;
2482 if (*arg == '>')
2483 {
2484 ++arg;
2485 append = TRUE;
2486 }
2487 arg = skipwhite(arg);
2488
2489 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002490 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002491 return NULL;
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002492 if (need_type(&t_string, lhs->lhs_member_type, FALSE,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002493 -1, 0, cctx, FALSE, FALSE) == FAIL)
2494 return NULL;
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002495 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002496 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002497 VIM_CLEAR(lhs->lhs_name);
2498 }
2499 else
2500 {
2501 generate_instr(cctx, ISN_REDIRSTART);
2502 lhs->lhs_append = append;
2503 if (lhs->lhs_has_index)
2504 {
2505 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2506 if (lhs->lhs_whole == NULL)
2507 return NULL;
2508 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002509 }
2510
2511 return arg + lhs->lhs_varlen_total;
2512 }
2513
2514 // other redirects are handled like at script level
2515 return compile_exec(line, eap, cctx);
2516}
2517
2518#if defined(FEAT_QUICKFIX) || defined(PROTO)
2519 char_u *
2520compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2521{
2522 isn_T *isn;
2523 char_u *p;
2524
2525 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2526 if (isn == NULL)
2527 return NULL;
2528 isn->isn_arg.number = eap->cmdidx;
2529
2530 p = eap->arg;
2531 if (compile_expr0(&p, cctx) == FAIL)
2532 return NULL;
2533
2534 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2535 if (isn == NULL)
2536 return NULL;
2537 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2538 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2539 return NULL;
2540 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2541 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2542 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2543
2544 return p;
2545}
2546#endif
2547
2548/*
2549 * Compile "return [expr]".
2550 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2551 */
2552 char_u *
2553compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2554{
2555 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002556 type_T *stack_type;
2557
mityu500c4442022-12-02 18:12:05 +00002558 if (*p != NUL && *p != '|' && *p != '\n'
2559 && (legacy || !vim9_comment_start(p)))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002560 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002561 // For a lambda, "return expr" is always used, also when "expr" results
2562 // in a void.
2563 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2564 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002565 {
2566 emsg(_(e_returning_value_in_function_without_return_type));
2567 return NULL;
2568 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002569 if (legacy)
2570 {
2571 int save_flags = cmdmod.cmod_flags;
2572
2573 generate_LEGACY_EVAL(cctx, p);
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002574 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, FALSE, -1,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002575 0, cctx, FALSE, FALSE) == FAIL)
2576 return NULL;
2577 cmdmod.cmod_flags |= CMOD_LEGACY;
2578 (void)skip_expr(&p, NULL);
2579 cmdmod.cmod_flags = save_flags;
2580 }
2581 else
2582 {
2583 // compile return argument into instructions
2584 if (compile_expr0(&p, cctx) == FAIL)
2585 return NULL;
2586 }
2587
2588 if (cctx->ctx_skip != SKIP_YES)
2589 {
2590 // "check_return_type" with uf_ret_type set to &t_unknown is used
2591 // for an inline function without a specified return type. Set the
2592 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002593 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002594 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002595 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002596 || (!check_return_type
2597 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2598 {
2599 cctx->ctx_ufunc->uf_ret_type = stack_type;
2600 }
2601 else
2602 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002603 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, FALSE,
2604 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002605 return NULL;
2606 }
2607 }
2608 }
2609 else
2610 {
2611 // "check_return_type" cannot be TRUE, only used for a lambda which
2612 // always has an argument.
2613 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2614 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2615 {
2616 emsg(_(e_missing_return_value));
2617 return NULL;
2618 }
2619
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002620 if (cctx->ctx_ufunc->uf_flags & FC_NEW)
2621 {
2622 // For a class new() constructor, return an object of the class.
2623 generate_instr(cctx, ISN_RETURN_OBJECT);
2624 cctx->ctx_ufunc->uf_ret_type =
2625 &cctx->ctx_ufunc->uf_class->class_object_type;
2626 }
2627 else
2628 // No argument, return zero.
2629 generate_PUSHNR(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002630 }
2631
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002632 // may need ENDLOOP when inside a :for or :while loop
2633 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2634
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002635 // Undo any command modifiers.
2636 generate_undo_cmdmods(cctx);
2637
2638 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2639 return NULL;
2640
2641 // "return val | endif" is possible
2642 return skipwhite(p);
2643}
2644
2645/*
2646 * Check if the separator for a :global or :substitute command is OK.
2647 */
2648 int
2649check_global_and_subst(char_u *cmd, char_u *arg)
2650{
2651 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2652 {
2653 semsg(_(e_separator_not_supported_str), arg);
2654 return FAIL;
2655 }
2656 if (VIM_ISWHITE(cmd[1]))
2657 {
2658 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2659 return FAIL;
2660 }
2661 return OK;
2662}
2663
2664
2665#endif // defined(FEAT_EVAL)