From d109676ec0e8ebd648658583842ec3a91952adf3 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 29 Mar 2014 19:44:15 +0200 Subject: [PATCH 1/2] py: Reraising exception possible only in except block. --- py/vm.c | 3 +++ tests/basics/try-reraise.py | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/py/vm.c b/py/vm.c index f340f52190..d28416db3d 100644 --- a/py/vm.c +++ b/py/vm.c @@ -697,6 +697,9 @@ unwind_return: unum = *ip++; assert(unum <= 1); if (unum == 0) { + if (!currently_in_except_block) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise")); + } // This assumes that nlr.ret_val holds last raised // exception and is not overwritten since then. obj1 = nlr.ret_val; diff --git a/tests/basics/try-reraise.py b/tests/basics/try-reraise.py index bc817fc386..bf5e77c0b0 100644 --- a/tests/basics/try-reraise.py +++ b/tests/basics/try-reraise.py @@ -1,4 +1,4 @@ -# Re-reraising last exception with raise w/o args +# Reraising last exception with raise w/o args def f(): try: @@ -10,3 +10,10 @@ try: f() except ValueError as e: print(repr(e)) + + +# Can reraise only in except block +try: + raise +except RuntimeError: + print("RuntimeError") From a0ad77ba08e7bae8c71592565be9469aeff268ef Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 29 Mar 2014 23:16:27 +0200 Subject: [PATCH 2/2] vm: Establish macros PUSH_EXC_BLOCK & POP_EXC_BLOCK to deal with exc stack. E.g. to handle currently_in_except_block restoring properly. --- py/vm.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/py/vm.c b/py/vm.c index d28416db3d..84bd4172dc 100644 --- a/py/vm.c +++ b/py/vm.c @@ -45,7 +45,7 @@ typedef enum { #define TOP() (*sp) #define SET_TOP(val) *sp = (val) -#define SETUP_BLOCK() \ +#define PUSH_EXC_BLOCK() \ DECODE_ULABEL; /* except labels are always forward */ \ ++exc_sp; \ exc_sp->opcode = op; \ @@ -53,6 +53,10 @@ typedef enum { exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \ currently_in_except_block = 0; /* in a try block now */ +#define POP_EXC_BLOCK() \ + currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \ + exc_sp--; /* pop back to previous exception handler */ + mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, mp_obj_t *ret) { const byte *ip = code; @@ -386,7 +390,7 @@ dispatch_loop: SET_TOP(rt_load_attr(obj1, MP_QSTR___exit__)); rt_load_method(obj1, MP_QSTR___enter__, sp + 1); obj2 = rt_call_method_n_kw(0, 0, sp + 1); - SETUP_BLOCK(); + PUSH_EXC_BLOCK(); PUSH(obj2); break; @@ -478,7 +482,7 @@ unwind_jump: // matched against: POP_BLOCK or POP_EXCEPT (anything else?) case MP_BC_SETUP_EXCEPT: case MP_BC_SETUP_FINALLY: - SETUP_BLOCK(); + PUSH_EXC_BLOCK(); break; case MP_BC_END_FINALLY: @@ -527,8 +531,7 @@ unwind_jump: case MP_BC_POP_BLOCK: // we are exiting an exception handler, so pop the last one of the exception-stack assert(exc_sp >= exc_stack); - currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); // restore previous state - exc_sp--; // pop back to previous exception handler + POP_EXC_BLOCK(); break; // matched against: SETUP_EXCEPT @@ -539,8 +542,7 @@ unwind_jump: assert(currently_in_except_block); //sp = (mp_obj_t*)(*exc_sp--); //exc_sp--; // discard ip - currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); // restore previous state - exc_sp--; // pop back to previous exception handler + POP_EXC_BLOCK(); //sp -= 3; // pop 3 exception values break; @@ -830,8 +832,7 @@ yield: // at the moment we are just raising the very last exception (the one that caused the nested exception) // move up to previous exception handler - currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); // restore previous state - exc_sp--; // pop back to previous exception handler + POP_EXC_BLOCK(); } if (exc_sp >= exc_stack) {