summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtin.h1
-rw-r--r--py/builtintables.c3
-rw-r--r--py/modcmath.c131
-rw-r--r--py/modmath.c9
-rw-r--r--py/mpconfig.h12
-rw-r--r--py/py.mk1
-rw-r--r--py/qstrdefs.h9
-rw-r--r--py/runtime.c5
-rw-r--r--py/vm.c66
-rw-r--r--stmhal/Makefile1
-rw-r--r--stmhal/main.c36
-rw-r--r--stmhal/malloc0.c37
-rw-r--r--stmhal/std.h2
-rw-r--r--stmhal/stm32f4xx_it.c34
-rw-r--r--stmhal/usbd_desc_cdc_msc.c18
-rw-r--r--tests/README4
-rw-r--r--tests/basics/int-divzero.py5
-rw-r--r--tests/basics/list1.py5
-rw-r--r--tests/basics/modulo.py17
-rw-r--r--tests/basics/string-format-modulo.py14
-rw-r--r--tests/basics/string-format.py87
-rw-r--r--tests/basics/true-value.py6
-rw-r--r--tests/basics/types1.py6
-rw-r--r--tests/basics/types2.py4
-rw-r--r--tests/float/float1.py (renamed from tests/basics/float1.py)0
-rw-r--r--tests/float/int-divzero.py4
-rw-r--r--tests/float/list-index.py8
-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.py14
-rw-r--r--tests/float/string-format-modulo.py16
-rw-r--r--tests/float/string-format.py123
-rw-r--r--tests/float/true-value.py7
-rw-r--r--tests/float/types.py17
-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-xtests/run-tests11
-rw-r--r--unix/mpconfigport.h2
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
diff --git a/py/py.mk b/py/py.mk
index 5d02c95faf..996cbee4e3 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -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)));
diff --git a/py/vm.c b/py/vm.c
index 1c154007ca..e42e54941e 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -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