Skip to content

Commit 3ec9b01

Browse files
committed
Add exception __context__
1 parent 2c2925a commit 3ec9b01

File tree

3 files changed

+33
-14
lines changed

3 files changed

+33
-14
lines changed

tests/snippets/try_exceptions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,8 @@ def __init__(self):
137137
raise
138138
except RuntimeError:
139139
pass
140+
141+
try:
142+
raise ZeroDivisionError
143+
except ZeroDivisionError as ex:
144+
assert ex.__context__ == None

vm/src/compile.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ impl Compiler {
572572
self.emit(Instruction::Jump { target: else_label });
573573

574574
// except handlers:
575+
let was_in_exc_handler = self.in_exc_handler;
575576
self.in_exc_handler = true;
576577
self.set_label(handler_label);
577578
// Exception is on top of stack now
@@ -609,6 +610,8 @@ impl Compiler {
609610

610611
// Handler code:
611612
self.compile_statements(&handler.body)?;
613+
// Drop exception from top of stack:
614+
self.emit(Instruction::Pop);
612615
self.emit(Instruction::Jump {
613616
target: finally_label,
614617
});
@@ -621,9 +624,6 @@ impl Compiler {
621624
target: handler_label,
622625
});
623626
self.set_label(handler_label);
624-
// Drop exception from top of stack:
625-
self.emit(Instruction::Pop);
626-
self.in_exc_handler = false;
627627
// If code flows here, we have an unhandled exception,
628628
// emit finally code and raise again!
629629
// Duplicate finally code here:
@@ -633,8 +633,8 @@ impl Compiler {
633633
self.compile_statements(statements)?;
634634
}
635635
self.emit(Instruction::Raise {
636-
argc: 1,
637-
in_exc: false,
636+
argc: 0,
637+
in_exc: true,
638638
});
639639

640640
// We successfully ran the try block:
@@ -649,7 +649,7 @@ impl Compiler {
649649
if let Some(statements) = finalbody {
650650
self.compile_statements(statements)?;
651651
}
652-
652+
self.in_exc_handler = was_in_exc_handler;
653653
// unimplemented!();
654654
Ok(())
655655
}

vm/src/frame.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -716,23 +716,37 @@ impl Frame {
716716
}
717717

718718
bytecode::Instruction::Raise { argc, in_exc } => {
719-
if argc.clone() == 0 && in_exc.clone() == false {
720-
return Err(vm.new_exception(
721-
vm.ctx.exceptions.runtime_error.clone(),
722-
"No active exception to reraise".to_string(),
723-
));
724-
}
725719
let cause = match argc {
726720
2 => self.get_exception(vm, true)?,
727721
_ => vm.get_none(),
728722
};
729723
let exception = match argc {
730-
0 | 1 | 2 => self.get_exception(vm, false)?,
724+
0 => match in_exc {
725+
true => self.get_exception(vm, false)?,
726+
false => {
727+
return Err(vm.new_exception(
728+
vm.ctx.exceptions.runtime_error.clone(),
729+
"No active exception to reraise".to_string(),
730+
));
731+
}
732+
},
733+
1 | 2 => self.get_exception(vm, false)?,
731734
3 => panic!("Not implemented!"),
732735
_ => panic!("Invalid parameter for RAISE_VARARGS, must be between 0 to 3"),
733736
};
734-
info!("Exception raised: {:?} with cause: {:?}", exception, cause);
737+
let context = match argc {
738+
0 => vm.get_none(), // We have already got the exception,
739+
_ => match in_exc {
740+
true => self.get_exception(vm, false)?,
741+
false => vm.get_none(),
742+
},
743+
};
744+
info!(
745+
"Exception raised: {:?} with cause: {:?} and context: {:?}",
746+
exception, cause, context
747+
);
735748
vm.set_attr(&exception, vm.new_str("__cause__".to_string()), cause)?;
749+
vm.set_attr(&exception, vm.new_str("__context__".to_string()), context)?;
736750
Err(exception)
737751
}
738752

0 commit comments

Comments
 (0)