diff options
author | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2014-03-22 17:50:12 +0200 |
---|---|---|
committer | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2014-03-22 17:55:42 +0200 |
commit | 48caa09a9dd4b53656f58f622cf38341b6c099dc (patch) | |
tree | f1ee33c29869906cfb5a669d595c6850709198f3 /py/vm.c | |
parent | 61fd20f168e96efe1f85246401ee4871a14ad9bd (diff) | |
download | micropython-48caa09a9dd4b53656f58f622cf38341b6c099dc.tar.gz micropython-48caa09a9dd4b53656f58f622cf38341b6c099dc.zip |
objgenerator: Implement .throw() method to throw exceptions into generator.
Diffstat (limited to 'py/vm.c')
-rw-r--r-- | py/vm.c | 20 |
1 files changed, 14 insertions, 6 deletions
@@ -82,7 +82,7 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, mp_exc_stack exc_stack[4]; mp_exc_stack *exc_sp = &exc_stack[0] - 1; // execute the byte code - mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp); + mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp, MP_OBJ_NULL); switch (vm_return_kind) { case MP_VM_RETURN_NORMAL: @@ -107,8 +107,8 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, // MP_VM_RETURN_EXCEPTION, exception in fastn[0] mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out, - mp_exc_stack *exc_stack, - mp_exc_stack **exc_sp_in_out) { + mp_exc_stack *exc_stack, mp_exc_stack **exc_sp_in_out, + volatile mp_obj_t inject_exc) { // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think) const byte *ip = *ip_in_out; @@ -118,13 +118,21 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i mp_obj_t obj1, obj2; nlr_buf_t nlr; - volatile machine_uint_t currently_in_except_block = 0; // 0 or 1, to detect nested exceptions - mp_exc_stack *volatile exc_sp = *exc_sp_in_out; // stack grows up, exc_sp points to top of stack + volatile machine_uint_t currently_in_except_block = (int)*exc_sp_in_out & 1; // 0 or 1, to detect nested exceptions + mp_exc_stack *volatile exc_sp = (void*)((int)*exc_sp_in_out & ~1); // stack grows up, exc_sp points to top of stack const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop) // outer exception handling loop for (;;) { if (nlr_push(&nlr) == 0) { + // If we have exception to inject, now that we finish setting up + // execution context, raise it. This works as if RAISE_VARARGS + // bytecode was executed. + if (inject_exc != MP_OBJ_NULL) { + mp_obj_t t = inject_exc; + inject_exc = MP_OBJ_NULL; + nlr_jump(rt_make_raise_obj(t)); + } // loop to execute byte code for (;;) { dispatch_loop: @@ -599,7 +607,7 @@ unwind_return: nlr_pop(); *ip_in_out = ip; *sp_in_out = sp; - *exc_sp_in_out = exc_sp; + *exc_sp_in_out = (void*)((int)exc_sp | currently_in_except_block); return MP_VM_RETURN_YIELD; case MP_BC_IMPORT_NAME: |