Skip to content

Commit 86fc18e

Browse files
committed
Refactor block stack unwinding to enable finally execution.
1 parent 9168455 commit 86fc18e

File tree

3 files changed

+172
-129
lines changed

3 files changed

+172
-129
lines changed

bytecode/src/bytecode.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ pub enum Instruction {
178178
start: Label,
179179
end: Label,
180180
},
181+
182+
/// Setup a finally handler, which will be called whenever one of this events occurs:
183+
/// - the block is popped
184+
/// - the function returns
185+
/// - an exception is returned
186+
SetupFinally {
187+
handler: Label,
188+
},
189+
190+
/// Marker bytecode for the end of a finally sequence.
191+
/// When this bytecode is executed, the eval loop does one of those things:
192+
/// - Continue at a certain bytecode position
193+
/// - Propagate the exception
194+
/// - Return from a function
195+
EndFinally,
196+
181197
SetupExcept {
182198
handler: Label,
183199
},
@@ -475,7 +491,9 @@ impl Instruction {
475491
YieldValue => w!(YieldValue),
476492
YieldFrom => w!(YieldFrom),
477493
SetupLoop { start, end } => w!(SetupLoop, label_map[start], label_map[end]),
478-
SetupExcept { handler } => w!(SetupExcept, handler),
494+
SetupExcept { handler } => w!(SetupExcept, label_map[handler]),
495+
SetupFinally { handler } => w!(SetupFinally, label_map[handler]),
496+
EndFinally => w!(EndFinally),
479497
SetupWith { end } => w!(SetupWith, end),
480498
CleanupWith { end } => w!(CleanupWith, end),
481499
PopBlock => w!(PopBlock),

compiler/src/compile.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -708,12 +708,20 @@ impl<O: OutputStream> Compiler<O> {
708708
&mut self,
709709
body: &[ast::Statement],
710710
handlers: &[ast::ExceptHandler],
711-
orelse: &Option<Vec<ast::Statement>>,
712-
finalbody: &Option<Vec<ast::Statement>>,
711+
orelse: &Option<ast::Suite>,
712+
finalbody: &Option<ast::Suite>,
713713
) -> Result<(), CompileError> {
714714
let mut handler_label = self.new_label();
715715
let finally_label = self.new_label();
716716
let else_label = self.new_label();
717+
718+
// Setup a finally block if we have a finally statement.
719+
if finalbody.is_some() {
720+
self.emit(Instruction::SetupFinally {
721+
handler: finally_label,
722+
});
723+
}
724+
717725
// try:
718726
self.emit(Instruction::SetupExcept {
719727
handler: handler_label,
@@ -798,8 +806,9 @@ impl<O: OutputStream> Compiler<O> {
798806
self.set_label(finally_label);
799807
if let Some(statements) = finalbody {
800808
self.compile_statements(statements)?;
809+
self.emit(Instruction::EndFinally);
801810
}
802-
// unimplemented!();
811+
803812
Ok(())
804813
}
805814

0 commit comments

Comments
 (0)