@@ -46,6 +46,11 @@ enum BlockType {
46
46
Finally {
47
47
handler : bytecode:: Label ,
48
48
} ,
49
+
50
+ /// Active finally sequence
51
+ FinallyHandler {
52
+ reason : Option < UnwindReason > ,
53
+ } ,
49
54
With {
50
55
end : bytecode:: Label ,
51
56
context_manager : PyObjectRef ,
@@ -58,6 +63,7 @@ pub type FrameRef = PyRef<Frame>;
58
63
/// The reason why we might be unwinding a block.
59
64
/// This could be return of function, exception being
60
65
/// raised, a break or continue being hit, etc..
66
+ #[ derive( Clone , Debug ) ]
61
67
enum UnwindReason {
62
68
/// We are returning a value from a return statement.
63
69
Returning { value : PyObjectRef } ,
@@ -407,10 +413,27 @@ impl Frame {
407
413
self . push_block ( BlockType :: Finally { handler : * handler } ) ;
408
414
Ok ( None )
409
415
}
410
- bytecode:: Instruction :: EndFinally => {
411
- let _block = self . pop_block ( ) . unwrap ( ) ;
416
+ bytecode:: Instruction :: EnterFinally => {
417
+ self . push_block ( BlockType :: FinallyHandler { reason : None } ) ;
412
418
Ok ( None )
413
419
}
420
+ bytecode:: Instruction :: EndFinally => {
421
+ // Pop the finally handler from the stack, and recall
422
+ // what was the reason we were in this finally clause.
423
+ let block = self . pop_block ( ) ;
424
+
425
+ if let BlockType :: FinallyHandler { reason } = block. typ {
426
+ if let Some ( reason) = reason {
427
+ self . unwind_blocks ( vm, reason)
428
+ } else {
429
+ Ok ( None )
430
+ }
431
+ } else {
432
+ panic ! (
433
+ "Block type must be finally handler when reaching EndFinally instruction!"
434
+ ) ;
435
+ }
436
+ }
414
437
bytecode:: Instruction :: SetupWith { end } => {
415
438
let context_manager = self . pop_value ( ) ;
416
439
// Call enter:
@@ -423,7 +446,7 @@ impl Frame {
423
446
Ok ( None )
424
447
}
425
448
bytecode:: Instruction :: CleanupWith { end : end1 } => {
426
- let block = self . pop_block ( ) . unwrap ( ) ;
449
+ let block = self . pop_block ( ) ;
427
450
if let BlockType :: With {
428
451
end : end2,
429
452
context_manager,
@@ -438,7 +461,7 @@ impl Frame {
438
461
Ok ( None )
439
462
}
440
463
bytecode:: Instruction :: PopBlock => {
441
- self . pop_block ( ) . expect ( "no pop to block" ) ;
464
+ self . pop_block ( ) ;
442
465
Ok ( None )
443
466
}
444
467
bytecode:: Instruction :: GetIter => {
@@ -687,7 +710,7 @@ impl Frame {
687
710
Ok ( None )
688
711
}
689
712
bytecode:: Instruction :: PopException { } => {
690
- let block = self . pop_block ( ) . unwrap ( ) ; // this asserts that the block is_some.
713
+ let block = self . pop_block ( ) ;
691
714
if let BlockType :: ExceptHandler = block. typ {
692
715
vm. pop_exception ( ) . expect ( "Should have exception in stack" ) ;
693
716
Ok ( None )
@@ -781,7 +804,7 @@ impl Frame {
781
804
match block. typ {
782
805
BlockType :: Loop { start, end } => match & reason {
783
806
UnwindReason :: Break => {
784
- self . pop_block ( ) . unwrap ( ) ;
807
+ self . pop_block ( ) ;
785
808
self . jump ( end) ;
786
809
return Ok ( None ) ;
787
810
}
@@ -790,33 +813,32 @@ impl Frame {
790
813
return Ok ( None ) ;
791
814
}
792
815
_ => {
793
- self . pop_block ( ) . unwrap ( ) ;
816
+ self . pop_block ( ) ;
794
817
}
795
818
} ,
796
- BlockType :: Finally { .. } => {
797
- self . pop_block ( ) . unwrap ( ) ;
798
- // TODO!
819
+ BlockType :: Finally { handler } => {
820
+ self . pop_block ( ) ;
821
+ self . push_block ( BlockType :: FinallyHandler {
822
+ reason : Some ( reason. clone ( ) ) ,
823
+ } ) ;
824
+ self . jump ( handler) ;
825
+ return Ok ( None ) ;
799
826
}
800
827
BlockType :: TryExcept { handler } => {
801
- self . pop_block ( ) . unwrap ( ) ;
802
- match & reason {
803
- UnwindReason :: Raising { exception } => {
804
- self . push_block ( BlockType :: ExceptHandler { } ) ;
805
- self . push_value ( exception. clone ( ) ) ;
806
- vm. push_exception ( exception. clone ( ) ) ;
807
- self . jump ( handler) ;
808
- return Ok ( None ) ;
809
- }
810
- _ => {
811
- // No worries!
812
- }
828
+ self . pop_block ( ) ;
829
+ if let UnwindReason :: Raising { exception } = & reason {
830
+ self . push_block ( BlockType :: ExceptHandler { } ) ;
831
+ self . push_value ( exception. clone ( ) ) ;
832
+ vm. push_exception ( exception. clone ( ) ) ;
833
+ self . jump ( handler) ;
834
+ return Ok ( None ) ;
813
835
}
814
836
}
815
837
BlockType :: With {
816
838
context_manager,
817
839
end,
818
840
} => {
819
- self . pop_block ( ) . unwrap ( ) ;
841
+ self . pop_block ( ) ;
820
842
match & reason {
821
843
UnwindReason :: Raising { exception } => {
822
844
match self . call_context_manager_exit (
@@ -866,8 +888,11 @@ impl Frame {
866
888
}
867
889
}
868
890
}
891
+ BlockType :: FinallyHandler { .. } => {
892
+ self . pop_block ( ) ;
893
+ }
869
894
BlockType :: ExceptHandler => {
870
- self . pop_block ( ) . unwrap ( ) ;
895
+ self . pop_block ( ) ;
871
896
vm. pop_exception ( ) . expect ( "Should have exception in stack" ) ;
872
897
}
873
898
}
@@ -881,8 +906,6 @@ impl Frame {
881
906
panic ! ( "Internal error: break or continue must occur within a loop block." )
882
907
} // UnwindReason::NoWorries => Ok(None),
883
908
}
884
-
885
- // None
886
909
}
887
910
888
911
fn call_context_manager_exit (
@@ -1193,10 +1216,14 @@ impl Frame {
1193
1216
} ) ;
1194
1217
}
1195
1218
1196
- fn pop_block ( & self ) -> Option < Block > {
1197
- let block = self . blocks . borrow_mut ( ) . pop ( ) ?;
1219
+ fn pop_block ( & self ) -> Block {
1220
+ let block = self
1221
+ . blocks
1222
+ . borrow_mut ( )
1223
+ . pop ( )
1224
+ . expect ( "No more blocks to pop!" ) ;
1198
1225
self . stack . borrow_mut ( ) . truncate ( block. level ) ;
1199
- Some ( block)
1226
+ block
1200
1227
}
1201
1228
1202
1229
fn current_block ( & self ) -> Option < Block > {
0 commit comments