mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-22 12:35:22 +00:00
Implement execution of finally block. Fixes #1306.
This commit is contained in:
parent
e8db01a09a
commit
e37f117035
1 changed files with 20 additions and 11 deletions
|
@ -712,13 +712,13 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
finalbody: &Option<ast::Suite>,
|
finalbody: &Option<ast::Suite>,
|
||||||
) -> Result<(), CompileError> {
|
) -> Result<(), CompileError> {
|
||||||
let mut handler_label = self.new_label();
|
let mut handler_label = self.new_label();
|
||||||
let finally_label = self.new_label();
|
let finally_handler_label = self.new_label();
|
||||||
let else_label = self.new_label();
|
let else_label = self.new_label();
|
||||||
|
|
||||||
// Setup a finally block if we have a finally statement.
|
// Setup a finally block if we have a finally statement.
|
||||||
if finalbody.is_some() {
|
if finalbody.is_some() {
|
||||||
self.emit(Instruction::SetupFinally {
|
self.emit(Instruction::SetupFinally {
|
||||||
handler: finally_label,
|
handler: finally_handler_label,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,26 +773,28 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
// Handler code:
|
// Handler code:
|
||||||
self.compile_statements(&handler.body)?;
|
self.compile_statements(&handler.body)?;
|
||||||
self.emit(Instruction::PopException);
|
self.emit(Instruction::PopException);
|
||||||
|
|
||||||
|
if finalbody.is_some() {
|
||||||
|
self.emit(Instruction::PopBlock); // pop finally block
|
||||||
|
// We enter the finally block, without exception.
|
||||||
|
self.emit(Instruction::EnterFinally);
|
||||||
|
}
|
||||||
|
|
||||||
self.emit(Instruction::Jump {
|
self.emit(Instruction::Jump {
|
||||||
target: finally_label,
|
target: finally_handler_label,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Emit a new label for the next handler
|
// Emit a new label for the next handler
|
||||||
self.set_label(handler_label);
|
self.set_label(handler_label);
|
||||||
handler_label = self.new_label();
|
handler_label = self.new_label();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit(Instruction::Jump {
|
self.emit(Instruction::Jump {
|
||||||
target: handler_label,
|
target: handler_label,
|
||||||
});
|
});
|
||||||
self.set_label(handler_label);
|
self.set_label(handler_label);
|
||||||
// If code flows here, we have an unhandled exception,
|
// If code flows here, we have an unhandled exception,
|
||||||
// emit finally code and raise again!
|
// raise the exception again!
|
||||||
// Duplicate finally code here:
|
|
||||||
// TODO: this bytecode is now duplicate, could this be
|
|
||||||
// improved?
|
|
||||||
if let Some(statements) = finalbody {
|
|
||||||
self.compile_statements(statements)?;
|
|
||||||
}
|
|
||||||
self.emit(Instruction::Raise { argc: 0 });
|
self.emit(Instruction::Raise { argc: 0 });
|
||||||
|
|
||||||
// We successfully ran the try block:
|
// We successfully ran the try block:
|
||||||
|
@ -802,8 +804,15 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
self.compile_statements(statements)?;
|
self.compile_statements(statements)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if finalbody.is_some() {
|
||||||
|
self.emit(Instruction::PopBlock); // pop finally block
|
||||||
|
|
||||||
|
// We enter the finally block, without return / exception.
|
||||||
|
self.emit(Instruction::EnterFinally);
|
||||||
|
}
|
||||||
|
|
||||||
// finally:
|
// finally:
|
||||||
self.set_label(finally_label);
|
self.set_label(finally_handler_label);
|
||||||
if let Some(statements) = finalbody {
|
if let Some(statements) = finalbody {
|
||||||
self.compile_statements(statements)?;
|
self.compile_statements(statements)?;
|
||||||
self.emit(Instruction::EndFinally);
|
self.emit(Instruction::EndFinally);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue