diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/builtin.h | 1 | ||||
-rw-r--r-- | py/builtintables.c | 3 | ||||
-rw-r--r-- | py/mkenv.mk | 2 | ||||
-rw-r--r-- | py/modcmath.c | 131 | ||||
-rw-r--r-- | py/modmath.c | 9 | ||||
-rw-r--r-- | py/mpconfig.h | 12 | ||||
-rw-r--r-- | py/nlr.h | 20 | ||||
-rw-r--r-- | py/nlrsetjmp.c | 16 | ||||
-rw-r--r-- | py/py.mk | 2 | ||||
-rw-r--r-- | py/qstrdefs.h | 9 | ||||
-rw-r--r-- | py/runtime.c | 5 | ||||
-rw-r--r-- | py/vm.c | 66 |
12 files changed, 242 insertions, 34 deletions
diff --git a/py/builtin.h b/py/builtin.h index 36b9f38814..9b2b9c9424 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -48,6 +48,7 @@ extern const mp_obj_module_t mp_module_array; extern const mp_obj_module_t mp_module_collections; extern const mp_obj_module_t mp_module_io; extern const mp_obj_module_t mp_module_math; +extern const mp_obj_module_t mp_module_cmath; extern const mp_obj_module_t mp_module_micropython; extern const mp_obj_module_t mp_module_struct; extern const mp_obj_module_t mp_module_sys; diff --git a/py/builtintables.c b/py/builtintables.c index 6bdae24002..c4c96ed35a 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -139,6 +139,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = { #if MICROPY_ENABLE_FLOAT { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&mp_module_math }, +#if MICROPY_ENABLE_MOD_CMATH + { MP_OBJ_NEW_QSTR(MP_QSTR_cmath), (mp_obj_t)&mp_module_cmath }, +#endif #endif #if MICROPY_ENABLE_MOD_SYS { MP_OBJ_NEW_QSTR(MP_QSTR_sys), (mp_obj_t)&mp_module_sys }, diff --git a/py/mkenv.mk b/py/mkenv.mk index 8ae54f06bb..4bc71edd78 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -54,4 +54,6 @@ STRIP = $(CROSS_COMPILE)strip all: .PHONY: all +.DELETE_ON_ERROR: + MKENV_INCLUDED = 1 diff --git a/py/modcmath.c b/py/modcmath.c new file mode 100644 index 0000000000..3f561e7f30 --- /dev/null +++ b/py/modcmath.c @@ -0,0 +1,131 @@ +#include <math.h> + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "builtin.h" + +#if MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_CMATH + +// These are defined in modmath.c +extern const mp_obj_float_t mp_math_e_obj; +extern const mp_obj_float_t mp_math_pi_obj; + +mp_obj_t mp_cmath_phase(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + return mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase); + +mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + mp_obj_t tuple[2] = { + mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)), + mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)), + }; + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar); + +mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) { + mp_float_t r = mp_obj_get_float(r_obj); + mp_float_t phi = mp_obj_get_float(phi_obj); + return mp_obj_new_complex(r * MICROPY_FLOAT_C_FUN(cos)(phi), r * MICROPY_FLOAT_C_FUN(sin)(phi)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect); + +mp_obj_t mp_cmath_exp(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real); + return mp_obj_new_complex(exp_real * MICROPY_FLOAT_C_FUN(cos)(imag), exp_real * MICROPY_FLOAT_C_FUN(sin)(imag)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp); + +// TODO can take second argument, being the base +mp_obj_t mp_cmath_log(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log); + +mp_obj_t mp_cmath_log10(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log10)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10); + +mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real*real + imag*imag, 0.25); + mp_float_t theta = 0.5 * MICROPY_FLOAT_C_FUN(atan2)(imag, real); + return mp_obj_new_complex(sqrt_abs * cos(theta), sqrt_abs * sin(theta)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt); + +mp_obj_t mp_cmath_cos(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), -MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos); + +mp_obj_t mp_cmath_sin(mp_obj_t z_obj) { + mp_float_t real, imag; + mp_obj_get_complex(z_obj, &real, &imag); + return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sin_obj, mp_cmath_sin); + +STATIC const mp_map_elem_t mp_module_cmath_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_cmath) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_e), (mp_obj_t)&mp_math_e_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pi), (mp_obj_t)&mp_math_pi_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_phase), (mp_obj_t)&mp_cmath_phase_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_polar), (mp_obj_t)&mp_cmath_polar_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_rect), (mp_obj_t)&mp_cmath_rect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_exp), (mp_obj_t)&mp_cmath_exp_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_log), (mp_obj_t)&mp_cmath_log_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_log10), (mp_obj_t)&mp_cmath_log10_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&mp_cmath_sqrt_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_acos), (mp_obj_t)&mp_cmath_acos_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_asin), (mp_obj_t)&mp_cmath_asin_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_atan), (mp_obj_t)&mp_cmath_atan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_cos), (mp_obj_t)&mp_cmath_cos_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sin), (mp_obj_t)&mp_cmath_sin_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&mp_cmath_tan_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_acosh), (mp_obj_t)&mp_cmath_acosh_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_asinh), (mp_obj_t)&mp_cmath_asinh_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_atanh), (mp_obj_t)&mp_cmath_atanh_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_cosh), (mp_obj_t)&mp_cmath_cosh_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&mp_cmath_sinh_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&mp_cmath_tanh_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_cmath_isfinite_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_cmath_isinf_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_cmath_isnan_obj }, +}; + +STATIC const mp_obj_dict_t mp_module_cmath_globals = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(mp_module_cmath_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(mp_module_cmath_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)mp_module_cmath_globals_table, + }, +}; + +const mp_obj_module_t mp_module_cmath = { + .base = { &mp_type_module }, + .name = MP_QSTR_cmath, + .globals = (mp_obj_dict_t*)&mp_module_cmath_globals, +}; + +#endif // MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_CMATH diff --git a/py/modmath.c b/py/modmath.c index c26ba16189..09bb4ce3aa 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -6,7 +6,7 @@ #include "obj.h" #include "builtin.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_MATH //TODO: Change macros to check for overflow and raise OverflowError or RangeError #define MATH_FUN_1(py_name, c_name) \ @@ -25,8 +25,9 @@ mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int((machine_int_t)MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); -STATIC const mp_obj_float_t mp_math_e_obj = {{&mp_type_float}, M_E}; -STATIC const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI}; +// These are also used by cmath.c +const mp_obj_float_t mp_math_e_obj = {{&mp_type_float}, M_E}; +const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI}; MATH_FUN_1(sqrt, sqrt) MATH_FUN_2(pow, pow) @@ -156,4 +157,4 @@ const mp_obj_module_t mp_module_math = { .globals = (mp_obj_dict_t*)&mp_module_math_globals, }; -#endif // MICROPY_ENABLE_FLOAT +#endif // MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_MATH diff --git a/py/mpconfig.h b/py/mpconfig.h index 7fd7067953..43c931cd66 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -110,6 +110,16 @@ typedef double mp_float_t; #define MICROPY_ENABLE_FLOAT (0) #endif +// Whether to provide "math" module +#ifndef MICROPY_ENABLE_MOD_MATH +#define MICROPY_ENABLE_MOD_MATH (1) +#endif + +// Whether to provide "cmath" module +#ifndef MICROPY_ENABLE_MOD_CMATH +#define MICROPY_ENABLE_MOD_CMATH (0) +#endif + // Whether to provide "io" module #ifndef MICROPY_ENABLE_MOD_IO #define MICROPY_ENABLE_MOD_IO (1) @@ -137,7 +147,7 @@ typedef double mp_float_t; // Whether to support the property object #ifndef MICROPY_ENABLE_PROPERTY -#define MICROPY_ENABLE_PROPERTY (0) +#define MICROPY_ENABLE_PROPERTY (1) #endif // Enable features which improve CPython compatibility @@ -2,12 +2,14 @@ // exception handling, basically a stack of setjmp/longjmp buffers #include <limits.h> +#include <setjmp.h> typedef struct _nlr_buf_t nlr_buf_t; struct _nlr_buf_t { // the entries here must all be machine word size nlr_buf_t *prev; void *ret_val; +#if !MICROPY_NLR_SETJMP #if defined(__i386__) void *regs[6]; #elif defined(__x86_64__) @@ -19,13 +21,29 @@ struct _nlr_buf_t { #elif defined(__thumb2__) void *regs[10]; #else -#error Unknown arch in nlr.h + #define MICROPY_NLR_SETJMP (1) + #warning "No native NLR support for this arch, using setjmp implementation" +#endif +#endif + +#if MICROPY_NLR_SETJMP + jmp_buf jmpbuf; #endif }; +#if MICROPY_NLR_SETJMP +extern nlr_buf_t *nlr_setjmp_top; +void nlr_setjmp_jump(void *val) __attribute__((noreturn)); +// nlr_push() must be defined as a macro, because "The stack context will be +// invalidated if the function which called setjmp() returns." +#define nlr_push(buf) ((buf)->prev = nlr_setjmp_top, nlr_setjmp_top = (buf), setjmp((buf)->jmpbuf)) +#define nlr_pop() { nlr_setjmp_top = nlr_setjmp_top->prev; } +#define nlr_jump(val) nlr_setjmp_jump(val) +#else unsigned int nlr_push(nlr_buf_t *); void nlr_pop(void); void nlr_jump(void *val) __attribute__((noreturn)); +#endif // This must be implemented by a port. It's called by nlr_jump // if no nlr buf has been pushed. It must not return, but rather diff --git a/py/nlrsetjmp.c b/py/nlrsetjmp.c new file mode 100644 index 0000000000..a97c8634b2 --- /dev/null +++ b/py/nlrsetjmp.c @@ -0,0 +1,16 @@ +#include <setjmp.h> +#include <stdio.h> +#include "nlr.h" + +#if MICROPY_NLR_SETJMP + +nlr_buf_t *nlr_setjmp_top; + +void nlr_setjmp_jump(void *val) { + nlr_buf_t *buf = nlr_setjmp_top; + nlr_setjmp_top = buf->prev; + buf->ret_val = val; + longjmp(buf->jmpbuf, 1); +} + +#endif @@ -15,6 +15,7 @@ PY_O_BASENAME = \ nlrx86.o \ nlrx64.o \ nlrthumb.o \ + nlrsetjmp.o \ malloc.o \ gc.o \ qstr.o \ @@ -87,6 +88,7 @@ PY_O_BASENAME = \ modcollections.o \ modio.o \ modmath.o \ + modcmath.o \ modmicropython.o \ modstruct.o \ modsys.o \ diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 20c4db75f0..a4df86fda7 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -217,6 +217,7 @@ Q(iterator) Q(module) Q(slice) +#if MICROPY_ENABLE_MOD_MATH || MICROPY_ENABLE_MOD_CMATH Q(math) Q(e) Q(pi) @@ -258,6 +259,14 @@ Q(erf) Q(erfc) Q(gamma) Q(lgamma) +#endif + +#if MICROPY_ENABLE_MOD_CMATH +Q(cmath) +Q(phase) +Q(polar) +Q(rect) +#endif Q(mem_total) Q(mem_current) diff --git a/py/runtime.c b/py/runtime.c index a507f97f36..98b2d076ec 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -365,7 +365,8 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break; case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); break; - default: assert(0); + default: + goto unsupported_op; } // TODO: We just should make mp_obj_new_int() inline and use that if (MP_OBJ_FITS_SMALL_INT(lhs_val)) { @@ -437,9 +438,7 @@ generic_binary_op: // TODO implement dispatch for reverse binary ops // TODO specify in error message what the operator is -#if MICROPY_ENABLE_FLOAT unsupported_op: -#endif nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand types for binary operator: '%s', '%s'", mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs))); @@ -165,8 +165,6 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i mp_obj_t *fastn, mp_obj_t **sp_in_out, mp_exc_stack_t *exc_stack, mp_exc_stack_t **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) - #if MICROPY_USE_COMPUTED_GOTOS #include "vmentrytable.h" #define DISPATCH() do { \ @@ -182,32 +180,43 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i #define ENTRY_DEFAULT default #endif - int op = 0; - const byte *ip = *ip_in_out; - mp_obj_t *sp = *sp_in_out; - machine_uint_t unum; - qstr qst; - mp_obj_t obj1, obj2; - nlr_buf_t nlr; + // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser + // sees that it's possible for us to jump from the dispatch loop to the exception + // handler. Without this, the code may have a different stack layout in the dispatch + // loop and the exception handler, leading to very obscure bugs. + #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0) + // variables that are visible to the exception handler (declared volatile) volatile bool currently_in_except_block = MP_TAGPTR_TAG(*exc_sp_in_out); // 0 or 1, to detect nested exceptions mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(*exc_sp_in_out); // 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) + const byte *volatile save_ip = *ip_in_out; // 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) + mp_obj_t *volatile save_sp = *sp_in_out; // this is so we can access sp in the exception handler when needed // outer exception handling loop for (;;) { + nlr_buf_t nlr; outer_dispatch_loop: if (nlr_push(&nlr) == 0) { + // local variables that are not visible to the exception handler + byte op = 0; + const byte *ip = *ip_in_out; + mp_obj_t *sp = *sp_in_out; + machine_uint_t unum; + qstr qst; + mp_obj_t obj1, obj2; + // 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. // Injecting exc into yield from generator is a special case, // handled by MP_BC_YIELD_FROM itself if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) { - mp_obj_t t = inject_exc; + obj1 = inject_exc; inject_exc = MP_OBJ_NULL; - nlr_raise(mp_make_raise_obj(t)); + obj1 = mp_make_raise_obj(obj1); + RAISE(obj1); } + // loop to execute byte code for (;;) { dispatch_loop: @@ -297,7 +306,8 @@ dispatch_loop: load_check: if (obj1 == MP_OBJ_NULL) { local_name_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment")); + obj1 = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment"); + RAISE(obj1); } PUSH(obj1); DISPATCH(); @@ -580,7 +590,7 @@ unwind_jump: // if TOS is an integer, does something else // else error if (mp_obj_is_exception_type(TOP())) { - nlr_raise(sp[-1]); + RAISE(sp[-1]); } if (TOP() == mp_const_none) { sp--; @@ -606,6 +616,7 @@ unwind_jump: ENTRY(MP_BC_FOR_ITER): DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward + save_sp = sp; obj1 = mp_iternext_allow_raise(TOP()); if (obj1 == MP_OBJ_NULL) { --sp; // pop the exhausted iterator @@ -829,12 +840,14 @@ unwind_return: } } if (obj1 == MP_OBJ_NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise")); + obj1 = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise"); + RAISE(obj1); } } else { obj1 = POP(); } - nlr_raise(mp_make_raise_obj(obj1)); + obj1 = mp_make_raise_obj(obj1); + RAISE(obj1); ENTRY(MP_BC_YIELD_VALUE): yield: @@ -847,7 +860,7 @@ yield: ENTRY(MP_BC_YIELD_FROM): { //#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type) #define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type) -#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_raise(t); } +#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); } mp_vm_return_kind_t ret_kind; obj1 = POP(); mp_obj_t t_exc = MP_OBJ_NULL; @@ -890,7 +903,7 @@ yield: GENERATOR_EXIT_IF_NEEDED(t_exc); DISPATCH(); } else { - nlr_raise(obj2); + RAISE(obj2); } } } @@ -912,25 +925,27 @@ yield: DISPATCH(); ENTRY_DEFAULT: - printf("code %p, byte code 0x%02x not implemented\n", ip, op); obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented"); nlr_pop(); fastn[0] = obj1; return MP_VM_RETURN_EXCEPTION; + #if !MICROPY_USE_COMPUTED_GOTOS } // switch #endif - } + } // for loop } else { +exception_handler: // exception occurred // check if it's a StopIteration within a for block if (*save_ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) { - ip = save_ip + 1; + const byte *ip = save_ip + 1; + machine_uint_t unum; DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward - --sp; // pop the exhausted iterator - ip += unum; // jump to after for-block + *ip_in_out = ip + unum; // jump to after for-block + *sp_in_out = save_sp - 1; // pop the exhausted iterator goto outer_dispatch_loop; // continue with dispatch loop } @@ -969,14 +984,15 @@ yield: currently_in_except_block = 1; // catch exception and pass to byte code - sp = MP_TAGPTR_PTR(exc_sp->val_sp); - ip = exc_sp->handler; + *ip_in_out = exc_sp->handler; + mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp); // save this exception in the stack so it can be used in a reraise, if needed exc_sp->prev_exc = nlr.ret_val; // push(traceback, exc-val, exc-type) PUSH(mp_const_none); PUSH(nlr.ret_val); PUSH(mp_obj_get_type(nlr.ret_val)); + *sp_in_out = sp; } else { // propagate exception to higher level |