blob: 0d6dc01f9f46b39040ed1dbfef416065c0aa3862 [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;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000192 char_u *buf;
193 isntype_T isn = ISN_EXEC;
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100194 char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
Ernie Raelee865f32023-09-29 19:53:55 +0200195 int is_arg = FALSE;
196
197#ifdef LOG_LOCKVAR
198 ch_log(NULL, "LKVAR: compile_lock_unlock(): cookie %p, name %s",
199 coookie, p);
200#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000201
202 if (cctx->ctx_skip == SKIP_YES)
203 return OK;
204
Bram Moolenaard1d8f6b2022-08-14 21:28:32 +0100205 if (*p == NUL)
206 {
207 semsg(_(e_argument_required_for_str), cmd);
208 return FAIL;
209 }
210
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000211 // Cannot use :lockvar and :unlockvar on local variables.
212 if (p[1] != ':')
213 {
214 char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
Ernie Raelee865f32023-09-29 19:53:55 +0200215 // If name is is locally accessible, except for local var,
216 // then put it on the stack to use with ISN_LOCKUNLOCK.
217 // This could be v.memb, v[idx_key]; bare class variable,
218 // function arg. The local variable on the stack, will be passed
219 // to ex_lockvar() indirectly.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000220
Ernie Raelee865f32023-09-29 19:53:55 +0200221 char_u *name = NULL;
222 int len = end - p;
223
224 if (lookup_local(p, len, NULL, cctx) == OK)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000225 {
Ernie Raelee865f32023-09-29 19:53:55 +0200226 // Handle "this", "this.val", "anyvar[idx]"
227 if (*end != '.' && *end != '['
228 && (len != 4 || STRNCMP("this", p, len) != 0))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000229 {
230 emsg(_(e_cannot_lock_unlock_local_variable));
231 return FAIL;
232 }
Ernie Raelee865f32023-09-29 19:53:55 +0200233 // Push the local on the stack, could be "this".
234 name = p;
235#ifdef LOG_LOCKVAR
236 ch_log(NULL, "LKVAR: compile... lookup_local: name %s", name);
237#endif
238 }
239 if (name == NULL)
240 {
241 class_T *cl;
242 if (cctx_class_member_idx(cctx, p, len, &cl) >= 0)
243 {
244 if (*end != '.' && *end != '[')
245 {
246 // Push the class of the bare class variable name
247 name = cl->class_name;
248 len = STRLEN(name);
249#ifdef LOG_LOCKVAR
250 ch_log(NULL, "LKVAR: compile... cctx_class_member: name %s",
251 name);
252#endif
253 }
254 }
255 }
256 if (name == NULL)
257 {
258 int idx;
259 type_T *type;
260 // Can lockvar any function arg.
261 // TODO: test arg[idx]/arg.member
262 if (arg_exists(p, len, &idx, &type, NULL, cctx) == OK)
263 {
264 name = p;
265 is_arg = TRUE;
266#ifdef LOG_LOCKVAR
267 ch_log(NULL, "LKVAR: compile... arg_exists: name %s", name);
268#endif
269 }
270 }
271 if (name != NULL)
272 {
273#ifdef LOG_LOCKVAR
274 ch_log(NULL, "LKVAR: compile... INS_LOCKUNLOCK %s", name);
275#endif
276 if (compile_load(&name, name + len, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000277 return FAIL;
278 isn = ISN_LOCKUNLOCK;
279 }
280 }
281
282 // Checking is done at runtime.
283 *name_end = NUL;
Ernie Raelee865f32023-09-29 19:53:55 +0200284 size_t len = name_end - p + 20;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000285 buf = alloc(len);
286 if (buf == NULL)
287 ret = FAIL;
288 else
289 {
Bram Moolenaare939f5e2022-01-26 21:32:59 +0000290 if (deep < 0)
291 vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
292 else
293 vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
Ernie Raelee865f32023-09-29 19:53:55 +0200294#ifdef LOG_LOCKVAR
295 ch_log(NULL, "LKVAR: compile... buf %s", buf);
296#endif
297 if (isn == ISN_LOCKUNLOCK)
298 ret = generate_LOCKUNLOCK(cctx, buf, is_arg);
299 else
300 ret = generate_EXEC_copy(cctx, isn, buf);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000301
302 vim_free(buf);
303 *name_end = cc;
304 }
305 return ret;
306}
307
308/*
309 * compile "unlet var", "lock var" and "unlock var"
310 * "arg" points to "var".
311 */
312 char_u *
313compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
314{
Bram Moolenaar70c43d82022-01-26 21:01:15 +0000315 int deep = 0;
316 char_u *p = arg;
317
318 if (eap->cmdidx != CMD_unlet)
319 {
320 if (eap->forceit)
321 deep = -1;
322 else if (vim_isdigit(*p))
323 {
324 deep = getdigits(&p);
325 p = skipwhite(p);
326 }
327 else
328 deep = 2;
329 }
330
331 ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000332 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
333 cctx);
334 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
335}
336
337/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100338 * Generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
339 * "funcref_idx" is used for JUMP_WHILE_FALSE
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000340 */
341 static int
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100342compile_jump_to_end(
343 endlabel_T **el,
344 jumpwhen_T when,
345 int funcref_idx,
346 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000347{
348 garray_T *instr = &cctx->ctx_instr;
349 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
350
351 if (endlabel == NULL)
352 return FAIL;
353 endlabel->el_next = *el;
354 *el = endlabel;
355 endlabel->el_end_label = instr->ga_len;
356
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100357 if (when == JUMP_WHILE_FALSE)
358 generate_WHILE(cctx, funcref_idx);
359 else
360 generate_JUMP(cctx, when, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000361 return OK;
362}
363
364 static void
365compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
366{
367 garray_T *instr = &cctx->ctx_instr;
368
369 while (*el != NULL)
370 {
371 endlabel_T *cur = (*el);
372 isn_T *isn;
373
374 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
375 isn->isn_arg.jump.jump_where = jump_where;
376 *el = cur->el_next;
377 vim_free(cur);
378 }
379}
380
381 static void
382compile_free_jump_to_end(endlabel_T **el)
383{
384 while (*el != NULL)
385 {
386 endlabel_T *cur = (*el);
387
388 *el = cur->el_next;
389 vim_free(cur);
390 }
391}
392
393/*
394 * Create a new scope and set up the generic items.
395 */
396 static scope_T *
397new_scope(cctx_T *cctx, scopetype_T type)
398{
399 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
400
401 if (scope == NULL)
402 return NULL;
403 scope->se_outer = cctx->ctx_scope;
404 cctx->ctx_scope = scope;
405 scope->se_type = type;
406 scope->se_local_count = cctx->ctx_locals.ga_len;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100407 if (scope->se_outer != NULL)
408 scope->se_loop_depth = scope->se_outer->se_loop_depth;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000409 return scope;
410}
411
412/*
413 * Free the current scope and go back to the outer scope.
414 */
415 void
416drop_scope(cctx_T *cctx)
417{
418 scope_T *scope = cctx->ctx_scope;
419
420 if (scope == NULL)
421 {
422 iemsg("calling drop_scope() without a scope");
423 return;
424 }
425 cctx->ctx_scope = scope->se_outer;
426 switch (scope->se_type)
427 {
428 case IF_SCOPE:
429 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
430 case FOR_SCOPE:
431 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
432 case WHILE_SCOPE:
433 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
434 case TRY_SCOPE:
435 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
436 case NO_SCOPE:
437 case BLOCK_SCOPE:
438 break;
439 }
440 vim_free(scope);
441}
442
443 static int
444misplaced_cmdmod(cctx_T *cctx)
445{
446 garray_T *instr = &cctx->ctx_instr;
447
448 if (cctx->ctx_has_cmdmod
449 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
450 == ISN_CMDMOD)
451 {
452 emsg(_(e_misplaced_command_modifier));
453 return TRUE;
454 }
455 return FALSE;
456}
457
458/*
459 * compile "if expr"
460 *
461 * "if expr" Produces instructions:
462 * EVAL expr Push result of "expr"
463 * JUMP_IF_FALSE end
464 * ... body ...
465 * end:
466 *
467 * "if expr | else" Produces instructions:
468 * EVAL expr Push result of "expr"
469 * JUMP_IF_FALSE else
470 * ... body ...
471 * JUMP_ALWAYS end
472 * else:
473 * ... body ...
474 * end:
475 *
476 * "if expr1 | elseif expr2 | else" Produces instructions:
477 * EVAL expr Push result of "expr"
478 * JUMP_IF_FALSE elseif
479 * ... body ...
480 * JUMP_ALWAYS end
481 * elseif:
482 * EVAL expr Push result of "expr"
483 * JUMP_IF_FALSE else
484 * ... body ...
485 * JUMP_ALWAYS end
486 * else:
487 * ... body ...
488 * end:
489 */
490 char_u *
491compile_if(char_u *arg, cctx_T *cctx)
492{
493 char_u *p = arg;
494 garray_T *instr = &cctx->ctx_instr;
495 int instr_count = instr->ga_len;
496 scope_T *scope;
497 skip_T skip_save = cctx->ctx_skip;
498 ppconst_T ppconst;
499
500 CLEAR_FIELD(ppconst);
501 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
502 {
503 clear_ppconst(&ppconst);
504 return NULL;
505 }
506 if (!ends_excmd2(arg, skipwhite(p)))
507 {
Bram Moolenaar74409f62022-01-01 15:58:22 +0000508 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000509 return NULL;
510 }
511 if (cctx->ctx_skip == SKIP_YES)
512 clear_ppconst(&ppconst);
513 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
514 {
515 int error = FALSE;
516 int v;
517
518 // The expression results in a constant.
519 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
520 clear_ppconst(&ppconst);
521 if (error)
522 return NULL;
523 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
524 }
525 else
526 {
527 // Not a constant, generate instructions for the expression.
528 cctx->ctx_skip = SKIP_UNKNOWN;
529 if (generate_ppconst(cctx, &ppconst) == FAIL)
530 return NULL;
531 if (bool_on_stack(cctx) == FAIL)
532 return NULL;
533 }
534
535 // CMDMOD_REV must come before the jump
536 generate_undo_cmdmods(cctx);
537
538 scope = new_scope(cctx, IF_SCOPE);
539 if (scope == NULL)
540 return NULL;
541 scope->se_skip_save = skip_save;
542 // "is_had_return" will be reset if any block does not end in :return
543 scope->se_u.se_if.is_had_return = TRUE;
544
545 if (cctx->ctx_skip == SKIP_UNKNOWN)
546 {
547 // "where" is set when ":elseif", "else" or ":endif" is found
548 scope->se_u.se_if.is_if_label = instr->ga_len;
549 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
550 }
551 else
552 scope->se_u.se_if.is_if_label = -1;
553
554#ifdef FEAT_PROFILE
555 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
556 && skip_save != SKIP_YES)
557 {
558 // generated a profile start, need to generate a profile end, since it
559 // won't be done after returning
560 cctx->ctx_skip = SKIP_NOT;
561 generate_instr(cctx, ISN_PROF_END);
562 cctx->ctx_skip = SKIP_YES;
563 }
564#endif
565
566 return p;
567}
568
569 char_u *
570compile_elseif(char_u *arg, cctx_T *cctx)
571{
572 char_u *p = arg;
573 garray_T *instr = &cctx->ctx_instr;
574 int instr_count;
575 isn_T *isn;
576 scope_T *scope = cctx->ctx_scope;
577 ppconst_T ppconst;
578 skip_T save_skip = cctx->ctx_skip;
579
580 if (scope == NULL || scope->se_type != IF_SCOPE)
581 {
582 emsg(_(e_elseif_without_if));
583 return NULL;
584 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100585 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000586 if (!cctx->ctx_had_return)
587 scope->se_u.se_if.is_had_return = FALSE;
588
589 if (cctx->ctx_skip == SKIP_NOT)
590 {
591 // previous block was executed, this one and following will not
592 cctx->ctx_skip = SKIP_YES;
593 scope->se_u.se_if.is_seen_skip_not = TRUE;
594 }
595 if (scope->se_u.se_if.is_seen_skip_not)
596 {
597 // A previous block was executed, skip over expression and bail out.
598 // Do not count the "elseif" for profiling and cmdmod
599 instr->ga_len = current_instr_idx(cctx);
600
601 skip_expr_cctx(&p, cctx);
602 return p;
603 }
604
605 if (cctx->ctx_skip == SKIP_UNKNOWN)
606 {
607 int moved_cmdmod = FALSE;
608 int saved_debug = FALSE;
609 isn_T debug_isn;
610
611 // Move any CMDMOD instruction to after the jump
612 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
613 {
614 if (GA_GROW_FAILS(instr, 1))
615 return NULL;
616 ((isn_T *)instr->ga_data)[instr->ga_len] =
617 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
618 --instr->ga_len;
619 moved_cmdmod = TRUE;
620 }
621
622 // Remove the already generated ISN_DEBUG, it is written below the
623 // ISN_FOR instruction.
624 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
625 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
626 .isn_type == ISN_DEBUG)
627 {
628 --instr->ga_len;
629 debug_isn = ((isn_T *)instr->ga_data)[instr->ga_len];
630 saved_debug = TRUE;
631 }
632
633 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100634 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000635 return NULL;
636 // previous "if" or "elseif" jumps here
637 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
638 isn->isn_arg.jump.jump_where = instr->ga_len;
639
640 if (moved_cmdmod)
641 ++instr->ga_len;
642
643 if (saved_debug)
644 {
645 // move the debug instruction here
646 if (GA_GROW_FAILS(instr, 1))
647 return NULL;
648 ((isn_T *)instr->ga_data)[instr->ga_len] = debug_isn;
649 ++instr->ga_len;
650 }
651 }
652
653 // compile "expr"; if we know it evaluates to FALSE skip the block
654 CLEAR_FIELD(ppconst);
655 if (cctx->ctx_skip == SKIP_YES)
656 {
657 cctx->ctx_skip = SKIP_UNKNOWN;
658#ifdef FEAT_PROFILE
659 if (cctx->ctx_compile_type == CT_PROFILE)
660 // the previous block was skipped, need to profile this line
661 generate_instr(cctx, ISN_PROF_START);
662#endif
663 if (cctx->ctx_compile_type == CT_DEBUG)
664 // the previous block was skipped, may want to debug this line
665 generate_instr_debug(cctx);
666 }
667
668 instr_count = instr->ga_len;
669 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
670 {
671 clear_ppconst(&ppconst);
672 return NULL;
673 }
674 cctx->ctx_skip = save_skip;
675 if (!ends_excmd2(arg, skipwhite(p)))
676 {
677 clear_ppconst(&ppconst);
Bram Moolenaar74409f62022-01-01 15:58:22 +0000678 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000679 return NULL;
680 }
681 if (scope->se_skip_save == SKIP_YES)
682 clear_ppconst(&ppconst);
683 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
684 {
685 int error = FALSE;
686 int v;
687
688 // The expression result is a constant.
689 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
690 if (error)
691 {
692 clear_ppconst(&ppconst);
693 return NULL;
694 }
695 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
696 clear_ppconst(&ppconst);
697 scope->se_u.se_if.is_if_label = -1;
698 }
699 else
700 {
701 // Not a constant, generate instructions for the expression.
702 cctx->ctx_skip = SKIP_UNKNOWN;
703 if (generate_ppconst(cctx, &ppconst) == FAIL)
704 return NULL;
705 if (bool_on_stack(cctx) == FAIL)
706 return NULL;
707
708 // CMDMOD_REV must come before the jump
709 generate_undo_cmdmods(cctx);
710
711 // "where" is set when ":elseif", "else" or ":endif" is found
712 scope->se_u.se_if.is_if_label = instr->ga_len;
713 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
714 }
715
716 return p;
717}
718
719 char_u *
720compile_else(char_u *arg, cctx_T *cctx)
721{
722 char_u *p = arg;
723 garray_T *instr = &cctx->ctx_instr;
724 isn_T *isn;
725 scope_T *scope = cctx->ctx_scope;
726
727 if (scope == NULL || scope->se_type != IF_SCOPE)
728 {
729 emsg(_(e_else_without_if));
730 return NULL;
731 }
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100732 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000733 if (!cctx->ctx_had_return)
734 scope->se_u.se_if.is_had_return = FALSE;
735 scope->se_u.se_if.is_seen_else = TRUE;
736
737#ifdef FEAT_PROFILE
738 if (cctx->ctx_compile_type == CT_PROFILE)
739 {
740 if (cctx->ctx_skip == SKIP_NOT
741 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
742 .isn_type == ISN_PROF_START)
743 // the previous block was executed, do not count "else" for
744 // profiling
745 --instr->ga_len;
746 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
747 {
748 // the previous block was not executed, this one will, do count the
749 // "else" for profiling
750 cctx->ctx_skip = SKIP_NOT;
751 generate_instr(cctx, ISN_PROF_END);
752 generate_instr(cctx, ISN_PROF_START);
753 cctx->ctx_skip = SKIP_YES;
754 }
755 }
756#endif
757
758 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
759 {
760 // jump from previous block to the end, unless the else block is empty
761 if (cctx->ctx_skip == SKIP_UNKNOWN)
762 {
763 if (!cctx->ctx_had_return
764 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100765 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000766 return NULL;
767 }
768
769 if (cctx->ctx_skip == SKIP_UNKNOWN)
770 {
771 if (scope->se_u.se_if.is_if_label >= 0)
772 {
773 // previous "if" or "elseif" jumps here
774 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
775 isn->isn_arg.jump.jump_where = instr->ga_len;
776 scope->se_u.se_if.is_if_label = -1;
777 }
778 }
779
780 if (cctx->ctx_skip != SKIP_UNKNOWN)
781 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
782 }
783
784 return p;
785}
786
787 char_u *
788compile_endif(char_u *arg, cctx_T *cctx)
789{
790 scope_T *scope = cctx->ctx_scope;
791 ifscope_T *ifscope;
792 garray_T *instr = &cctx->ctx_instr;
793 isn_T *isn;
794
795 if (misplaced_cmdmod(cctx))
796 return NULL;
797
798 if (scope == NULL || scope->se_type != IF_SCOPE)
799 {
800 emsg(_(e_endif_without_if));
801 return NULL;
802 }
803 ifscope = &scope->se_u.se_if;
Bram Moolenaara275f2c2022-10-11 20:04:09 +0100804 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000805 if (!cctx->ctx_had_return)
806 ifscope->is_had_return = FALSE;
807
808 if (scope->se_u.se_if.is_if_label >= 0)
809 {
810 // previous "if" or "elseif" jumps here
811 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
812 isn->isn_arg.jump.jump_where = instr->ga_len;
813 }
814 // Fill in the "end" label in jumps at the end of the blocks.
815 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
816
817#ifdef FEAT_PROFILE
818 // even when skipping we count the endif as executed, unless the block it's
819 // in is skipped
820 if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_skip == SKIP_YES
821 && scope->se_skip_save != SKIP_YES)
822 {
823 cctx->ctx_skip = SKIP_NOT;
824 generate_instr(cctx, ISN_PROF_START);
825 }
826#endif
827 cctx->ctx_skip = scope->se_skip_save;
828
829 // If all the blocks end in :return and there is an :else then the
830 // had_return flag is set.
831 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
832
833 drop_scope(cctx);
834 return arg;
835}
836
837/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +0100838 * Save the info needed for ENDLOOP. Used by :for and :while.
839 */
840 static void
841compile_fill_loop_info(loop_info_T *loop_info, int funcref_idx, cctx_T *cctx)
842{
843 loop_info->li_funcref_idx = funcref_idx;
844 loop_info->li_local_count = cctx->ctx_locals.ga_len;
845 loop_info->li_closure_count = cctx->ctx_closure_count;
846}
847
848/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000849 * Compile "for var in expr":
850 *
851 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100852 * STORE -1 in loop-idx Set index to -1
853 * EVAL expr Result of "expr" on top of stack
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000854 * top: FOR loop-idx, end Increment index, use list on bottom of stack
855 * - if beyond end, jump to "end"
856 * - otherwise get item from list and push it
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100857 * - store ec_funcrefs in var "loop-idx" + 1
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000858 * STORE var Store item in "var"
859 * ... body ...
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100860 * ENDLOOP funcref-idx off count Only if closure uses local var
861 * JUMP top Jump back to repeat
862 * end: DROP Drop the result of "expr"
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000863 *
864 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
865 * UNPACK 2 Split item in 2
866 * STORE var1 Store item in "var1"
867 * STORE var2 Store item in "var2"
868 */
869 char_u *
870compile_for(char_u *arg_start, cctx_T *cctx)
871{
872 char_u *arg;
873 char_u *arg_end;
874 char_u *name = NULL;
875 char_u *p;
876 char_u *wp;
877 int var_count = 0;
878 int var_list = FALSE;
879 int semicolon = FALSE;
880 size_t varlen;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000881 garray_T *instr = &cctx->ctx_instr;
882 scope_T *scope;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100883 forscope_T *forscope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000884 lvar_T *loop_lvar; // loop iteration variable
Bram Moolenaarcc341812022-09-19 15:54:34 +0100885 int loop_lvar_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100886 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100887 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000888 lvar_T *var_lvar; // variable for "var"
889 type_T *vartype;
890 type_T *item_type = &t_any;
891 int idx;
892 int prev_lnum = cctx->ctx_prev_lnum;
893
894 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
895 if (p == NULL)
896 return NULL;
897 if (var_count == 0)
898 var_count = 1;
899 else
900 var_list = TRUE; // can also be a list of one variable
901
902 // consume "in"
903 wp = p;
904 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
905 return NULL;
906 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
907 {
908 if (*p == ':' && wp != p)
909 semsg(_(e_no_white_space_allowed_before_colon_str), p);
910 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +0000911 emsg(_(e_missing_in_after_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000912 return NULL;
913 }
914 wp = p + 2;
915 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
916 return NULL;
917
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000918 // Find the already generated ISN_DEBUG to get the line number for the
919 // instruction written below the ISN_FOR instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000920 if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
921 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
922 .isn_type == ISN_DEBUG)
923 {
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +0000924 prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000925 .isn_arg.debug.dbg_break_lnum;
926 }
927
928 scope = new_scope(cctx, FOR_SCOPE);
929 if (scope == NULL)
930 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +0100931 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
932 {
933 emsg(_(e_loop_nesting_too_deep));
934 return NULL;
935 }
936 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100937 forscope = &scope->se_u.se_for;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000938
939 // Reserve a variable to store the loop iteration counter and initialize it
940 // to -1.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100941 loop_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000942 if (loop_lvar == NULL)
943 {
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000944 drop_scope(cctx);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100945 return NULL; // out of memory
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000946 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100947 // get the index before a following reserve_local() makes the lval invalid
948 loop_lvar_idx = loop_lvar->lv_idx;
949 generate_STORENR(cctx, loop_lvar_idx, -1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000950
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100951 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
952 // The variable index is always the loop var index plus one.
953 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +0100954 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100955 if (funcref_lvar == NULL)
956 {
957 drop_scope(cctx);
958 return NULL; // out of memory
959 }
Bram Moolenaarcc341812022-09-19 15:54:34 +0100960 // get the index before a following reserve_local() makes the lval invalid
961 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100962
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000963 // compile "expr", it remains on the stack until "endfor"
964 arg = p;
965 if (compile_expr0(&arg, cctx) == FAIL)
966 {
967 drop_scope(cctx);
968 return NULL;
969 }
970 arg_end = arg;
971
972 if (cctx->ctx_skip != SKIP_YES)
973 {
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000974 // If we know the type of "var" and it is not a supported type we can
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000975 // give an error now.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000976 vartype = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000977 if (vartype->tt_type != VAR_LIST
978 && vartype->tt_type != VAR_STRING
979 && vartype->tt_type != VAR_BLOB
980 && vartype->tt_type != VAR_ANY
981 && vartype->tt_type != VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000982 {
983 semsg(_(e_for_loop_on_str_not_supported),
984 vartype_name(vartype->tt_type));
985 drop_scope(cctx);
986 return NULL;
987 }
988
989 if (vartype->tt_type == VAR_STRING)
990 item_type = &t_string;
991 else if (vartype->tt_type == VAR_BLOB)
992 item_type = &t_number;
993 else if (vartype->tt_type == VAR_LIST
994 && vartype->tt_member->tt_type != VAR_ANY)
995 {
996 if (!var_list)
997 item_type = vartype->tt_member;
998 else if (vartype->tt_member->tt_type == VAR_LIST
999 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
1000 item_type = vartype->tt_member->tt_member;
1001 }
1002
1003 // CMDMOD_REV must come before the FOR instruction.
1004 generate_undo_cmdmods(cctx);
1005
1006 // "for_end" is set when ":endfor" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001007 forscope->fs_top_label = current_instr_idx(cctx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001008
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001009 if (cctx->ctx_compile_type == CT_DEBUG)
1010 {
1011 int save_prev_lnum = cctx->ctx_prev_lnum;
1012 isn_T *isn;
1013
1014 // Add ISN_DEBUG here, before deciding to end the loop. There will
1015 // be another ISN_DEBUG before the next instruction.
1016 // Use the prev_lnum from the ISN_DEBUG instruction removed above.
1017 // Increment the variable count so that the loop variable can be
1018 // inspected.
1019 cctx->ctx_prev_lnum = prev_lnum;
1020 isn = generate_instr_debug(cctx);
1021 ++isn->isn_arg.debug.dbg_var_names_len;
1022 cctx->ctx_prev_lnum = save_prev_lnum;
1023 }
1024
Bram Moolenaarcc341812022-09-19 15:54:34 +01001025 generate_FOR(cctx, loop_lvar_idx);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001026
1027 arg = arg_start;
1028 if (var_list)
1029 {
1030 generate_UNPACK(cctx, var_count, semicolon);
1031 arg = skipwhite(arg + 1); // skip white after '['
1032
Bram Moolenaar078a4612022-01-04 15:17:03 +00001033 // drop the list item
1034 --cctx->ctx_type_stack.ga_len;
1035
1036 // add type of the items
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001037 for (idx = 0; idx < var_count; ++idx)
1038 {
Bram Moolenaar078a4612022-01-04 15:17:03 +00001039 type_T *type = (semicolon && idx == 0) ? vartype : item_type;
1040
1041 if (push_type_stack(cctx, type) == FAIL)
1042 {
1043 drop_scope(cctx);
1044 return NULL;
1045 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001046 }
1047 }
1048
1049 for (idx = 0; idx < var_count; ++idx)
1050 {
1051 assign_dest_T dest = dest_local;
1052 int opt_flags = 0;
1053 int vimvaridx = -1;
1054 type_T *type = &t_any;
1055 type_T *lhs_type = &t_any;
1056 where_T where = WHERE_INIT;
1057
1058 p = skip_var_one(arg, FALSE);
1059 varlen = p - arg;
1060 name = vim_strnsave(arg, varlen);
1061 if (name == NULL)
1062 goto failed;
Bram Moolenaarce93d162023-01-30 21:12:34 +00001063 if (*skipwhite(p) == ':')
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001064 {
Bram Moolenaarce93d162023-01-30 21:12:34 +00001065 if (VIM_ISWHITE(*p))
1066 {
1067 semsg(_(e_no_white_space_allowed_before_colon_str), p);
1068 goto failed;
1069 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001070 p = skipwhite(p + 1);
1071 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
1072 }
1073
1074 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
1075 &vimvaridx, &type, cctx) == FAIL)
1076 goto failed;
1077 if (dest != dest_local)
1078 {
1079 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
Bram Moolenaard505d172022-12-18 21:42:55 +00001080 type, name, NULL) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001081 goto failed;
1082 }
1083 else if (varlen == 1 && *arg == '_')
1084 {
1085 // Assigning to "_": drop the value.
1086 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1087 goto failed;
1088 }
1089 else
1090 {
1091 // Script var is not supported.
1092 if (STRNCMP(name, "s:", 2) == 0)
1093 {
1094 emsg(_(e_cannot_use_script_variable_in_for_loop));
1095 goto failed;
1096 }
1097
1098 if (!valid_varname(arg, (int)varlen, FALSE))
1099 goto failed;
1100 if (lookup_local(arg, varlen, NULL, cctx) == OK)
1101 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00001102 semsg(_(e_variable_already_declared_str), arg);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001103 goto failed;
1104 }
1105
1106 // Reserve a variable to store "var".
LemonBoyc5d27442023-08-19 13:02:35 +02001107 if (var_list)
1108 {
1109 where.wt_index = idx + 1;
1110 where.wt_kind = WT_VARIABLE;
1111 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001112 if (lhs_type == &t_any)
1113 lhs_type = item_type;
1114 else if (item_type != &t_unknown
Bram Moolenaarc6951a72022-12-29 20:56:24 +00001115 && need_type_where(item_type, lhs_type, FALSE, -1,
Bram Moolenaara1c51952022-02-02 16:20:26 +00001116 where, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001117 goto failed;
Bram Moolenaar159b2d52022-10-11 21:41:25 +01001118 var_lvar = reserve_local(cctx, arg, varlen, ASSIGN_FINAL,
Bram Moolenaar6586a012022-09-30 11:04:50 +01001119 lhs_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001120 if (var_lvar == NULL)
1121 // out of memory or used as an argument
1122 goto failed;
1123
1124 if (semicolon && idx == var_count - 1)
1125 var_lvar->lv_type = vartype;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001126 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
1127 }
1128
1129 if (*p == ',' || *p == ';')
1130 ++p;
1131 arg = skipwhite(p);
1132 vim_free(name);
1133 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001134
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001135 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001136 compile_fill_loop_info(&forscope->fs_loop_info, funcref_lvar_idx, cctx);
1137 forscope->fs_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001138 }
1139
1140 return arg_end;
1141
1142failed:
1143 vim_free(name);
1144 drop_scope(cctx);
1145 return NULL;
1146}
1147
1148/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001149 * Used when ending a loop of :for and :while: Generate an ISN_ENDLOOP
1150 * instruction if any variable was declared that could be used by a new
1151 * closure.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001152 */
1153 static int
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001154compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001155{
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001156 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1157 && cctx->ctx_closure_count > loop_info->li_closure_count)
Bram Moolenaarcc341812022-09-19 15:54:34 +01001158 return generate_ENDLOOP(cctx, loop_info);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001159 return OK;
1160}
1161
1162/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001163 * compile "endfor"
1164 */
1165 char_u *
1166compile_endfor(char_u *arg, cctx_T *cctx)
1167{
1168 garray_T *instr = &cctx->ctx_instr;
1169 scope_T *scope = cctx->ctx_scope;
1170 forscope_T *forscope;
1171 isn_T *isn;
1172
1173 if (misplaced_cmdmod(cctx))
1174 return NULL;
1175
1176 if (scope == NULL || scope->se_type != FOR_SCOPE)
1177 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001178 emsg(_(e_endfor_without_for));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001179 return NULL;
1180 }
1181 forscope = &scope->se_u.se_for;
1182 cctx->ctx_scope = scope->se_outer;
1183 if (cctx->ctx_skip != SKIP_YES)
1184 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001185 // Handle the case that any local variables were declared that might be
1186 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001187 if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001188 return NULL;
1189
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001190 unwind_locals(cctx, scope->se_local_count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001191
1192 // At end of ":for" scope jump back to the FOR instruction.
1193 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
1194
1195 // Fill in the "end" label in the FOR statement so it can jump here.
Bram Moolenaar2b4ecc22022-01-02 14:08:18 +00001196 // In debug mode an ISN_DEBUG was inserted.
1197 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
1198 + (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001199 isn->isn_arg.forloop.for_end = instr->ga_len;
1200
1201 // Fill in the "end" label any BREAK statements
1202 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
1203
1204 // Below the ":for" scope drop the "expr" list from the stack.
1205 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
1206 return NULL;
1207 }
1208
1209 vim_free(scope);
1210
1211 return arg;
1212}
1213
1214/*
1215 * compile "while expr"
1216 *
1217 * Produces instructions:
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001218 * top: EVAL expr Push result of "expr"
1219 * WHILE funcref-idx end Jump if false
1220 * ... body ...
1221 * ENDLOOP funcref-idx off count only if closure uses local var
1222 * JUMP top Jump back to repeat
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001223 * end:
1224 *
1225 */
1226 char_u *
1227compile_while(char_u *arg, cctx_T *cctx)
1228{
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001229 char_u *p = arg;
1230 scope_T *scope;
1231 whilescope_T *whilescope;
1232 lvar_T *funcref_lvar;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001233 int funcref_lvar_idx;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001234
1235 scope = new_scope(cctx, WHILE_SCOPE);
1236 if (scope == NULL)
1237 return NULL;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001238 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
1239 {
1240 emsg(_(e_loop_nesting_too_deep));
1241 return NULL;
1242 }
1243 ++scope->se_loop_depth;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001244 whilescope = &scope->se_u.se_while;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001245
1246 // "endwhile" jumps back here, one before when profiling or using cmdmods
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001247 whilescope->ws_top_label = current_instr_idx(cctx);
1248
1249 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
1250 // It is not used when no closures are encountered, we don't know yet.
Bram Moolenaar6586a012022-09-30 11:04:50 +01001251 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, ASSIGN_VAR, &t_number);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001252 if (funcref_lvar == NULL)
1253 {
1254 drop_scope(cctx);
1255 return NULL; // out of memory
1256 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001257 // get the index before a following reserve_local() makes the lval invalid
1258 funcref_lvar_idx = funcref_lvar->lv_idx;
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001259
1260 // remember the number of variables and closures, used for ENDLOOP
Bram Moolenaarcc341812022-09-19 15:54:34 +01001261 compile_fill_loop_info(&whilescope->ws_loop_info, funcref_lvar_idx, cctx);
1262 whilescope->ws_loop_info.li_depth = scope->se_loop_depth - 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001263
1264 // compile "expr"
1265 if (compile_expr0(&p, cctx) == FAIL)
1266 return NULL;
1267
1268 if (!ends_excmd2(arg, skipwhite(p)))
1269 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00001270 semsg(_(e_trailing_characters_str), p);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001271 return NULL;
1272 }
1273
1274 if (cctx->ctx_skip != SKIP_YES)
1275 {
1276 if (bool_on_stack(cctx) == FAIL)
1277 return FAIL;
1278
1279 // CMDMOD_REV must come before the jump
1280 generate_undo_cmdmods(cctx);
1281
1282 // "while_end" is set when ":endwhile" is found
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001283 if (compile_jump_to_end(&whilescope->ws_end_label,
Bram Moolenaarcc341812022-09-19 15:54:34 +01001284 JUMP_WHILE_FALSE, funcref_lvar_idx, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001285 return FAIL;
1286 }
1287
1288 return p;
1289}
1290
1291/*
1292 * compile "endwhile"
1293 */
1294 char_u *
1295compile_endwhile(char_u *arg, cctx_T *cctx)
1296{
1297 scope_T *scope = cctx->ctx_scope;
1298 garray_T *instr = &cctx->ctx_instr;
1299
1300 if (misplaced_cmdmod(cctx))
1301 return NULL;
1302 if (scope == NULL || scope->se_type != WHILE_SCOPE)
1303 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001304 emsg(_(e_endwhile_without_while));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001305 return NULL;
1306 }
1307 cctx->ctx_scope = scope->se_outer;
1308 if (cctx->ctx_skip != SKIP_YES)
1309 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001310 whilescope_T *whilescope = &scope->se_u.se_while;
1311
1312 // Handle the case that any local variables were declared that might be
1313 // used in a closure.
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001314 if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001315 return NULL;
1316
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001317 unwind_locals(cctx, scope->se_local_count, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001318
1319#ifdef FEAT_PROFILE
1320 // count the endwhile before jumping
1321 may_generate_prof_end(cctx, cctx->ctx_lnum);
1322#endif
1323
1324 // At end of ":for" scope jump back to the FOR instruction.
1325 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
1326
1327 // Fill in the "end" label in the WHILE statement so it can jump here.
1328 // And in any jumps for ":break"
1329 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
1330 instr->ga_len, cctx);
1331 }
1332
1333 vim_free(scope);
1334
1335 return arg;
1336}
1337
1338/*
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001339 * Get the current information about variables declared inside a loop.
Bram Moolenaarcc341812022-09-19 15:54:34 +01001340 * Returns TRUE if there are any and fills "lvi".
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001341 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001342 int
1343get_loop_var_info(cctx_T *cctx, loopvarinfo_T *lvi)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001344{
1345 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001346 int prev_local_count = 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001347
Bram Moolenaarcc341812022-09-19 15:54:34 +01001348 CLEAR_POINTER(lvi);
1349 for (;;)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001350 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01001351 loop_info_T *loopinfo;
1352 int cur_local_last;
1353 int start_local_count;
1354
1355 while (scope != NULL && scope->se_type != WHILE_SCOPE
1356 && scope->se_type != FOR_SCOPE)
1357 scope = scope->se_outer;
1358 if (scope == NULL)
1359 break;
1360
1361 if (scope->se_type == WHILE_SCOPE)
1362 {
1363 loopinfo = &scope->se_u.se_while.ws_loop_info;
1364 // :while reserves one variable for funcref count
1365 cur_local_last = loopinfo->li_local_count - 1;
1366 }
1367 else
1368 {
1369 loopinfo = &scope->se_u.se_for.fs_loop_info;
1370 // :for reserves three variable: loop count, funcref count and loop
1371 // var
1372 cur_local_last = loopinfo->li_local_count - 3;
1373 }
1374
1375 start_local_count = loopinfo->li_local_count;
1376 if (cctx->ctx_locals.ga_len > start_local_count)
1377 {
1378 lvi->lvi_loop[loopinfo->li_depth].var_idx =
1379 (short)start_local_count;
1380 lvi->lvi_loop[loopinfo->li_depth].var_count =
1381 (short)(cctx->ctx_locals.ga_len - start_local_count
1382 - prev_local_count);
1383 if (lvi->lvi_depth == 0)
1384 lvi->lvi_depth = loopinfo->li_depth + 1;
1385 }
1386
1387 scope = scope->se_outer;
1388 prev_local_count = cctx->ctx_locals.ga_len - cur_local_last;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001389 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01001390 return lvi->lvi_depth > 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001391}
1392
1393/*
Bram Moolenaarcc341812022-09-19 15:54:34 +01001394 * Get the index of the variable "idx" in a loop, if any.
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001395 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01001396 void
1397get_loop_var_idx(cctx_T *cctx, int idx, lvar_T *lvar)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001398{
Bram Moolenaarcc341812022-09-19 15:54:34 +01001399 loopvarinfo_T lvi;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001400
Bram Moolenaarcc341812022-09-19 15:54:34 +01001401 lvar->lv_loop_depth = -1;
1402 lvar->lv_loop_idx = -1;
1403 if (get_loop_var_info(cctx, &lvi))
1404 {
1405 int depth;
1406
1407 for (depth = lvi.lvi_depth - 1; depth >= 0; --depth)
1408 if (idx >= lvi.lvi_loop[depth].var_idx
1409 && idx < lvi.lvi_loop[depth].var_idx
1410 + lvi.lvi_loop[depth].var_count)
1411 {
1412 lvar->lv_loop_depth = depth;
1413 lvar->lv_loop_idx = lvi.lvi_loop[depth].var_idx;
1414 return;
1415 }
1416 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001417}
1418
1419/*
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001420 * Common for :break, :continue and :return
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001421 */
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001422 static int
1423compile_find_scope(
1424 int *loop_label, // where to jump to or NULL
1425 endlabel_T ***el, // end label or NULL
1426 int *try_scopes, // :try scopes encountered or NULL
1427 char *error, // error to use when no scope found
1428 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001429{
1430 scope_T *scope = cctx->ctx_scope;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001431
1432 for (;;)
1433 {
1434 if (scope == NULL)
1435 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001436 if (error != NULL)
1437 emsg(_(error));
1438 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001439 }
1440 if (scope->se_type == FOR_SCOPE)
1441 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001442 if (compile_loop_end(&scope->se_u.se_for.fs_loop_info, cctx)
1443 == FAIL)
1444 return FAIL;
1445 if (loop_label != NULL)
1446 *loop_label = scope->se_u.se_for.fs_top_label;
1447 if (el != NULL)
1448 *el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001449 break;
1450 }
1451 if (scope->se_type == WHILE_SCOPE)
1452 {
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001453 if (compile_loop_end(&scope->se_u.se_while.ws_loop_info, cctx)
1454 == FAIL)
1455 return FAIL;
1456 if (loop_label != NULL)
1457 *loop_label = scope->se_u.se_while.ws_top_label;
1458 if (el != NULL)
1459 *el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001460 break;
1461 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001462 if (try_scopes != NULL && scope->se_type == TRY_SCOPE)
1463 ++*try_scopes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001464 scope = scope->se_outer;
1465 }
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001466 return OK;
1467}
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001468
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001469/*
1470 * compile "continue"
1471 */
1472 char_u *
1473compile_continue(char_u *arg, cctx_T *cctx)
1474{
1475 int try_scopes = 0;
1476 int loop_label;
1477
1478 if (compile_find_scope(&loop_label, NULL, &try_scopes,
1479 e_continue_without_while_or_for, cctx) == FAIL)
1480 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001481 if (try_scopes > 0)
1482 // Inside one or more try/catch blocks we first need to jump to the
1483 // "finally" or "endtry" to cleanup.
1484 generate_TRYCONT(cctx, try_scopes, loop_label);
1485 else
1486 // Jump back to the FOR or WHILE instruction.
1487 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
1488
1489 return arg;
1490}
1491
1492/*
1493 * compile "break"
1494 */
1495 char_u *
1496compile_break(char_u *arg, cctx_T *cctx)
1497{
Bram Moolenaar873f8242022-03-10 21:53:44 +00001498 int try_scopes = 0;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001499 endlabel_T **el;
1500
Bram Moolenaar8abb5842022-09-17 12:39:58 +01001501 if (compile_find_scope(NULL, &el, &try_scopes,
1502 e_break_without_while_or_for, cctx) == FAIL)
1503 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001504
Bram Moolenaar3f45d672023-02-27 22:06:51 +00001505 if (cctx->ctx_skip == SKIP_YES)
1506 return arg;
1507
Bram Moolenaar873f8242022-03-10 21:53:44 +00001508 if (try_scopes > 0)
1509 // Inside one or more try/catch blocks we first need to jump to the
1510 // "finally" or "endtry" to cleanup. Then come to the next JUMP
dundargocc57b5bc2022-11-02 13:30:51 +00001511 // instruction, which we don't know the index of yet.
Bram Moolenaar873f8242022-03-10 21:53:44 +00001512 generate_TRYCONT(cctx, try_scopes, cctx->ctx_instr.ga_len + 1);
1513
1514 // Jump to the end of the FOR or WHILE loop. The instruction index will be
1515 // filled in later.
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001516 if (compile_jump_to_end(el, JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaar3f45d672023-02-27 22:06:51 +00001517 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001518
1519 return arg;
1520}
1521
1522/*
1523 * compile "{" start of block
1524 */
1525 char_u *
1526compile_block(char_u *arg, cctx_T *cctx)
1527{
1528 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1529 return NULL;
1530 return skipwhite(arg + 1);
1531}
1532
1533/*
1534 * compile end of block: drop one scope
1535 */
1536 void
1537compile_endblock(cctx_T *cctx)
1538{
1539 scope_T *scope = cctx->ctx_scope;
1540
1541 cctx->ctx_scope = scope->se_outer;
Bram Moolenaara275f2c2022-10-11 20:04:09 +01001542 unwind_locals(cctx, scope->se_local_count, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001543 vim_free(scope);
1544}
1545
1546/*
1547 * Compile "try".
1548 * Creates a new scope for the try-endtry, pointing to the first catch and
1549 * finally.
1550 * Creates another scope for the "try" block itself.
1551 * TRY instruction sets up exception handling at runtime.
1552 *
1553 * "try"
1554 * TRY -> catch1, -> finally push trystack entry
1555 * ... try block
1556 * "throw {exception}"
1557 * EVAL {exception}
1558 * THROW create exception
1559 * ... try block
1560 * " catch {expr}"
1561 * JUMP -> finally
1562 * catch1: PUSH exception
1563 * EVAL {expr}
1564 * MATCH
1565 * JUMP nomatch -> catch2
1566 * CATCH remove exception
1567 * ... catch block
1568 * " catch"
1569 * JUMP -> finally
1570 * catch2: CATCH remove exception
1571 * ... catch block
1572 * " finally"
1573 * finally:
1574 * ... finally block
1575 * " endtry"
1576 * ENDTRY pop trystack entry, may rethrow
1577 */
1578 char_u *
1579compile_try(char_u *arg, cctx_T *cctx)
1580{
1581 garray_T *instr = &cctx->ctx_instr;
1582 scope_T *try_scope;
1583 scope_T *scope;
1584
1585 if (misplaced_cmdmod(cctx))
1586 return NULL;
1587
1588 // scope that holds the jumps that go to catch/finally/endtry
1589 try_scope = new_scope(cctx, TRY_SCOPE);
1590 if (try_scope == NULL)
1591 return NULL;
1592
1593 if (cctx->ctx_skip != SKIP_YES)
1594 {
1595 isn_T *isn;
1596
1597 // "try_catch" is set when the first ":catch" is found or when no catch
1598 // is found and ":finally" is found.
1599 // "try_finally" is set when ":finally" is found
1600 // "try_endtry" is set when ":endtry" is found
1601 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
1602 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
1603 return NULL;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001604 isn->isn_arg.tryref.try_ref = ALLOC_CLEAR_ONE(tryref_T);
1605 if (isn->isn_arg.tryref.try_ref == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001606 return NULL;
1607 }
1608
1609 // scope for the try block itself
1610 scope = new_scope(cctx, BLOCK_SCOPE);
1611 if (scope == NULL)
1612 return NULL;
1613
1614 return arg;
1615}
1616
1617/*
1618 * Compile "catch {expr}".
1619 */
1620 char_u *
1621compile_catch(char_u *arg, cctx_T *cctx UNUSED)
1622{
1623 scope_T *scope = cctx->ctx_scope;
1624 garray_T *instr = &cctx->ctx_instr;
1625 char_u *p;
1626 isn_T *isn;
1627
1628 if (misplaced_cmdmod(cctx))
1629 return NULL;
1630
1631 // end block scope from :try or :catch
1632 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1633 compile_endblock(cctx);
1634 scope = cctx->ctx_scope;
1635
1636 // Error if not in a :try scope
1637 if (scope == NULL || scope->se_type != TRY_SCOPE)
1638 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001639 emsg(_(e_catch_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001640 return NULL;
1641 }
1642
Bram Moolenaar9d383f32023-05-14 21:38:12 +01001643 if (scope->se_u.se_try.ts_caught_all
1644 && !ignore_unreachable_code_for_testing)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001645 {
1646 emsg(_(e_catch_unreachable_after_catch_all));
1647 return NULL;
1648 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001649 if (!cctx->ctx_had_return)
1650 scope->se_u.se_try.ts_no_return = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001651
1652 if (cctx->ctx_skip != SKIP_YES)
1653 {
1654#ifdef FEAT_PROFILE
1655 // the profile-start should be after the jump
1656 if (cctx->ctx_compile_type == CT_PROFILE
1657 && instr->ga_len > 0
1658 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1659 .isn_type == ISN_PROF_START)
1660 --instr->ga_len;
1661#endif
1662 // Jump from end of previous block to :finally or :endtry
1663 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001664 JUMP_ALWAYS, 0, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001665 return NULL;
1666
1667 // End :try or :catch scope: set value in ISN_TRY instruction
1668 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001669 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1670 isn->isn_arg.tryref.try_ref->try_catch = instr->ga_len;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001671 if (scope->se_u.se_try.ts_catch_label != 0)
1672 {
1673 // Previous catch without match jumps here
1674 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1675 isn->isn_arg.jump.jump_where = instr->ga_len;
1676 }
1677#ifdef FEAT_PROFILE
1678 if (cctx->ctx_compile_type == CT_PROFILE)
1679 {
1680 // a "throw" that jumps here needs to be counted
1681 generate_instr(cctx, ISN_PROF_END);
1682 // the "catch" is also counted
1683 generate_instr(cctx, ISN_PROF_START);
1684 }
1685#endif
1686 if (cctx->ctx_compile_type == CT_DEBUG)
1687 generate_instr_debug(cctx);
1688 }
1689
1690 p = skipwhite(arg);
1691 if (ends_excmd2(arg, p))
1692 {
1693 scope->se_u.se_try.ts_caught_all = TRUE;
1694 scope->se_u.se_try.ts_catch_label = 0;
1695 }
1696 else
1697 {
1698 char_u *end;
1699 char_u *pat;
1700 char_u *tofree = NULL;
1701 int dropped = 0;
1702 int len;
1703
1704 // Push v:exception, push {expr} and MATCH
1705 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
1706
1707 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
1708 if (*end != *p)
1709 {
1710 semsg(_(e_separator_mismatch_str), p);
1711 vim_free(tofree);
Bram Moolenaar54969f42022-02-07 13:56:44 +00001712 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001713 }
1714 if (tofree == NULL)
1715 len = (int)(end - (p + 1));
1716 else
1717 len = (int)(end - tofree);
1718 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
1719 vim_free(tofree);
1720 p += len + 2 + dropped;
1721 if (pat == NULL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001722 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001723 if (generate_PUSHS(cctx, &pat) == FAIL)
Bram Moolenaar54969f42022-02-07 13:56:44 +00001724 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001725
1726 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
1727 return NULL;
1728
1729 scope->se_u.se_try.ts_catch_label = instr->ga_len;
1730 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
1731 return NULL;
1732 }
1733
1734 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
1735 return NULL;
1736
1737 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
1738 return NULL;
1739 return p;
1740}
1741
1742 char_u *
1743compile_finally(char_u *arg, cctx_T *cctx)
1744{
1745 scope_T *scope = cctx->ctx_scope;
1746 garray_T *instr = &cctx->ctx_instr;
1747 isn_T *isn;
1748 int this_instr;
1749
1750 if (misplaced_cmdmod(cctx))
1751 return NULL;
1752
1753 // end block scope from :try or :catch
1754 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1755 compile_endblock(cctx);
1756 scope = cctx->ctx_scope;
1757
1758 // Error if not in a :try scope
1759 if (scope == NULL || scope->se_type != TRY_SCOPE)
1760 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001761 emsg(_(e_finally_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001762 return NULL;
1763 }
1764
1765 if (cctx->ctx_skip != SKIP_YES)
1766 {
1767 // End :catch or :finally scope: set value in ISN_TRY instruction
1768 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar0d807102021-12-21 09:42:09 +00001769 if (isn->isn_arg.tryref.try_ref->try_finally != 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001770 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001771 emsg(_(e_multiple_finally));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001772 return NULL;
1773 }
1774
1775 this_instr = instr->ga_len;
1776#ifdef FEAT_PROFILE
1777 if (cctx->ctx_compile_type == CT_PROFILE
1778 && ((isn_T *)instr->ga_data)[this_instr - 1]
1779 .isn_type == ISN_PROF_START)
1780 {
1781 // jump to the profile start of the "finally"
1782 --this_instr;
1783
1784 // jump to the profile end above it
1785 if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1]
1786 .isn_type == ISN_PROF_END)
1787 --this_instr;
1788 }
1789#endif
1790
1791 // Fill in the "end" label in jumps at the end of the blocks.
1792 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1793 this_instr, cctx);
1794
1795 // If there is no :catch then an exception jumps to :finally.
Bram Moolenaar0d807102021-12-21 09:42:09 +00001796 if (isn->isn_arg.tryref.try_ref->try_catch == 0)
1797 isn->isn_arg.tryref.try_ref->try_catch = this_instr;
1798 isn->isn_arg.tryref.try_ref->try_finally = this_instr;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001799 if (scope->se_u.se_try.ts_catch_label != 0)
1800 {
1801 // Previous catch without match jumps here
1802 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
1803 isn->isn_arg.jump.jump_where = this_instr;
1804 scope->se_u.se_try.ts_catch_label = 0;
1805 }
Bram Moolenaar53c29612022-01-12 16:18:18 +00001806 scope->se_u.se_try.ts_has_finally = TRUE;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001807 if (generate_instr(cctx, ISN_FINALLY) == NULL)
1808 return NULL;
1809 }
1810
1811 return arg;
1812}
1813
1814 char_u *
1815compile_endtry(char_u *arg, cctx_T *cctx)
1816{
1817 scope_T *scope = cctx->ctx_scope;
1818 garray_T *instr = &cctx->ctx_instr;
1819 isn_T *try_isn;
1820
1821 if (misplaced_cmdmod(cctx))
1822 return NULL;
1823
1824 // end block scope from :catch or :finally
1825 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
1826 compile_endblock(cctx);
1827 scope = cctx->ctx_scope;
1828
1829 // Error if not in a :try scope
1830 if (scope == NULL || scope->se_type != TRY_SCOPE)
1831 {
1832 if (scope == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00001833 emsg(_(e_endtry_without_try));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001834 else if (scope->se_type == WHILE_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001835 emsg(_(e_missing_endwhile));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001836 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar1a992222021-12-31 17:25:48 +00001837 emsg(_(e_missing_endfor));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001838 else
Bram Moolenaar1a992222021-12-31 17:25:48 +00001839 emsg(_(e_missing_endif));
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001840 return NULL;
1841 }
1842
1843 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
1844 if (cctx->ctx_skip != SKIP_YES)
1845 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00001846 if (try_isn->isn_arg.tryref.try_ref->try_catch == 0
1847 && try_isn->isn_arg.tryref.try_ref->try_finally == 0)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001848 {
1849 emsg(_(e_missing_catch_or_finally));
1850 return NULL;
1851 }
1852
1853#ifdef FEAT_PROFILE
1854 if (cctx->ctx_compile_type == CT_PROFILE
1855 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
1856 .isn_type == ISN_PROF_START)
1857 // move the profile start after "endtry" so that it's not counted when
1858 // the exception is rethrown.
1859 --instr->ga_len;
1860#endif
1861
1862 // Fill in the "end" label in jumps at the end of the blocks, if not
1863 // done by ":finally".
1864 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
1865 instr->ga_len, cctx);
1866
1867 if (scope->se_u.se_try.ts_catch_label != 0)
1868 {
1869 // Last catch without match jumps here
1870 isn_T *isn = ((isn_T *)instr->ga_data)
1871 + scope->se_u.se_try.ts_catch_label;
1872 isn->isn_arg.jump.jump_where = instr->ga_len;
1873 }
1874 }
1875
Bram Moolenaar53c29612022-01-12 16:18:18 +00001876 // If there is a finally clause that ends in return then we will return.
1877 // If one of the blocks didn't end in "return" or we did not catch all
1878 // exceptions reset the had_return flag.
1879 if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
1880 && (scope->se_u.se_try.ts_no_return
1881 || !scope->se_u.se_try.ts_caught_all))
1882 cctx->ctx_had_return = FALSE;
1883
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001884 compile_endblock(cctx);
1885
1886 if (cctx->ctx_skip != SKIP_YES)
1887 {
1888 // End :catch or :finally scope: set instruction index in ISN_TRY
1889 // instruction
Bram Moolenaar0d807102021-12-21 09:42:09 +00001890 try_isn->isn_arg.tryref.try_ref->try_endtry = instr->ga_len;
Bram Moolenaarfe154992022-03-22 20:42:12 +00001891 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001892 return NULL;
1893#ifdef FEAT_PROFILE
1894 if (cctx->ctx_compile_type == CT_PROFILE)
1895 generate_instr(cctx, ISN_PROF_START);
1896#endif
1897 }
1898 return arg;
1899}
1900
1901/*
1902 * compile "throw {expr}"
1903 */
1904 char_u *
1905compile_throw(char_u *arg, cctx_T *cctx UNUSED)
1906{
1907 char_u *p = skipwhite(arg);
1908
1909 if (compile_expr0(&p, cctx) == FAIL)
1910 return NULL;
1911 if (cctx->ctx_skip == SKIP_YES)
1912 return p;
1913 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
1914 return NULL;
1915 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
1916 return NULL;
1917
1918 return p;
1919}
1920
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001921/*
1922 * Compile an expression or function call.
1923 */
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001924 char_u *
1925compile_eval(char_u *arg, cctx_T *cctx)
1926{
1927 char_u *p = arg;
1928 int name_only;
1929 long lnum = SOURCING_LNUM;
1930
1931 // find_ex_command() will consider a variable name an expression, assuming
1932 // that something follows on the next line. Check that something actually
1933 // follows, otherwise it's probably a misplaced command.
1934 name_only = cmd_is_name_only(arg);
1935
1936 if (compile_expr0(&p, cctx) == FAIL)
1937 return NULL;
1938
1939 if (name_only && lnum == SOURCING_LNUM)
1940 {
1941 semsg(_(e_expression_without_effect_str), arg);
1942 return NULL;
1943 }
1944
1945 // drop the result
1946 generate_instr_drop(cctx, ISN_DROP, 1);
1947
1948 return skipwhite(p);
1949}
1950
1951/*
Bram Moolenaarc572ad52022-09-08 20:49:22 +01001952 * Get the local variable index for deferred function calls.
1953 * Reserve it when not done already.
1954 * Returns zero for failure.
1955 */
1956 int
1957get_defer_var_idx(cctx_T *cctx)
1958{
1959 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1960 + cctx->ctx_ufunc->uf_dfunc_idx;
1961 if (dfunc->df_defer_var_idx == 0)
1962 {
1963 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1964 TRUE, &t_list_any);
1965 if (lvar == NULL)
1966 return 0;
1967 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1968 }
1969 return dfunc->df_defer_var_idx;
1970}
1971
1972/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001973 * Compile "defer func(arg)".
1974 */
1975 char_u *
1976compile_defer(char_u *arg_start, cctx_T *cctx)
1977{
Bram Moolenaar16900322022-09-08 19:51:45 +01001978 char_u *paren;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001979 char_u *arg = arg_start;
1980 int argcount = 0;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001981 int defer_var_idx;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001982 type_T *type;
1983 int func_idx;
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001984 int obj_method = 0;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001985
1986 // Get a funcref for the function name.
1987 // TODO: better way to find the "(".
Bram Moolenaar16900322022-09-08 19:51:45 +01001988 paren = vim_strchr(arg, '(');
1989 if (paren == NULL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001990 {
1991 semsg(_(e_missing_parenthesis_str), arg);
1992 return NULL;
1993 }
Bram Moolenaar16900322022-09-08 19:51:45 +01001994 *paren = NUL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001995 func_idx = find_internal_func(arg);
1996 if (func_idx >= 0)
1997 // TODO: better type
1998 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1999 &t_func_any, FALSE);
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002000 else
2001 {
2002 int typecount = cctx->ctx_type_stack.ga_len;
2003 if (compile_expr0(&arg, cctx) == FAIL)
2004 return NULL;
2005 if (cctx->ctx_type_stack.ga_len >= typecount + 2)
2006 // must have seen "obj.Func", pushed an object and a function
2007 obj_method = 1;
2008 }
Bram Moolenaar16900322022-09-08 19:51:45 +01002009 *paren = '(';
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002010
2011 // check for function type
2012 type = get_type_on_stack(cctx, 0);
2013 if (type->tt_type != VAR_FUNC)
2014 {
2015 emsg(_(e_function_name_required));
2016 return NULL;
2017 }
2018
2019 // compile the arguments
Bram Moolenaar16900322022-09-08 19:51:45 +01002020 arg = skipwhite(paren + 1);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002021 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
2022 return NULL;
2023
Bram Moolenaar16900322022-09-08 19:51:45 +01002024 if (func_idx >= 0)
2025 {
2026 type2_T *argtypes = NULL;
2027 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
2028
2029 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
2030 &argtypes, shuffled_argtypes) == FAIL)
2031 return NULL;
2032 }
2033 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
2034 arg_start) == FAIL)
2035 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002036
Bram Moolenaar806a2732022-09-04 15:40:36 +01002037 defer_var_idx = get_defer_var_idx(cctx);
2038 if (defer_var_idx == 0)
2039 return NULL;
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002040 if (generate_DEFER(cctx, defer_var_idx - 1, obj_method, argcount) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +01002041 return NULL;
2042
2043 return skipwhite(arg);
2044}
2045
2046/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002047 * compile "echo expr"
2048 * compile "echomsg expr"
2049 * compile "echoerr expr"
2050 * compile "echoconsole expr"
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002051 * compile "echowindow expr" - may have cmd_count set
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002052 * compile "execute expr"
2053 */
2054 char_u *
Bram Moolenaar9b994112022-12-25 15:59:25 +00002055compile_mult_expr(
2056 char_u *arg,
2057 int cmdidx,
2058 long cmd_count UNUSED,
2059 cctx_T *cctx)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002060{
2061 char_u *p = arg;
2062 char_u *prev = arg;
2063 char_u *expr_start;
2064 int count = 0;
2065 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002066 type_T *type;
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002067 int r = OK;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002068
2069 for (;;)
2070 {
2071 if (ends_excmd2(prev, p))
2072 break;
2073 expr_start = p;
2074 if (compile_expr0(&p, cctx) == FAIL)
2075 return NULL;
2076
2077 if (cctx->ctx_skip != SKIP_YES)
2078 {
2079 // check for non-void type
Bram Moolenaar078a4612022-01-04 15:17:03 +00002080 type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002081 if (type->tt_type == VAR_VOID)
2082 {
2083 semsg(_(e_expression_does_not_result_in_value_str), expr_start);
2084 return NULL;
2085 }
2086 }
2087
2088 ++count;
2089 prev = p;
2090 p = skipwhite(p);
2091 }
2092
2093 if (count > 0)
2094 {
2095 long save_lnum = cctx->ctx_lnum;
2096
2097 // Use the line number where the command started.
2098 cctx->ctx_lnum = start_ctx_lnum;
2099
2100 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002101 r = generate_ECHO(cctx, cmdidx == CMD_echo, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002102 else if (cmdidx == CMD_execute)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002103 r = generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002104 else if (cmdidx == CMD_echomsg)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002105 r = generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002106#ifdef HAS_MESSAGE_WINDOW
2107 else if (cmdidx == CMD_echowindow)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002108 r = generate_ECHOWINDOW(cctx, count, cmd_count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01002109#endif
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002110 else if (cmdidx == CMD_echoconsole)
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002111 r = generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002112 else
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002113 r = generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002114
2115 cctx->ctx_lnum = save_lnum;
2116 }
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01002117 return r == OK ? p : NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002118}
2119
2120/*
2121 * If "eap" has a range that is not a constant generate an ISN_RANGE
2122 * instruction to compute it and return OK.
2123 * Otherwise return FAIL, the caller must deal with any range.
2124 */
2125 static int
2126compile_variable_range(exarg_T *eap, cctx_T *cctx)
2127{
2128 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
2129 char_u *p = skipdigits(eap->cmd);
2130
2131 if (p == range_end)
2132 return FAIL;
2133 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
2134}
2135
2136/*
2137 * :put r
2138 * :put ={expr}
2139 */
2140 char_u *
2141compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
2142{
2143 char_u *line = arg;
2144 linenr_T lnum;
2145 char *errormsg;
2146 int above = eap->forceit;
2147
2148 eap->regname = *line;
2149
2150 if (eap->regname == '=')
2151 {
Bram Moolenaard0b7bfa2022-03-12 14:51:16 +00002152 char_u *p = skipwhite(line + 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002153
2154 if (compile_expr0(&p, cctx) == FAIL)
2155 return NULL;
2156 line = p;
2157 }
2158 else if (eap->regname != NUL)
2159 ++line;
2160
2161 if (compile_variable_range(eap, cctx) == OK)
2162 {
2163 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
2164 }
2165 else
2166 {
2167 // Either no range or a number.
2168 // "errormsg" will not be set because the range is ADDR_LINES.
2169 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
2170 // cannot happen
2171 return NULL;
2172 if (eap->addr_count == 0)
2173 lnum = -1;
2174 else
2175 lnum = eap->line2;
2176 if (above)
2177 --lnum;
2178 }
2179
2180 generate_PUT(cctx, eap->regname, lnum);
2181 return line;
2182}
2183
2184/*
2185 * A command that is not compiled, execute with legacy code.
2186 */
2187 char_u *
2188compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx)
2189{
2190 char_u *line = line_arg;
2191 char_u *p;
2192 int has_expr = FALSE;
2193 char_u *nextcmd = (char_u *)"";
2194 char_u *tofree = NULL;
2195 char_u *cmd_arg = NULL;
2196
2197 if (cctx->ctx_skip == SKIP_YES)
2198 goto theend;
2199
2200 // If there was a prececing command modifier, drop it and include it in the
2201 // EXEC command.
2202 if (cctx->ctx_has_cmdmod)
2203 {
2204 garray_T *instr = &cctx->ctx_instr;
2205 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2206
2207 if (isn->isn_type == ISN_CMDMOD)
2208 {
2209 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2210 ->cmod_filter_regmatch.regprog);
2211 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2212 --instr->ga_len;
2213 cctx->ctx_has_cmdmod = FALSE;
2214 }
2215 }
2216
2217 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
2218 {
2219 long argt = eap->argt;
2220 int usefilter = FALSE;
2221
2222 has_expr = argt & (EX_XFILE | EX_EXPAND);
2223
2224 // If the command can be followed by a bar, find the bar and truncate
2225 // it, so that the following command can be compiled.
2226 // The '|' is overwritten with a NUL, it is put back below.
2227 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
2228 && *eap->arg == '!')
2229 // :w !filter or :r !filter or :r! filter
2230 usefilter = TRUE;
2231 if ((argt & EX_TRLBAR) && !usefilter)
2232 {
2233 eap->argt = argt;
Bram Moolenaarac485062022-03-23 19:45:01 +00002234 separate_nextcmd(eap, TRUE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002235 if (eap->nextcmd != NULL)
2236 nextcmd = eap->nextcmd;
2237 }
2238 else if (eap->cmdidx == CMD_wincmd)
2239 {
2240 p = eap->arg;
2241 if (*p != NUL)
2242 ++p;
2243 if (*p == 'g' || *p == Ctrl_G)
2244 ++p;
2245 p = skipwhite(p);
2246 if (*p == '|')
2247 {
2248 *p = NUL;
2249 nextcmd = p + 1;
2250 }
2251 }
2252 else if (eap->cmdidx == CMD_command || eap->cmdidx == CMD_autocmd)
2253 {
2254 // If there is a trailing '{' read lines until the '}'
2255 p = eap->arg + STRLEN(eap->arg) - 1;
2256 while (p > eap->arg && VIM_ISWHITE(*p))
2257 --p;
2258 if (*p == '{')
2259 {
2260 exarg_T ea;
Bram Moolenaar62628d92022-02-25 21:10:53 +00002261 int flags = 0; // unused
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002262 int start_lnum = SOURCING_LNUM;
2263
2264 CLEAR_FIELD(ea);
2265 ea.arg = eap->arg;
2266 fill_exarg_from_cctx(&ea, cctx);
2267 (void)may_get_cmd_block(&ea, p, &tofree, &flags);
2268 if (tofree != NULL)
2269 {
2270 *p = NUL;
2271 line = concat_str(line, tofree);
2272 if (line == NULL)
2273 goto theend;
2274 vim_free(tofree);
2275 tofree = line;
2276 SOURCING_LNUM = start_lnum;
2277 }
2278 }
2279 }
2280 }
2281
2282 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
2283 {
2284 // expand filename in "syntax include [@group] filename"
2285 has_expr = TRUE;
2286 eap->arg = skipwhite(eap->arg + 7);
2287 if (*eap->arg == '@')
2288 eap->arg = skiptowhite(eap->arg);
2289 }
2290
2291 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
2292 && STRLEN(eap->arg) > 4)
2293 {
2294 int delim = *eap->arg;
2295
2296 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
2297 if (*p == delim)
2298 cmd_arg = p + 1;
2299 }
2300
2301 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
2302 cmd_arg = eap->arg;
2303
2304 if (cmd_arg != NULL)
2305 {
2306 exarg_T nea;
2307
2308 CLEAR_FIELD(nea);
2309 nea.cmd = cmd_arg;
2310 p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL);
2311 if (nea.cmdidx < CMD_SIZE)
2312 {
2313 has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND);
2314 if (has_expr)
2315 eap->arg = skiptowhite(eap->arg);
2316 }
2317 }
2318
2319 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
2320 {
2321 int count = 0;
2322 char_u *start = skipwhite(line);
2323
2324 // :cmd xxx`=expr1`yyy`=expr2`zzz
2325 // PUSHS ":cmd xxx"
2326 // eval expr1
2327 // PUSHS "yyy"
2328 // eval expr2
2329 // PUSHS "zzz"
2330 // EXECCONCAT 5
2331 for (;;)
2332 {
2333 if (p > start)
2334 {
2335 char_u *val = vim_strnsave(start, p - start);
2336
2337 generate_PUSHS(cctx, &val);
2338 ++count;
2339 }
2340 p += 2;
2341 if (compile_expr0(&p, cctx) == FAIL)
2342 return NULL;
2343 may_generate_2STRING(-1, TRUE, cctx);
2344 ++count;
2345 p = skipwhite(p);
2346 if (*p != '`')
2347 {
2348 emsg(_(e_missing_backtick));
2349 return NULL;
2350 }
2351 start = p + 1;
2352
2353 p = (char_u *)strstr((char *)start, "`=");
2354 if (p == NULL)
2355 {
2356 if (*skipwhite(start) != NUL)
2357 {
2358 char_u *val = vim_strsave(start);
2359
2360 generate_PUSHS(cctx, &val);
2361 ++count;
2362 }
2363 break;
2364 }
2365 }
2366 generate_EXECCONCAT(cctx, count);
2367 }
2368 else
2369 generate_EXEC_copy(cctx, ISN_EXEC, line);
2370
2371theend:
2372 if (*nextcmd != NUL)
2373 {
2374 // the parser expects a pointer to the bar, put it back
2375 --nextcmd;
2376 *nextcmd = '|';
2377 }
2378 vim_free(tofree);
2379
2380 return nextcmd;
2381}
2382
2383/*
2384 * A script command with heredoc, e.g.
2385 * ruby << EOF
2386 * command
2387 * EOF
2388 * Has been turned into one long line with NL characters by
2389 * get_function_body():
2390 * ruby << EOF<NL> command<NL>EOF
2391 */
2392 char_u *
2393compile_script(char_u *line, cctx_T *cctx)
2394{
2395 if (cctx->ctx_skip != SKIP_YES)
2396 {
2397 isn_T *isn;
2398
2399 if ((isn = generate_instr(cctx, ISN_EXEC_SPLIT)) == NULL)
2400 return NULL;
2401 isn->isn_arg.string = vim_strsave(line);
2402 }
2403 return (char_u *)"";
2404}
2405
2406
2407/*
2408 * :s/pat/repl/
2409 */
2410 char_u *
2411compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
2412{
2413 char_u *cmd = eap->arg;
2414 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
2415
2416 if (expr != NULL)
2417 {
2418 int delimiter = *cmd++;
2419
2420 // There is a \=expr, find it in the substitute part.
2421 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
2422 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
2423 {
2424 garray_T save_ga = cctx->ctx_instr;
2425 char_u *end;
2426 int expr_res;
2427 int trailing_error;
2428 int instr_count;
2429 isn_T *instr;
2430 isn_T *isn;
2431
2432 cmd += 3;
2433 end = skip_substitute(cmd, delimiter);
2434
2435 // Temporarily reset the list of instructions so that the jump
2436 // labels are correct.
2437 cctx->ctx_instr.ga_len = 0;
2438 cctx->ctx_instr.ga_maxlen = 0;
2439 cctx->ctx_instr.ga_data = NULL;
2440 expr_res = compile_expr0(&cmd, cctx);
2441 if (end[-1] == NUL)
2442 end[-1] = delimiter;
2443 cmd = skipwhite(cmd);
2444 trailing_error = *cmd != delimiter && *cmd != NUL;
2445
2446 if (expr_res == FAIL || trailing_error
2447 || GA_GROW_FAILS(&cctx->ctx_instr, 1))
2448 {
2449 if (trailing_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00002450 semsg(_(e_trailing_characters_str), cmd);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002451 clear_instr_ga(&cctx->ctx_instr);
2452 cctx->ctx_instr = save_ga;
2453 return NULL;
2454 }
2455
2456 // Move the generated instructions into the ISN_SUBSTITUTE
2457 // instructions, then restore the list of instructions before
2458 // adding the ISN_SUBSTITUTE instruction.
2459 instr_count = cctx->ctx_instr.ga_len;
2460 instr = cctx->ctx_instr.ga_data;
2461 instr[instr_count].isn_type = ISN_FINISH;
2462
2463 cctx->ctx_instr = save_ga;
2464 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2465 {
2466 int idx;
2467
2468 for (idx = 0; idx < instr_count; ++idx)
2469 delete_instr(instr + idx);
2470 vim_free(instr);
2471 return NULL;
2472 }
2473 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
2474 isn->isn_arg.subs.subs_instr = instr;
2475
2476 // skip over flags
2477 if (*end == '&')
2478 ++end;
2479 while (ASCII_ISALPHA(*end) || *end == '#')
2480 ++end;
2481 return end;
2482 }
2483 }
2484
2485 return compile_exec(arg, eap, cctx);
2486}
2487
2488 char_u *
2489compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
2490{
2491 char_u *arg = eap->arg;
2492 lhs_T *lhs = &cctx->ctx_redir_lhs;
2493
2494 if (lhs->lhs_name != NULL)
2495 {
2496 if (STRNCMP(arg, "END", 3) == 0)
2497 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002498 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002499 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002500 if (lhs->lhs_append)
2501 {
2502 // First load the current variable value.
2503 if (compile_load_lhs_with_index(lhs, lhs->lhs_whole,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002504 cctx) == FAIL)
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002505 return NULL;
2506 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002507
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002508 // Gets the redirected text and put it on the stack, then store
2509 // it in the variable.
2510 generate_instr_type(cctx, ISN_REDIREND, &t_string);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002511
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002512 if (lhs->lhs_append)
2513 generate_CONCAT(cctx, 2);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002514
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002515 if (lhs->lhs_has_index)
2516 {
2517 // Use the info in "lhs" to store the value at the index in
2518 // the list or dict.
2519 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002520 &t_string, cctx) == FAIL)
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002521 return NULL;
2522 }
2523 else if (generate_store_lhs(cctx, lhs, -1, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002524 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002525
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002526 VIM_CLEAR(lhs->lhs_name);
2527 VIM_CLEAR(lhs->lhs_whole);
2528 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002529 return arg + 3;
2530 }
2531 emsg(_(e_cannot_nest_redir));
2532 return NULL;
2533 }
2534
2535 if (arg[0] == '=' && arg[1] == '>')
2536 {
2537 int append = FALSE;
2538
2539 // redirect to a variable is compiled
2540 arg += 2;
2541 if (*arg == '>')
2542 {
2543 ++arg;
2544 append = TRUE;
2545 }
2546 arg = skipwhite(arg);
2547
2548 if (compile_assign_lhs(arg, lhs, CMD_redir,
Bram Moolenaar97f8c102022-04-02 19:43:57 +01002549 FALSE, FALSE, FALSE, 1, cctx) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002550 return NULL;
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002551 if (need_type(&t_string, lhs->lhs_member_type, FALSE,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002552 -1, 0, cctx, FALSE, FALSE) == FAIL)
2553 return NULL;
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002554 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002555 {
Bram Moolenaar3558afe2022-10-13 16:12:57 +01002556 VIM_CLEAR(lhs->lhs_name);
2557 }
2558 else
2559 {
2560 generate_instr(cctx, ISN_REDIRSTART);
2561 lhs->lhs_append = append;
2562 if (lhs->lhs_has_index)
2563 {
2564 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
2565 if (lhs->lhs_whole == NULL)
2566 return NULL;
2567 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002568 }
2569
2570 return arg + lhs->lhs_varlen_total;
2571 }
2572
2573 // other redirects are handled like at script level
2574 return compile_exec(line, eap, cctx);
2575}
2576
2577#if defined(FEAT_QUICKFIX) || defined(PROTO)
2578 char_u *
2579compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx)
2580{
2581 isn_T *isn;
2582 char_u *p;
2583
2584 isn = generate_instr(cctx, ISN_CEXPR_AUCMD);
2585 if (isn == NULL)
2586 return NULL;
2587 isn->isn_arg.number = eap->cmdidx;
2588
2589 p = eap->arg;
2590 if (compile_expr0(&p, cctx) == FAIL)
2591 return NULL;
2592
2593 isn = generate_instr(cctx, ISN_CEXPR_CORE);
2594 if (isn == NULL)
2595 return NULL;
2596 isn->isn_arg.cexpr.cexpr_ref = ALLOC_ONE(cexprref_T);
2597 if (isn->isn_arg.cexpr.cexpr_ref == NULL)
2598 return NULL;
2599 isn->isn_arg.cexpr.cexpr_ref->cer_cmdidx = eap->cmdidx;
2600 isn->isn_arg.cexpr.cexpr_ref->cer_forceit = eap->forceit;
2601 isn->isn_arg.cexpr.cexpr_ref->cer_cmdline = vim_strsave(skipwhite(line));
2602
2603 return p;
2604}
2605#endif
2606
2607/*
2608 * Compile "return [expr]".
2609 * When "legacy" is TRUE evaluate [expr] with legacy syntax
2610 */
2611 char_u *
2612compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
2613{
2614 char_u *p = arg;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002615 type_T *stack_type;
2616
mityu500c4442022-12-02 18:12:05 +00002617 if (*p != NUL && *p != '|' && *p != '\n'
2618 && (legacy || !vim9_comment_start(p)))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002619 {
Bram Moolenaar0bfa8492022-01-22 12:27:04 +00002620 // For a lambda, "return expr" is always used, also when "expr" results
2621 // in a void.
2622 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
2623 && (cctx->ctx_ufunc->uf_flags & FC_LAMBDA) == 0)
Bram Moolenaaref7aadb2022-01-18 18:46:07 +00002624 {
2625 emsg(_(e_returning_value_in_function_without_return_type));
2626 return NULL;
2627 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002628 if (legacy)
2629 {
2630 int save_flags = cmdmod.cmod_flags;
2631
2632 generate_LEGACY_EVAL(cctx, p);
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002633 if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, FALSE, -1,
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002634 0, cctx, FALSE, FALSE) == FAIL)
2635 return NULL;
2636 cmdmod.cmod_flags |= CMOD_LEGACY;
2637 (void)skip_expr(&p, NULL);
2638 cmdmod.cmod_flags = save_flags;
2639 }
2640 else
2641 {
2642 // compile return argument into instructions
2643 if (compile_expr0(&p, cctx) == FAIL)
2644 return NULL;
2645 }
2646
2647 if (cctx->ctx_skip != SKIP_YES)
2648 {
2649 // "check_return_type" with uf_ret_type set to &t_unknown is used
2650 // for an inline function without a specified return type. Set the
2651 // return type here.
Bram Moolenaar078a4612022-01-04 15:17:03 +00002652 stack_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002653 if ((check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar1a572e92022-03-15 12:28:10 +00002654 || cctx->ctx_ufunc->uf_ret_type == &t_unknown))
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002655 || (!check_return_type
2656 && cctx->ctx_ufunc->uf_ret_type == &t_unknown))
2657 {
2658 cctx->ctx_ufunc->uf_ret_type = stack_type;
2659 }
2660 else
2661 {
Bram Moolenaarc6951a72022-12-29 20:56:24 +00002662 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, FALSE,
2663 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002664 return NULL;
2665 }
2666 }
2667 }
2668 else
2669 {
2670 // "check_return_type" cannot be TRUE, only used for a lambda which
2671 // always has an argument.
2672 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
2673 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
2674 {
2675 emsg(_(e_missing_return_value));
2676 return NULL;
2677 }
2678
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02002679 if (IS_CONSTRUCTOR_METHOD(cctx->ctx_ufunc))
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002680 {
2681 // For a class new() constructor, return an object of the class.
2682 generate_instr(cctx, ISN_RETURN_OBJECT);
2683 cctx->ctx_ufunc->uf_ret_type =
2684 &cctx->ctx_ufunc->uf_class->class_object_type;
2685 }
2686 else
2687 // No argument, return zero.
2688 generate_PUSHNR(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002689 }
2690
Bram Moolenaar8abb5842022-09-17 12:39:58 +01002691 // may need ENDLOOP when inside a :for or :while loop
2692 if (compile_find_scope(NULL, NULL, NULL, NULL, cctx) == FAIL)
2693
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002694 // Undo any command modifiers.
2695 generate_undo_cmdmods(cctx);
2696
2697 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
2698 return NULL;
2699
2700 // "return val | endif" is possible
2701 return skipwhite(p);
2702}
2703
2704/*
2705 * Check if the separator for a :global or :substitute command is OK.
2706 */
2707 int
2708check_global_and_subst(char_u *cmd, char_u *arg)
2709{
2710 if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL)
2711 {
2712 semsg(_(e_separator_not_supported_str), arg);
2713 return FAIL;
2714 }
2715 if (VIM_ISWHITE(cmd[1]))
2716 {
2717 semsg(_(e_no_white_space_allowed_before_separator_str), cmd);
2718 return FAIL;
2719 }
2720 return OK;
2721}
2722
2723
2724#endif // defined(FEAT_EVAL)