diff options
-rw-r--r-- | py/builtin.h | 1 | ||||
-rw-r--r-- | py/builtintables.c | 3 | ||||
-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/py.mk | 1 | ||||
-rw-r--r-- | py/qstrdefs.h | 9 | ||||
-rw-r--r-- | py/runtime.c | 5 | ||||
-rw-r--r-- | py/vm.c | 66 | ||||
-rw-r--r-- | stmhal/Makefile | 1 | ||||
-rw-r--r-- | stmhal/main.c | 36 | ||||
-rw-r--r-- | stmhal/malloc0.c | 37 | ||||
-rw-r--r-- | stmhal/std.h | 2 | ||||
-rw-r--r-- | stmhal/stm32f4xx_it.c | 34 | ||||
-rw-r--r-- | stmhal/usbd_desc_cdc_msc.c | 18 | ||||
-rw-r--r-- | tests/README | 4 | ||||
-rw-r--r-- | tests/basics/int-divzero.py | 5 | ||||
-rw-r--r-- | tests/basics/list1.py | 5 | ||||
-rw-r--r-- | tests/basics/modulo.py | 17 | ||||
-rw-r--r-- | tests/basics/string-format-modulo.py | 14 | ||||
-rw-r--r-- | tests/basics/string-format.py | 87 | ||||
-rw-r--r-- | tests/basics/true-value.py | 6 | ||||
-rw-r--r-- | tests/basics/types1.py | 6 | ||||
-rw-r--r-- | tests/basics/types2.py | 4 | ||||
-rw-r--r-- | tests/float/float1.py (renamed from tests/basics/float1.py) | 0 | ||||
-rw-r--r-- | tests/float/int-divzero.py | 4 | ||||
-rw-r--r-- | tests/float/list-index.py | 8 | ||||
-rw-r--r-- | tests/float/math-fun-bool.py (renamed from tests/basics/math-fun-bool.py) | 0 | ||||
-rw-r--r-- | tests/float/math-fun.py (renamed from tests/basics/math-fun.py) | 0 | ||||
-rw-r--r-- | tests/float/modulo.py | 14 | ||||
-rw-r--r-- | tests/float/string-format-modulo.py | 16 | ||||
-rw-r--r-- | tests/float/string-format.py | 123 | ||||
-rw-r--r-- | tests/float/true-value.py | 7 | ||||
-rw-r--r-- | tests/float/types.py | 17 | ||||
-rw-r--r-- | tests/import/import-pkg1.py (renamed from tests/basics/import-pkg1.py) | 0 | ||||
-rw-r--r-- | tests/import/import-pkg2.py (renamed from tests/basics/import-pkg2.py) | 0 | ||||
-rw-r--r-- | tests/import/import-pkg3.py (renamed from tests/basics/import-pkg3.py) | 0 | ||||
-rw-r--r-- | tests/import/import-pkg4.py (renamed from tests/basics/import-pkg4.py) | 0 | ||||
-rw-r--r-- | tests/import/import-pkg5.py (renamed from tests/basics/import-pkg5.py) | 0 | ||||
-rw-r--r-- | tests/import/import1a.py (renamed from tests/basics/import1a.py) | 0 | ||||
-rw-r--r-- | tests/import/import1b.py (renamed from tests/basics/import1b.py) | 0 | ||||
-rw-r--r-- | tests/import/import2a.py (renamed from tests/basics/import2a.py) | 0 | ||||
-rw-r--r-- | tests/import/import3a.py (renamed from tests/basics/import3a.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg/__init__.py (renamed from tests/basics/pkg/__init__.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg/mod.py (renamed from tests/basics/pkg/mod.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg2/__init__.py (renamed from tests/basics/pkg2/__init__.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg2/mod1.py (renamed from tests/basics/pkg2/mod1.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg2/mod2.py (renamed from tests/basics/pkg2/mod2.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg3/__init__.py (renamed from tests/basics/pkg3/__init__.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg3/mod1.py (renamed from tests/basics/pkg3/mod1.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg3/mod2.py (renamed from tests/basics/pkg3/mod2.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg3/subpkg1/__init__.py (renamed from tests/basics/pkg3/subpkg1/__init__.py) | 0 | ||||
-rw-r--r-- | tests/import/pkg3/subpkg1/mod1.py (renamed from tests/basics/pkg3/subpkg1/mod1.py) | 0 | ||||
-rw-r--r-- | tests/import/try-module.py (renamed from tests/basics/try-module.py) | 0 | ||||
-rwxr-xr-x | tests/run-tests | 11 | ||||
-rw-r--r-- | unix/mpconfigport.h | 2 |
56 files changed, 456 insertions, 259 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/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 @@ -82,6 +82,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 diff --git a/stmhal/Makefile b/stmhal/Makefile index 56c00e905a..ac0367024a 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -71,7 +71,6 @@ SRC_C = \ printf.c \ math.c \ mathsincos.c \ - malloc0.c \ gccollect.c \ pybstdio.c \ readline.c \ diff --git a/stmhal/main.c b/stmhal/main.c index c5633fb68b..2d7e76172f 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -1,9 +1,7 @@ #include <stdio.h> #include <string.h> -#include <stm32f4xx_hal.h> -#include <stm32f4xx_hal_gpio.h> -#include "std.h" +#include "stm32f4xx_hal.h" #include "misc.h" #include "systick.h" @@ -14,11 +12,10 @@ #include "lexer.h" #include "parse.h" #include "obj.h" -#include "parsehelper.h" -#include "compile.h" #include "runtime.h" #include "gc.h" #include "gccollect.h" +#include "pybstdio.h" #include "readline.h" #include "pyexec.h" #include "usart.h" @@ -64,12 +61,25 @@ void flash_error(int n) { } void __fatal_error(const char *msg) { -#if MICROPY_HW_HAS_LCD + for (volatile uint delay = 0; delay < 10000000; delay++) { + } + led_state(1, 1); + led_state(2, 1); + led_state(3, 1); + led_state(4, 1); + stdout_tx_strn("\nFATAL ERROR:\n", 14); + stdout_tx_strn(msg, strlen(msg)); +#if 0 && MICROPY_HW_HAS_LCD lcd_print_strn("\nFATAL ERROR:\n", 14); lcd_print_strn(msg, strlen(msg)); #endif - for (;;) { - flash_error(1); + for (uint i = 0;;) { + led_toggle(((i++) & 3) + 1); + for (volatile uint delay = 0; delay < 10000000; delay++) { + } + if (i >= 8) { + __WFI(); + } } } @@ -109,16 +119,6 @@ STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) { MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode); -void fatality(void) { - led_state(PYB_LED_R1, 1); - led_state(PYB_LED_G1, 1); - led_state(PYB_LED_R2, 1); - led_state(PYB_LED_G2, 1); - for (;;) { - flash_error(1); - } -} - static const char fresh_boot_py[] = "# boot.py -- run on boot-up\n" "# can run arbitrary Python, but best to keep it minimal\n" diff --git a/stmhal/malloc0.c b/stmhal/malloc0.c deleted file mode 100644 index 510fa0d740..0000000000 --- a/stmhal/malloc0.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include "misc.h" -#include "mpconfig.h" -#include "gc.h" - -#if 0 -static uint32_t mem = 0; - -void *malloc(size_t n) { - if (mem == 0) { - extern uint32_t _heap_start; - mem = (uint32_t)&_heap_start; // need to use big ram block so we can execute code from it (is it true that we can't execute from CCM?) - } - void *ptr = (void*)mem; - mem = (mem + n + 3) & (~3); - if (mem > 0x20000000 + 0x18000) { - void __fatal_error(const char*); - __fatal_error("out of memory"); - } - return ptr; -} - -void free(void *ptr) { -} - -void *realloc(void *ptr, size_t n) { - return malloc(n); -} - -#endif - -void __assert_func(void) { - printf("\nASSERT FAIL!"); - for (;;) { - } -} diff --git a/stmhal/std.h b/stmhal/std.h index 843ddd8270..6982b715d0 100644 --- a/stmhal/std.h +++ b/stmhal/std.h @@ -1,7 +1,5 @@ typedef unsigned int size_t; -void __assert_func(void); - void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c index 06428a4c4f..df69f52b8e 100644 --- a/stmhal/stm32f4xx_it.c +++ b/stmhal/stm32f4xx_it.c @@ -64,7 +64,7 @@ /* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
-extern void fatality();
+extern void __fatal_error(const char*);
extern PCD_HandleTypeDef hpcd;
/* Private function prototypes -----------------------------------------------*/
@@ -88,12 +88,10 @@ void NMI_Handler(void) * @param None
* @retval None
*/
-void HardFault_Handler(void)
-{
+void HardFault_Handler(void) {
/* Go to infinite loop when Hard Fault exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("HardFault");
}
}
@@ -102,12 +100,10 @@ void HardFault_Handler(void) * @param None
* @retval None
*/
-void MemManage_Handler(void)
-{
+void MemManage_Handler(void) {
/* Go to infinite loop when Memory Manage exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("MemManage");
}
}
@@ -116,12 +112,10 @@ void MemManage_Handler(void) * @param None
* @retval None
*/
-void BusFault_Handler(void)
-{
+void BusFault_Handler(void) {
/* Go to infinite loop when Bus Fault exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("BusFault");
}
}
@@ -130,12 +124,10 @@ void BusFault_Handler(void) * @param None
* @retval None
*/
-void UsageFault_Handler(void)
-{
+void UsageFault_Handler(void) {
/* Go to infinite loop when Usage Fault exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("UsageFault");
}
}
diff --git a/stmhal/usbd_desc_cdc_msc.c b/stmhal/usbd_desc_cdc_msc.c index 137e0bed99..1af99d0b90 100644 --- a/stmhal/usbd_desc_cdc_msc.c +++ b/stmhal/usbd_desc_cdc_msc.c @@ -32,6 +32,23 @@ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
+
+// So we don't clash with existing ST boards, we use the unofficial FOSS VID.
+// This needs a proper solution.
+#define USBD_VID 0xf055
+#define USBD_PID 0x9800
+#define USBD_LANGID_STRING 0x409
+#define USBD_MANUFACTURER_STRING "Micro Python"
+#define USBD_PRODUCT_HS_STRING "Pyboard Virtual Comm Port in HS Mode"
+#define USBD_SERIALNUMBER_HS_STRING "000000000010"
+#define USBD_PRODUCT_FS_STRING "Pyboard Virtual Comm Port in FS Mode"
+#define USBD_SERIALNUMBER_FS_STRING "000000000011"
+#define USBD_CONFIGURATION_HS_STRING "VCP Config"
+#define USBD_INTERFACE_HS_STRING "VCP Interface"
+#define USBD_CONFIGURATION_FS_STRING "VCP Config"
+#define USBD_INTERFACE_FS_STRING "VCP Interface"
+
+/*
#define USBD_VID 0x0483
#define USBD_PID 0x5740
#define USBD_LANGID_STRING 0x409
@@ -44,6 +61,7 @@ #define USBD_INTERFACE_HS_STRING "VCP Interface"
#define USBD_CONFIGURATION_FS_STRING "VCP Config"
#define USBD_INTERFACE_FS_STRING "VCP Interface"
+*/
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
diff --git a/tests/README b/tests/README index ef00705712..0cb526c3b4 100644 --- a/tests/README +++ b/tests/README @@ -2,3 +2,7 @@ This directory contains tests for various functionality areas of MicroPython. To run all stable tests, run "run-tests" script in this directory. Note that bytecode tests are not yet stable and should be run separately in "bytecode" subdirectory. + +When creating new tests, anything that relies on float support should go in the +float/ subdirectory. Anything that relies on import x, where x is not a built-in +module, should go in the import/ subdirectory. diff --git a/tests/basics/int-divzero.py b/tests/basics/int-divzero.py index d1fc579321..28ec2a6995 100644 --- a/tests/basics/int-divzero.py +++ b/tests/basics/int-divzero.py @@ -1,9 +1,4 @@ try: - 1 / 0 -except ZeroDivisionError: - print("ZeroDivisionError") - -try: 1 // 0 except ZeroDivisionError: print("ZeroDivisionError") diff --git a/tests/basics/list1.py b/tests/basics/list1.py index a0c8afc4f8..c8317baa3d 100644 --- a/tests/basics/list1.py +++ b/tests/basics/list1.py @@ -22,8 +22,3 @@ print(x) print(x[1:]) print(x[:-1]) print(x[2:3]) - -try: - print(x[1.0]) -except TypeError: - print("TypeError") diff --git a/tests/basics/modulo.py b/tests/basics/modulo.py index 4d83db6ec8..c95305d13d 100644 --- a/tests/basics/modulo.py +++ b/tests/basics/modulo.py @@ -1,5 +1,6 @@ # check modulo matches python definition -# This test compiler version + +# this tests compiler constant folding print(123 % 7) print(-123 % 7) print(123 % -7) @@ -20,17 +21,3 @@ print(a % b) print(a % -b) print(-a % b) print(-a % -b) - -if False: - print(1.23456 % 0.7) - print(-1.23456 % 0.7) - print(1.23456 % -0.7) - print(-1.23456 % -0.7) - - a = 1.23456 - b = 0.7 - print(a % b) - print(a % -b) - print(-a % b) - print(-a % -b) - diff --git a/tests/basics/string-format-modulo.py b/tests/basics/string-format-modulo.py index 8e58be18c8..0e2c1d1096 100644 --- a/tests/basics/string-format-modulo.py +++ b/tests/basics/string-format-modulo.py @@ -23,11 +23,9 @@ except TypeError: print("%s" % True) print("%s" % 1) -print("%s" % 1.0) print("%r" % True) print("%r" % 1) -print("%r" % 1.0) print("%c" % 48) print("%c" % 'a') @@ -37,28 +35,16 @@ print("%d" % 10) print("%+d" % 10) print("% d" % 10) print("%d" % -10) -print("%d" % 1.0) print("%d" % True) print("%i" % -10) -print("%i" % 1.0) print("%i" % True) print("%u" % -10) -print("%u" % 1.0) print("%u" % True) print("%x" % 18) -print("%x" % 18.0) print("%o" % 18) -print("%o" % 18.0) print("%X" % 18) -print("%X" % 18.0) print("%#x" % 18) print("%#X" % 18) print("%#6o" % 18) print("%#6x" % 18) print("%#06x" % 18) -print("%e" % 1.23456) -print("%E" % 1.23456) -print("%f" % 1.23456) -print("%F" % 1.23456) -print("%g" % 1.23456) -print("%G" % 1.23456) diff --git a/tests/basics/string-format.py b/tests/basics/string-format.py index 2d6d0cc721..84ea054758 100644 --- a/tests/basics/string-format.py +++ b/tests/basics/string-format.py @@ -60,26 +60,6 @@ test("{:@<6d}", -123) test("{:@=6d}", -123) test("{:06d}", -123) -test("{:10.4e}", 123.456) -test("{:10.4e}", -123.456) -test("{:10.4f}", 123.456) -test("{:10.4f}", -123.456) -test("{:10.4g}", 123.456) -test("{:10.4g}", -123.456) -test("{:e}", 100) -test("{:f}", 200) -test("{:g}", 300) - -test("{:10.4E}", 123.456) -test("{:10.4E}", -123.456) -test("{:10.4F}", 123.456) -test("{:10.4F}", -123.456) -test("{:10.4G}", 123.456) -test("{:10.4G}", -123.456) - -# The following fails right now -#test("{:10.1}", 0.0) - def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg): fmt = '{' if conv: @@ -137,71 +117,4 @@ if full_tests: for str in ('', 'a', 'bcd', 'This is a test with a longer string'): test_fmt(conv, fill, alignment, '', '', width, '', 's', str) -eg_nums = (0.0, -0.0, 0.1, 1.234, 12.3459, 1.23456789, 123456789.0, -0.0, - -0.1, -1.234, -12.3459, 1e4, 1e-4, 1e5, 1e-5, 1e6, 1e-6, 1e10, - 1e37, -1e37, 1e-37, -1e-37, - 1.23456e8, 1.23456e7, 1.23456e6, 1.23456e5, 1.23456e4, 1.23456e3, 1.23456e2, 1.23456e1, 1.23456e0, - 1.23456e-1, 1.23456e-2, 1.23456e-3, 1.23456e-4, 1.23456e-5, 1.23456e-6, 1.23456e-7, 1.23456e-8, - -1.23456e8, -1.23456e7, -1.23456e6, -1.23456e5, -1.23456e4, -1.23456e3, -1.23456e2, -1.23456e1, -1.23456e0, - -1.23456e-1, -1.23456e-2, -1.23456e-3, -1.23456e-4, -1.23456e-5, -1.23456e-6, -1.23456e-7, -1.23456e-8) - -if full_tests: - for type in ('e', 'E', 'g', 'G', 'n'): - for width in ('', '4', '6', '8', '10'): - for alignment in ('', '<', '>', '=', '^'): - for fill in ('', '@', '0', ' '): - for sign in ('', '+', '-', ' '): - for prec in ('', '1', '3', '6'): - for num in eg_nums: - test_fmt('', fill, alignment, sign, '', width, prec, type, num) - -# Note: We use 1.23459 rather than 1.2345 because '{:3f}'.format(1.2345) -# rounds differently than print("%.3f", 1.2345); - -f_nums = (0.0, -0.0, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, - 0.0012, 0.0123, 0.1234, 1.23459, 12.3456, - -0.0001, -0.001, -0.01, -0.1, -1.0, -10.0, - -0.0012, -0.0123, -0.1234, -1.23459, -12.3456) - -if full_tests: - for type in ('f', 'F'): - for width in ('', '4', '6', '8', '10'): - for alignment in ('', '<', '>', '=', '^'): - for fill in ('', ' ', '0', '@'): - for sign in ('', '+', '-', ' '): - # An empty precision defaults to 6, but when uPy is - # configured to use a float, we can only use a - # precision of 6 with numbers less than 10 and still - # get results that compare to CPython (which uses - # long doubles). - for prec in ('1', '2', '3'): - for num in f_nums: - test_fmt('', fill, alignment, sign, '', width, prec, type, num) - for num in int_nums2: - test_fmt('', fill, alignment, sign, '', width, '', type, num) - -pct_nums1 = (0.1, 0.58, 0.99, -0.1, -0.58, -0.99) -pct_nums2 = (True, False, 1, 0, -1) - -if full_tests: - type = '%' - for width in ('', '4', '6', '8', '10'): - for alignment in ('', '<', '>', '=', '^'): - for fill in ('', ' ', '0', '@'): - for sign in ('', '+', '-', ' '): - # An empty precision defaults to 6, but when uPy is - # configured to use a float, we can only use a - # precision of 6 with numbers less than 10 and still - # get results that compare to CPython (which uses - # long doubles). - for prec in ('1', '2', '3'): - for num in pct_nums1: - test_fmt('', fill, alignment, sign, '', width, prec, type, num) - for num in pct_nums2: - test_fmt('', fill, alignment, sign, '', width, '', type, num) - -# We don't currently test a type of '' with floats (see the detailed comment -# in objstr.c) - # TODO Add tests for erroneous format strings. - diff --git a/tests/basics/true-value.py b/tests/basics/true-value.py index 1dd547f326..9ec209fe82 100644 --- a/tests/basics/true-value.py +++ b/tests/basics/true-value.py @@ -9,12 +9,6 @@ if not None: if not 0: print("0") -if not 0.0: - print("float 0") - -if not 0+0j: - print("complex 0") - if not "": print("Empty string") if "foo": diff --git a/tests/basics/types1.py b/tests/basics/types1.py index 57b33b842b..38a20d6803 100644 --- a/tests/basics/types1.py +++ b/tests/basics/types1.py @@ -2,8 +2,6 @@ print(bool) print(int) -print(float) -print(complex) print(tuple) print(list) print(set) @@ -11,8 +9,6 @@ print(dict) print(type(bool()) == bool) print(type(int()) == int) -print(type(float()) == float) -print(type(complex()) == complex) print(type(tuple()) == tuple) print(type(list()) == list) print(type(set()) == set) @@ -20,8 +16,6 @@ print(type(dict()) == dict) print(type(False) == bool) print(type(0) == int) -print(type(0.0) == float) -print(type(1j) == complex) print(type(()) == tuple) print(type([]) == list) print(type({None}) == set) diff --git a/tests/basics/types2.py b/tests/basics/types2.py index 83a69c918f..ba7be6b154 100644 --- a/tests/basics/types2.py +++ b/tests/basics/types2.py @@ -9,4 +9,6 @@ print(int == int) print(int != list) d = {} -d[int] = float +d[int] = list +d[list] = int +print(len(d)) diff --git a/tests/basics/float1.py b/tests/float/float1.py index bf1305c3d5..bf1305c3d5 100644 --- a/tests/basics/float1.py +++ b/tests/float/float1.py diff --git a/tests/float/int-divzero.py b/tests/float/int-divzero.py new file mode 100644 index 0000000000..b037dd8c7b --- /dev/null +++ b/tests/float/int-divzero.py @@ -0,0 +1,4 @@ +try: + 1 / 0 +except ZeroDivisionError: + print("ZeroDivisionError") diff --git a/tests/float/list-index.py b/tests/float/list-index.py new file mode 100644 index 0000000000..13e4557af7 --- /dev/null +++ b/tests/float/list-index.py @@ -0,0 +1,8 @@ +x = [1, 2] + +print(x[1]) + +try: + print(x[1.0]) +except TypeError: + print("TypeError") diff --git a/tests/basics/math-fun-bool.py b/tests/float/math-fun-bool.py index cf718d4b80..cf718d4b80 100644 --- a/tests/basics/math-fun-bool.py +++ b/tests/float/math-fun-bool.py diff --git a/tests/basics/math-fun.py b/tests/float/math-fun.py index 7a37c58454..7a37c58454 100644 --- a/tests/basics/math-fun.py +++ b/tests/float/math-fun.py diff --git a/tests/float/modulo.py b/tests/float/modulo.py new file mode 100644 index 0000000000..911268513a --- /dev/null +++ b/tests/float/modulo.py @@ -0,0 +1,14 @@ +# check modulo matches python definition +# TODO we currenty fail with this +if False: + print(1.23456 % 0.7) + print(-1.23456 % 0.7) + print(1.23456 % -0.7) + print(-1.23456 % -0.7) + + a = 1.23456 + b = 0.7 + print(a % b) + print(a % -b) + print(-a % b) + print(-a % -b) diff --git a/tests/float/string-format-modulo.py b/tests/float/string-format-modulo.py new file mode 100644 index 0000000000..f2117f3565 --- /dev/null +++ b/tests/float/string-format-modulo.py @@ -0,0 +1,16 @@ +print("%s" % 1.0) +print("%r" % 1.0) + +print("%d" % 1.0) +print("%i" % 1.0) +print("%u" % 1.0) +print("%x" % 18.0) +print("%o" % 18.0) +print("%X" % 18.0) + +print("%e" % 1.23456) +print("%E" % 1.23456) +print("%f" % 1.23456) +print("%F" % 1.23456) +print("%g" % 1.23456) +print("%G" % 1.23456) diff --git a/tests/float/string-format.py b/tests/float/string-format.py new file mode 100644 index 0000000000..b5ff68b8ca --- /dev/null +++ b/tests/float/string-format.py @@ -0,0 +1,123 @@ +# Change the following to True to get a much more comprehensive set of tests +# to run, albeit, which take considerably longer. + +full_tests = False + +def test(fmt, *args): + print('{:8s}'.format(fmt) + '>' + fmt.format(*args) + '<') + +test("{:10.4e}", 123.456) +test("{:10.4e}", -123.456) +test("{:10.4f}", 123.456) +test("{:10.4f}", -123.456) +test("{:10.4g}", 123.456) +test("{:10.4g}", -123.456) +test("{:e}", 100) +test("{:f}", 200) +test("{:g}", 300) + +test("{:10.4E}", 123.456) +test("{:10.4E}", -123.456) +test("{:10.4F}", 123.456) +test("{:10.4F}", -123.456) +test("{:10.4G}", 123.456) +test("{:10.4G}", -123.456) + +# The following fails right now +#test("{:10.1}", 0.0) + +def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg): + fmt = '{' + if conv: + fmt += '!' + fmt += conv + fmt += ':' + if alignment: + fmt += fill + fmt += alignment + fmt += sign + fmt += prefix + fmt += width + if precision: + fmt += '.' + fmt += precision + fmt += type + fmt += '}' + test(fmt, arg) + if fill == '0' and alignment == '=': + fmt = '{:' + fmt += sign + fmt += prefix + fmt += width + if precision: + fmt += '.' + fmt += precision + fmt += type + fmt += '}' + test(fmt, arg) + +eg_nums = (0.0, -0.0, 0.1, 1.234, 12.3459, 1.23456789, 123456789.0, -0.0, + -0.1, -1.234, -12.3459, 1e4, 1e-4, 1e5, 1e-5, 1e6, 1e-6, 1e10, + 1e37, -1e37, 1e-37, -1e-37, + 1.23456e8, 1.23456e7, 1.23456e6, 1.23456e5, 1.23456e4, 1.23456e3, 1.23456e2, 1.23456e1, 1.23456e0, + 1.23456e-1, 1.23456e-2, 1.23456e-3, 1.23456e-4, 1.23456e-5, 1.23456e-6, 1.23456e-7, 1.23456e-8, + -1.23456e8, -1.23456e7, -1.23456e6, -1.23456e5, -1.23456e4, -1.23456e3, -1.23456e2, -1.23456e1, -1.23456e0, + -1.23456e-1, -1.23456e-2, -1.23456e-3, -1.23456e-4, -1.23456e-5, -1.23456e-6, -1.23456e-7, -1.23456e-8) + +if full_tests: + for type in ('e', 'E', 'g', 'G', 'n'): + for width in ('', '4', '6', '8', '10'): + for alignment in ('', '<', '>', '=', '^'): + for fill in ('', '@', '0', ' '): + for sign in ('', '+', '-', ' '): + for prec in ('', '1', '3', '6'): + for num in eg_nums: + test_fmt('', fill, alignment, sign, '', width, prec, type, num) + +# Note: We use 1.23459 rather than 1.2345 because '{:3f}'.format(1.2345) +# rounds differently than print("%.3f", 1.2345); + +f_nums = (0.0, -0.0, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, + 0.0012, 0.0123, 0.1234, 1.23459, 12.3456, + -0.0001, -0.001, -0.01, -0.1, -1.0, -10.0, + -0.0012, -0.0123, -0.1234, -1.23459, -12.3456) + +if full_tests: + for type in ('f', 'F'): + for width in ('', '4', '6', '8', '10'): + for alignment in ('', '<', '>', '=', '^'): + for fill in ('', ' ', '0', '@'): + for sign in ('', '+', '-', ' '): + # An empty precision defaults to 6, but when uPy is + # configured to use a float, we can only use a + # precision of 6 with numbers less than 10 and still + # get results that compare to CPython (which uses + # long doubles). + for prec in ('1', '2', '3'): + for num in f_nums: + test_fmt('', fill, alignment, sign, '', width, prec, type, num) + for num in int_nums2: + test_fmt('', fill, alignment, sign, '', width, '', type, num) + +pct_nums1 = (0.1, 0.58, 0.99, -0.1, -0.58, -0.99) +pct_nums2 = (True, False, 1, 0, -1) + +if full_tests: + type = '%' + for width in ('', '4', '6', '8', '10'): + for alignment in ('', '<', '>', '=', '^'): + for fill in ('', ' ', '0', '@'): + for sign in ('', '+', '-', ' '): + # An empty precision defaults to 6, but when uPy is + # configured to use a float, we can only use a + # precision of 6 with numbers less than 10 and still + # get results that compare to CPython (which uses + # long doubles). + for prec in ('1', '2', '3'): + for num in pct_nums1: + test_fmt('', fill, alignment, sign, '', width, prec, type, num) + for num in pct_nums2: + test_fmt('', fill, alignment, sign, '', width, '', type, num) + +# We don't currently test a type of '' with floats (see the detailed comment +# in objstr.c) diff --git a/tests/float/true-value.py b/tests/float/true-value.py new file mode 100644 index 0000000000..df415f0031 --- /dev/null +++ b/tests/float/true-value.py @@ -0,0 +1,7 @@ +# Test true-ish value handling + +if not 0.0: + print("float 0") + +if not 0+0j: + print("complex 0") diff --git a/tests/float/types.py b/tests/float/types.py new file mode 100644 index 0000000000..75674c9246 --- /dev/null +++ b/tests/float/types.py @@ -0,0 +1,17 @@ +# float types + +print(float) +print(complex) + +print(type(float()) == float) +print(type(complex()) == complex) + +print(type(0.0) == float) +print(type(1j) == complex) + +# hashing float types + +d = dict() +d[float] = complex +d[complex] = float +print(len(d)) diff --git a/tests/basics/import-pkg1.py b/tests/import/import-pkg1.py index 8cd77af79d..8cd77af79d 100644 --- a/tests/basics/import-pkg1.py +++ b/tests/import/import-pkg1.py diff --git a/tests/basics/import-pkg2.py b/tests/import/import-pkg2.py index 2e9f34121b..2e9f34121b 100644 --- a/tests/basics/import-pkg2.py +++ b/tests/import/import-pkg2.py diff --git a/tests/basics/import-pkg3.py b/tests/import/import-pkg3.py index 0ee885b220..0ee885b220 100644 --- a/tests/basics/import-pkg3.py +++ b/tests/import/import-pkg3.py diff --git a/tests/basics/import-pkg4.py b/tests/import/import-pkg4.py index 90b6f2e0ee..90b6f2e0ee 100644 --- a/tests/basics/import-pkg4.py +++ b/tests/import/import-pkg4.py diff --git a/tests/basics/import-pkg5.py b/tests/import/import-pkg5.py index aa74bb45f0..aa74bb45f0 100644 --- a/tests/basics/import-pkg5.py +++ b/tests/import/import-pkg5.py diff --git a/tests/basics/import1a.py b/tests/import/import1a.py index 16b2d4d30f..16b2d4d30f 100644 --- a/tests/basics/import1a.py +++ b/tests/import/import1a.py diff --git a/tests/basics/import1b.py b/tests/import/import1b.py index be74eca094..be74eca094 100644 --- a/tests/basics/import1b.py +++ b/tests/import/import1b.py diff --git a/tests/basics/import2a.py b/tests/import/import2a.py index ce32b10b1b..ce32b10b1b 100644 --- a/tests/basics/import2a.py +++ b/tests/import/import2a.py diff --git a/tests/basics/import3a.py b/tests/import/import3a.py index 2e9d41f71d..2e9d41f71d 100644 --- a/tests/basics/import3a.py +++ b/tests/import/import3a.py diff --git a/tests/basics/pkg/__init__.py b/tests/import/pkg/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/tests/basics/pkg/__init__.py +++ b/tests/import/pkg/__init__.py diff --git a/tests/basics/pkg/mod.py b/tests/import/pkg/mod.py index 9e67bdd291..9e67bdd291 100644 --- a/tests/basics/pkg/mod.py +++ b/tests/import/pkg/mod.py diff --git a/tests/basics/pkg2/__init__.py b/tests/import/pkg2/__init__.py index 101ac7d400..101ac7d400 100644 --- a/tests/basics/pkg2/__init__.py +++ b/tests/import/pkg2/__init__.py diff --git a/tests/basics/pkg2/mod1.py b/tests/import/pkg2/mod1.py index 03754a45f6..03754a45f6 100644 --- a/tests/basics/pkg2/mod1.py +++ b/tests/import/pkg2/mod1.py diff --git a/tests/basics/pkg2/mod2.py b/tests/import/pkg2/mod2.py index 97dadcde46..97dadcde46 100644 --- a/tests/basics/pkg2/mod2.py +++ b/tests/import/pkg2/mod2.py diff --git a/tests/basics/pkg3/__init__.py b/tests/import/pkg3/__init__.py index 8b92fa9967..8b92fa9967 100644 --- a/tests/basics/pkg3/__init__.py +++ b/tests/import/pkg3/__init__.py diff --git a/tests/basics/pkg3/mod1.py b/tests/import/pkg3/mod1.py index 28a0f5bf10..28a0f5bf10 100644 --- a/tests/basics/pkg3/mod1.py +++ b/tests/import/pkg3/mod1.py diff --git a/tests/basics/pkg3/mod2.py b/tests/import/pkg3/mod2.py index 67f43bad52..67f43bad52 100644 --- a/tests/basics/pkg3/mod2.py +++ b/tests/import/pkg3/mod2.py diff --git a/tests/basics/pkg3/subpkg1/__init__.py b/tests/import/pkg3/subpkg1/__init__.py index 72b5423958..72b5423958 100644 --- a/tests/basics/pkg3/subpkg1/__init__.py +++ b/tests/import/pkg3/subpkg1/__init__.py diff --git a/tests/basics/pkg3/subpkg1/mod1.py b/tests/import/pkg3/subpkg1/mod1.py index 7a2ae44b54..7a2ae44b54 100644 --- a/tests/basics/pkg3/subpkg1/mod1.py +++ b/tests/import/pkg3/subpkg1/mod1.py diff --git a/tests/basics/try-module.py b/tests/import/try-module.py index 03a9db15b5..03a9db15b5 100644 --- a/tests/basics/try-module.py +++ b/tests/import/try-module.py diff --git a/tests/run-tests b/tests/run-tests index bd6e50bbd2..da18c6c765 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -29,7 +29,8 @@ failed_tests = [] tests = [] if not sys.argv[1:]: - tests = sorted(glob('basics/*.py') + glob('io/*.py') + glob('misc/*.py')) + test_dirs = ('basics', 'float', 'import', 'io', 'misc') + tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files) else: tests = sys.argv[1:] @@ -56,13 +57,9 @@ for test_file in tests: if test_on_pyboard: pyb.enter_raw_repl() try: - if test_file == 'basics/memoryerror.py': - # this test crashes the pyboard - output_mupy = b'CRASH' - else: - output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n') + output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n') except pyboard.PyboardError: - output_mupy = b'CRASH\n' + output_mupy + output_mupy = b'CRASH' else: try: output_mupy = subprocess.check_output([MP_PY, '-X', 'emit=bytecode', test_file]) diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index 9c91b757a8..cf6e6fae26 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -10,12 +10,12 @@ #define MICROPY_ENABLE_REPL_HELPERS (1) #define MICROPY_ENABLE_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_ENABLE_PROPERTY (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_PATH_MAX (PATH_MAX) #define MICROPY_USE_COMPUTED_GOTOS (1) #define MICROPY_MOD_SYS_STDFILES (1) +#define MICROPY_ENABLE_MOD_CMATH (1) // type definitions for the specific machine |