comparison src/vim9execute.c @ 23927:5e5780e3f75d v8.2.2506

patch 8.2.2506: Vim9: :continue does not work correctly in a :try block Commit: https://github.com/vim/vim/commit/c150c09ec4f97636c6339f5687fdaa9f665095d2 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 13 15:02:46 2021 +0100 patch 8.2.2506: Vim9: :continue does not work correctly in a :try block Problem: Vim9: :continue does not work correctly in a :try block Solution: Add the TRYCLEANUP instruction. (closes https://github.com/vim/vim/issues/7827)
author Bram Moolenaar <Bram@vim.org>
date Sat, 13 Feb 2021 15:15:03 +0100
parents a834f9c082e3
children f9a4ede76237
comparison
equal deleted inserted replaced
23926:1a41fde53816 23927:5e5780e3f75d
25 // Structure put on ec_trystack when ISN_TRY is encountered. 25 // Structure put on ec_trystack when ISN_TRY is encountered.
26 typedef struct { 26 typedef struct {
27 int tcd_frame_idx; // ec_frame_idx at ISN_TRY 27 int tcd_frame_idx; // ec_frame_idx at ISN_TRY
28 int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY 28 int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY
29 int tcd_catch_idx; // instruction of the first catch 29 int tcd_catch_idx; // instruction of the first catch
30 int tcd_finally_idx; // instruction of the finally block 30 int tcd_finally_idx; // instruction of the finally block or :endtry
31 int tcd_caught; // catch block entered 31 int tcd_caught; // catch block entered
32 int tcd_cont; // :continue encountered, jump here
32 int tcd_return; // when TRUE return from end of :finally 33 int tcd_return; // when TRUE return from end of :finally
33 } trycmd_T; 34 } trycmd_T;
34 35
35 36
36 // A stack is used to store: 37 // A stack is used to store:
2415 if (trystack->ga_len > 0) 2416 if (trystack->ga_len > 0)
2416 trycmd = ((trycmd_T *)trystack->ga_data) 2417 trycmd = ((trycmd_T *)trystack->ga_data)
2417 + trystack->ga_len - 1; 2418 + trystack->ga_len - 1;
2418 if (trycmd != NULL 2419 if (trycmd != NULL
2419 && trycmd->tcd_frame_idx == ectx.ec_frame_idx 2420 && trycmd->tcd_frame_idx == ectx.ec_frame_idx
2420 && trycmd->tcd_finally_idx != 0) 2421 && ectx.ec_instr[trycmd->tcd_finally_idx]
2422 .isn_type != ISN_ENDTRY)
2421 { 2423 {
2422 // jump to ":finally" 2424 // jump to ":finally"
2423 ectx.ec_iidx = trycmd->tcd_finally_idx; 2425 ectx.ec_iidx = trycmd->tcd_finally_idx;
2424 trycmd->tcd_return = TRUE; 2426 trycmd->tcd_return = TRUE;
2425 } 2427 }
2608 force_abort = need_rethrow = FALSE; 2610 force_abort = need_rethrow = FALSE;
2609 catch_exception(current_exception); 2611 catch_exception(current_exception);
2610 } 2612 }
2611 break; 2613 break;
2612 2614
2615 case ISN_TRYCONT:
2616 {
2617 garray_T *trystack = &ectx.ec_trystack;
2618 trycont_T *trycont = &iptr->isn_arg.trycont;
2619 int i;
2620 trycmd_T *trycmd;
2621 int iidx = trycont->tct_where;
2622
2623 if (trystack->ga_len < trycont->tct_levels)
2624 {
2625 siemsg("TRYCONT: expected %d levels, found %d",
2626 trycont->tct_levels, trystack->ga_len);
2627 goto failed;
2628 }
2629 // Make :endtry jump to any outer try block and the last
2630 // :endtry inside the loop to the loop start.
2631 for (i = trycont->tct_levels; i > 0; --i)
2632 {
2633 trycmd = ((trycmd_T *)trystack->ga_data)
2634 + trystack->ga_len - i;
2635 trycmd->tcd_cont = iidx;
2636 iidx = trycmd->tcd_finally_idx;
2637 }
2638 // jump to :finally or :endtry of current try statement
2639 ectx.ec_iidx = iidx;
2640 }
2641 break;
2642
2613 // end of ":try" block 2643 // end of ":try" block
2614 case ISN_ENDTRY: 2644 case ISN_ENDTRY:
2615 { 2645 {
2616 garray_T *trystack = &ectx.ec_trystack; 2646 garray_T *trystack = &ectx.ec_trystack;
2617 2647
2638 while (ectx.ec_stack.ga_len > trycmd->tcd_stack_len) 2668 while (ectx.ec_stack.ga_len > trycmd->tcd_stack_len)
2639 { 2669 {
2640 --ectx.ec_stack.ga_len; 2670 --ectx.ec_stack.ga_len;
2641 clear_tv(STACK_TV_BOT(0)); 2671 clear_tv(STACK_TV_BOT(0));
2642 } 2672 }
2673 if (trycmd->tcd_cont)
2674 // handling :continue: jump to outer try block or
2675 // start of the loop
2676 ectx.ec_iidx = trycmd->tcd_cont;
2643 } 2677 }
2644 } 2678 }
2645 break; 2679 break;
2646 2680
2647 case ISN_THROW: 2681 case ISN_THROW:
4211 4245
4212 case ISN_TRY: 4246 case ISN_TRY:
4213 { 4247 {
4214 try_T *try = &iptr->isn_arg.try; 4248 try_T *try = &iptr->isn_arg.try;
4215 4249
4216 smsg("%4d TRY catch -> %d, finally -> %d", current, 4250 smsg("%4d TRY catch -> %d, %s -> %d", current,
4217 try->try_catch, try->try_finally); 4251 try->try_catch,
4252 instr[try->try_finally].isn_type == ISN_ENDTRY
4253 ? "end" : "finally",
4254 try->try_finally);
4218 } 4255 }
4219 break; 4256 break;
4220 case ISN_CATCH: 4257 case ISN_CATCH:
4221 // TODO 4258 // TODO
4222 smsg("%4d CATCH", current); 4259 smsg("%4d CATCH", current);
4260 break;
4261 case ISN_TRYCONT:
4262 {
4263 trycont_T *trycont = &iptr->isn_arg.trycont;
4264
4265 smsg("%4d TRY-CONTINUE %d level%s -> %d", current,
4266 trycont->tct_levels,
4267 trycont->tct_levels == 1 ? "" : "s",
4268 trycont->tct_where);
4269 }
4223 break; 4270 break;
4224 case ISN_ENDTRY: 4271 case ISN_ENDTRY:
4225 smsg("%4d ENDTRY", current); 4272 smsg("%4d ENDTRY", current);
4226 break; 4273 break;
4227 case ISN_THROW: 4274 case ISN_THROW: