@@ -46,6 +46,11 @@ enum BlockType {
4646 Finally {
4747 handler : bytecode:: Label ,
4848 } ,
49+
50+ /// Active finally sequence
51+ FinallyHandler {
52+ reason : Option < UnwindReason > ,
53+ } ,
4954 With {
5055 end : bytecode:: Label ,
5156 context_manager : PyObjectRef ,
@@ -58,6 +63,7 @@ pub type FrameRef = PyRef<Frame>;
5863/// The reason why we might be unwinding a block.
5964/// This could be return of function, exception being
6065/// raised, a break or continue being hit, etc..
66+ #[ derive( Clone , Debug ) ]
6167enum UnwindReason {
6268 /// We are returning a value from a return statement.
6369 Returning { value : PyObjectRef } ,
@@ -407,10 +413,27 @@ impl Frame {
407413 self . push_block ( BlockType :: Finally { handler : * handler } ) ;
408414 Ok ( None )
409415 }
410- bytecode:: Instruction :: EndFinally => {
411- let _block = self . pop_block ( ) . unwrap ( ) ;
416+ bytecode:: Instruction :: EnterFinally => {
417+ self . push_block ( BlockType :: FinallyHandler { reason : None } ) ;
412418 Ok ( None )
413419 }
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+ }
414437 bytecode:: Instruction :: SetupWith { end } => {
415438 let context_manager = self . pop_value ( ) ;
416439 // Call enter:
@@ -423,7 +446,7 @@ impl Frame {
423446 Ok ( None )
424447 }
425448 bytecode:: Instruction :: CleanupWith { end : end1 } => {
426- let block = self . pop_block ( ) . unwrap ( ) ;
449+ let block = self . pop_block ( ) ;
427450 if let BlockType :: With {
428451 end : end2,
429452 context_manager,
@@ -438,7 +461,7 @@ impl Frame {
438461 Ok ( None )
439462 }
440463 bytecode:: Instruction :: PopBlock => {
441- self . pop_block ( ) . expect ( "no pop to block" ) ;
464+ self . pop_block ( ) ;
442465 Ok ( None )
443466 }
444467 bytecode:: Instruction :: GetIter => {
@@ -687,7 +710,7 @@ impl Frame {
687710 Ok ( None )
688711 }
689712 bytecode:: Instruction :: PopException { } => {
690- let block = self . pop_block ( ) . unwrap ( ) ; // this asserts that the block is_some.
713+ let block = self . pop_block ( ) ;
691714 if let BlockType :: ExceptHandler = block. typ {
692715 vm. pop_exception ( ) . expect ( "Should have exception in stack" ) ;
693716 Ok ( None )
@@ -781,7 +804,7 @@ impl Frame {
781804 match block. typ {
782805 BlockType :: Loop { start, end } => match & reason {
783806 UnwindReason :: Break => {
784- self . pop_block ( ) . unwrap ( ) ;
807+ self . pop_block ( ) ;
785808 self . jump ( end) ;
786809 return Ok ( None ) ;
787810 }
@@ -790,33 +813,32 @@ impl Frame {
790813 return Ok ( None ) ;
791814 }
792815 _ => {
793- self . pop_block ( ) . unwrap ( ) ;
816+ self . pop_block ( ) ;
794817 }
795818 } ,
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 ) ;
799826 }
800827 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 ) ;
813835 }
814836 }
815837 BlockType :: With {
816838 context_manager,
817839 end,
818840 } => {
819- self . pop_block ( ) . unwrap ( ) ;
841+ self . pop_block ( ) ;
820842 match & reason {
821843 UnwindReason :: Raising { exception } => {
822844 match self . call_context_manager_exit (
@@ -866,8 +888,11 @@ impl Frame {
866888 }
867889 }
868890 }
891+ BlockType :: FinallyHandler { .. } => {
892+ self . pop_block ( ) ;
893+ }
869894 BlockType :: ExceptHandler => {
870- self . pop_block ( ) . unwrap ( ) ;
895+ self . pop_block ( ) ;
871896 vm. pop_exception ( ) . expect ( "Should have exception in stack" ) ;
872897 }
873898 }
@@ -881,8 +906,6 @@ impl Frame {
881906 panic ! ( "Internal error: break or continue must occur within a loop block." )
882907 } // UnwindReason::NoWorries => Ok(None),
883908 }
884-
885- // None
886909 }
887910
888911 fn call_context_manager_exit (
@@ -1193,10 +1216,14 @@ impl Frame {
11931216 } ) ;
11941217 }
11951218
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!" ) ;
11981225 self . stack . borrow_mut ( ) . truncate ( block. level ) ;
1199- Some ( block)
1226+ block
12001227 }
12011228
12021229 fn current_block ( & self ) -> Option < Block > {
0 commit comments