(
&mut self,
body: &[ast::Stmt],
handlers: &[ast::ExceptHandler],
orelse: &[ast::Stmt],
finalbody: &[ast::Stmt],
)
| 3020 | } |
| 3021 | |
| 3022 | fn compile_try_statement( |
| 3023 | &mut self, |
| 3024 | body: &[ast::Stmt], |
| 3025 | handlers: &[ast::ExceptHandler], |
| 3026 | orelse: &[ast::Stmt], |
| 3027 | finalbody: &[ast::Stmt], |
| 3028 | ) -> CompileResult<()> { |
| 3029 | if finalbody.is_empty() { |
| 3030 | return self.compile_try_except_no_finally(body, handlers, orelse); |
| 3031 | } |
| 3032 | |
| 3033 | let handler_block = self.new_block(); |
| 3034 | let finally_block = self.new_block(); |
| 3035 | |
| 3036 | // finally needs TWO blocks: |
| 3037 | // - finally_block: normal path (no exception active) |
| 3038 | // - finally_except_block: exception path (PUSH_EXC_INFO -> body -> RERAISE) |
| 3039 | let finally_except_block = if !finalbody.is_empty() { |
| 3040 | Some(self.new_block()) |
| 3041 | } else { |
| 3042 | None |
| 3043 | }; |
| 3044 | let finally_cleanup_block = if finally_except_block.is_some() { |
| 3045 | Some(self.new_block()) |
| 3046 | } else { |
| 3047 | None |
| 3048 | }; |
| 3049 | // End block - continuation point after try-finally |
| 3050 | // Normal path jumps here to skip exception path blocks |
| 3051 | let end_block = self.new_block(); |
| 3052 | |
| 3053 | // Emit NOP at the try: line so LINE events fire for it |
| 3054 | emit!(self, Instruction::Nop); |
| 3055 | |
| 3056 | // Setup a finally block if we have a finally statement. |
| 3057 | // Push fblock with handler info for exception table generation |
| 3058 | // IMPORTANT: handler goes to finally_except_block (exception path), not finally_block |
| 3059 | if !finalbody.is_empty() { |
| 3060 | // SETUP_FINALLY doesn't push lasti for try body handler |
| 3061 | // Exception table: L1 to L2 -> L4 [1] (no lasti) |
| 3062 | let setup_target = finally_except_block.unwrap_or(finally_block); |
| 3063 | emit!( |
| 3064 | self, |
| 3065 | PseudoInstruction::SetupFinally { |
| 3066 | delta: setup_target |
| 3067 | } |
| 3068 | ); |
| 3069 | // Store finally body in fb_datum for unwind_fblock to compile inline |
| 3070 | self.push_fblock_full( |
| 3071 | FBlockType::FinallyTry, |
| 3072 | finally_block, |
| 3073 | finally_block, |
| 3074 | FBlockDatum::FinallyBody(finalbody.to_vec()), // Clone finally body for unwind |
| 3075 | )?; |
| 3076 | } |
| 3077 | |
| 3078 | let else_block = self.new_block(); |
| 3079 |
no test coverage detected