Skip to content

Commit 9a3c5db

Browse files
committed
Fix raising an exception in an except block
1 parent b30f5fb commit 9a3c5db

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

notes.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ astyle --style=java --add-brackets < x.c > x.go
3333

3434
Roadmap
3535
=======
36-
* FIXME catching an exception is stopping the error return / traceback working
3736
* FIXME (int("a", base=16): gives int() got multiple values for argument 'base'
3837
* make pystone.py work
3938
* make enough of internals work so can run python tests

vm/eval.go

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ func (vm *Vm) SetException(exception py.Object) {
104104
vm.exit = exitException
105105
}
106106

107+
// Clears the current exception
108+
//
109+
// Doesn't adjust the exit code
110+
func (vm *Vm) ClearException() {
111+
// Clear the exception
112+
vm.exc.Type = nil
113+
vm.exc.Value = nil
114+
vm.exc.Traceback = nil
115+
}
116+
107117
// Check for an exception (panic)
108118
//
109119
// Should be called with the result of recover
@@ -629,16 +639,15 @@ func do_POP_EXCEPT(vm *Vm, arg int32) {
629639
func do_END_FINALLY(vm *Vm, arg int32) {
630640
defer vm.CheckException()
631641
v := vm.POP()
642+
fmt.Printf("END_FINALLY v=%v\n", v)
632643
if vInt, ok := v.(py.Int); ok {
633644
vm.exit = vmExit(vInt)
634-
if vm.exit == exitYield {
645+
switch vm.exit {
646+
case exitYield:
635647
panic("Unexpected exitYield in END_FINALLY")
636-
}
637-
if vm.exit == exitReturn || vm.exit == exitContinue {
638-
// Leave return value on the stack
639-
// retval = vm.POP()
640-
}
641-
if vm.exit == exitSilenced {
648+
case exitReturn, exitContinue:
649+
vm.result = vm.POP()
650+
case exitSilenced:
642651
// An exception was silenced by 'with', we must
643652
// manually unwind the EXCEPT_HANDLER block which was
644653
// created when the exception was caught, otherwise
@@ -662,7 +671,10 @@ func do_END_FINALLY(vm *Vm, arg int32) {
662671
vm.exit = exitReraise
663672
} else if v != py.None {
664673
vm.SetException(py.ExceptionNewf(py.SystemError, "'finally' pops bad exception %#v", v))
674+
} else {
675+
vm.ClearException()
665676
}
677+
666678
}
667679

668680
// Loads the __build_class__ helper function to the stack which
@@ -1367,9 +1379,19 @@ func (vm *Vm) UnwindExceptHandler(frame *py.Frame, block *py.TryBlock) {
13671379
} else {
13681380
frame.Stack = frame.Stack[:block.Level+3]
13691381
}
1370-
vm.exc.Type = vm.POP().(*py.Type)
1371-
vm.exc.Value = vm.POP()
1372-
vm.exc.Traceback = vm.POP().(*py.Traceback)
1382+
// If have just raised an exception, don't overwrite it
1383+
//
1384+
// FIXME if have two exceptions python shows both tracebacks
1385+
//
1386+
// FIXME this is a departure from python's way not sure it is
1387+
// correct
1388+
if vm.exc.Value != nil {
1389+
vm.DROPN(3)
1390+
} else {
1391+
vm.exc.Type = vm.POP().(*py.Type)
1392+
vm.exc.Value = vm.POP()
1393+
vm.exc.Traceback = vm.POP().(*py.Traceback)
1394+
}
13731395
}
13741396

13751397
// Run the virtual machine on a Frame object

0 commit comments

Comments
 (0)