From 37379a2974190ab0fc97f840112d5a40c907368b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 29 Aug 2017 00:06:21 +0300 Subject: py/objstr: startswith, endswith: Check arg to be a string. Otherwise, it will silently get incorrect result on other values types, including CPython tuple form like "foo.png".endswith(("png", "jpg")) (which MicroPython doesn't support for unbloatedness). --- py/objstr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'py') diff --git a/py/objstr.c b/py/objstr.c index d4c038a68..f04bd90be 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -726,7 +726,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex); STATIC mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); GET_STR_DATA_LEN(args[0], str, str_len); - GET_STR_DATA_LEN(args[1], prefix, prefix_len); + size_t prefix_len; + const char *prefix = mp_obj_str_get_data(args[1], &prefix_len); const byte *start = str; if (n_args > 2) { start = str_index_to_ptr(self_type, str, str_len, args[2], true); @@ -740,7 +741,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith); STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { GET_STR_DATA_LEN(args[0], str, str_len); - GET_STR_DATA_LEN(args[1], suffix, suffix_len); + size_t suffix_len; + const char *suffix = mp_obj_str_get_data(args[1], &suffix_len); if (n_args > 2) { mp_raise_NotImplementedError("start/end indices"); } -- cgit v1.2.3 From be8e5744e64aec10a3499fd6ea034bbf4be0c871 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Aug 2017 12:52:18 +1000 Subject: py/nlrx86,x64: Replace #define of defined() with portable macro usage. Using gcc -Wpedantic will warn that #define of defined() is non-portable and this patch fixes this. --- py/nlrx64.c | 6 +++++- py/nlrx86.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'py') diff --git a/py/nlrx64.c b/py/nlrx64.c index c23fd8fc6..aeaacd50c 100644 --- a/py/nlrx64.c +++ b/py/nlrx64.c @@ -34,7 +34,11 @@ // x86-64 callee-save registers are: // rbx, rbp, rsp, r12, r13, r14, r15 -#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__)) +#if defined(_WIN32) || defined(__CYGWIN__) +#define NLR_OS_WINDOWS 1 +#else +#define NLR_OS_WINDOWS 0 +#endif __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); diff --git a/py/nlrx86.c b/py/nlrx86.c index 58aaa1a57..8d15d7bab 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -35,7 +35,11 @@ // For reference, x86 callee save regs are: // ebx, esi, edi, ebp, esp, eip -#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__)) +#if defined(_WIN32) || defined(__CYGWIN__) +#define NLR_OS_WINDOWS 1 +#else +#define NLR_OS_WINDOWS 0 +#endif #if NLR_OS_WINDOWS unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail"); -- cgit v1.2.3 From 58321dd9854d71a96e5db2d361e0efc05d9de8cf Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Aug 2017 13:04:01 +1000 Subject: all: Convert mp_uint_t to mp_unary_op_t/mp_binary_op_t where appropriate The unary-op/binary-op enums are already defined, and there are no arithmetic tricks used with these types, so it makes sense to use the correct enum type for arguments that take these values. It also reduces code size quite a bit for nan-boxing builds. --- extmod/modbtree.c | 2 +- extmod/modutimeq.c | 2 +- py/obj.c | 2 +- py/obj.h | 11 ++++++----- py/objarray.c | 4 ++-- py/objbool.c | 4 ++-- py/objcomplex.c | 6 +++--- py/objdict.c | 6 +++--- py/objfloat.c | 6 +++--- py/objint.c | 6 +++--- py/objint.h | 6 +++--- py/objint_longlong.c | 4 ++-- py/objint_mpz.c | 4 ++-- py/objlist.c | 4 ++-- py/objrange.c | 2 +- py/objset.c | 4 ++-- py/objstr.c | 7 ++++--- py/objstr.h | 2 +- py/objstrunicode.c | 2 +- py/objtuple.c | 4 ++-- py/objtuple.h | 4 ++-- py/objtype.c | 4 ++-- py/runtime.c | 4 ++-- py/runtime.h | 4 ++-- unix/modjni.c | 2 +- 25 files changed, 54 insertions(+), 52 deletions(-) (limited to 'py') diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 229daaf0f..5017079da 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -281,7 +281,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } -STATIC mp_obj_t btree_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in); switch (op) { case MP_BINARY_OP_IN: { diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index a19b3fda9..faa589583 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -189,7 +189,7 @@ STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_dump_obj, mod_utimeq_dump); #endif -STATIC mp_obj_t utimeq_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t utimeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_utimeq_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0); diff --git a/py/obj.c b/py/obj.c index 515a95b2e..0dab5f2ac 100644 --- a/py/obj.c +++ b/py/obj.c @@ -505,7 +505,7 @@ void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flag } } -mp_obj_t mp_generic_unary_op(mp_uint_t op, mp_obj_t o_in) { +mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in) { switch (op) { case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); default: return MP_OBJ_NULL; // op not supported diff --git a/py/obj.h b/py/obj.h index 22bfda0f9..2adcab1a6 100644 --- a/py/obj.h +++ b/py/obj.h @@ -30,6 +30,7 @@ #include "py/misc.h" #include "py/qstr.h" #include "py/mpprint.h" +#include "py/runtime0.h" // This is the definition of the opaque MicroPython object type. // All concrete objects have an encoding within this type and the @@ -429,8 +430,8 @@ typedef struct _mp_obj_iter_buf_t { typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind); typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args); -typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t); -typedef mp_obj_t (*mp_binary_op_fun_t)(mp_uint_t op, mp_obj_t, mp_obj_t); +typedef mp_obj_t (*mp_unary_op_fun_t)(mp_unary_op_t op, mp_obj_t); +typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_t op, mp_obj_t, mp_obj_t); typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); @@ -694,7 +695,7 @@ mp_obj_t mp_obj_id(mp_obj_t o_in); mp_obj_t mp_obj_len(mp_obj_t o_in); mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); -mp_obj_t mp_generic_unary_op(mp_uint_t op, mp_obj_t o_in); +mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in); // cell mp_obj_t mp_obj_cell_get(mp_obj_t self_in); @@ -734,11 +735,11 @@ mp_int_t mp_float_hash(mp_float_t val); #else static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; } #endif -mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported +mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported // complex void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); -mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported +mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported #else #define mp_obj_is_float(o) (false) #endif diff --git a/py/objarray.c b/py/objarray.c index a31c53680..d51cc650b 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -231,7 +231,7 @@ STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, } #endif -STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) { +STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0); @@ -240,7 +240,7 @@ STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) { } } -STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in); switch (op) { case MP_BINARY_OP_ADD: { diff --git a/py/objbool.c b/py/objbool.c index e5bc3c228..b94c57f87 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -63,7 +63,7 @@ STATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ } } -STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) { +STATIC mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) { if (op == MP_UNARY_OP_LEN) { return MP_OBJ_NULL; } @@ -71,7 +71,7 @@ STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) { return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(self->value)); } -STATIC mp_obj_t bool_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_bool_t *self = MP_OBJ_TO_PTR(lhs_in); return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(self->value), rhs_in); } diff --git a/py/objcomplex.c b/py/objcomplex.c index 55627afea..07b9d5d41 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -117,7 +117,7 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si } } -STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) { +STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0); @@ -128,7 +128,7 @@ STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) { } } -STATIC mp_obj_t complex_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t complex_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_complex_t *lhs = MP_OBJ_TO_PTR(lhs_in); return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in); } @@ -171,7 +171,7 @@ void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) { *imag = self->imag; } -mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) { +mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) { mp_float_t rhs_real, rhs_imag; mp_obj_get_complex(rhs_in, &rhs_real, &rhs_imag); // can be any type, this function will convert to float (if possible) switch (op) { diff --git a/py/objdict.c b/py/objdict.c index f6357a905..6bb243562 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -100,7 +100,7 @@ STATIC mp_obj_t dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n return dict_out; } -STATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->map.used != 0); @@ -115,7 +115,7 @@ STATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in); switch (op) { case MP_BINARY_OP_IN: { @@ -482,7 +482,7 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ mp_print_str(print, "])"); } -STATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // only supported for the 'keys' kind until sets and dicts are refactored mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in); if (o->kind != MP_DICT_VIEW_KEYS) { diff --git a/py/objfloat.c b/py/objfloat.c index 15edd810f..b1900b236 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -155,7 +155,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size } } -STATIC mp_obj_t float_unary_op(mp_uint_t op, mp_obj_t o_in) { +STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_float_t val = mp_obj_float_get(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0); @@ -166,7 +166,7 @@ STATIC mp_obj_t float_unary_op(mp_uint_t op, mp_obj_t o_in) { } } -STATIC mp_obj_t float_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_float_t lhs_val = mp_obj_float_get(lhs_in); #if MICROPY_PY_BUILTINS_COMPLEX if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) { @@ -239,7 +239,7 @@ STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) { *y = mod; } -mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_in) { +mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs_in) { mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible) switch (op) { case MP_BINARY_OP_ADD: diff --git a/py/objint.c b/py/objint.c index 29d889629..6a73b4382 100644 --- a/py/objint.c +++ b/py/objint.c @@ -325,12 +325,12 @@ mp_obj_t mp_obj_int_abs(mp_obj_t self_in) { } // This is called for operations on SMALL_INT that are not handled by mp_unary_op -mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { +mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { return MP_OBJ_NULL; // op not supported } // This is called for operations on SMALL_INT that are not handled by mp_binary_op -mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } @@ -382,7 +382,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { // This dispatcher function is expected to be independent of the implementation of long int // It handles the extra cases for integer-like arithmetic -mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (rhs_in == mp_const_false) { // false acts as 0 return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0)); diff --git a/py/objint.h b/py/objint.h index 394c23714..a4d4ff32d 100644 --- a/py/objint.h +++ b/py/objint.h @@ -58,9 +58,9 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); int mp_obj_int_sign(mp_obj_t self_in); mp_obj_t mp_obj_int_abs(mp_obj_t self_in); -mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in); -mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); -mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); +mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in); +mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); +mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus); #endif // MICROPY_INCLUDED_PY_OBJINT_H diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 02c005d2f..ddfdae744 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -118,7 +118,7 @@ mp_obj_t mp_obj_int_abs(mp_obj_t self_in) { } } -mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { +mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_int_t *o = o_in; switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->val != 0); @@ -134,7 +134,7 @@ mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { } } -mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { long long lhs_val; long long rhs_val; diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 0791a8af2..148446f0f 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -162,7 +162,7 @@ mp_obj_t mp_obj_int_abs(mp_obj_t self_in) { } } -mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { +mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(!mpz_is_zero(&o->mpz)); @@ -174,7 +174,7 @@ mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { } } -mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { const mpz_t *zlhs; const mpz_t *zrhs; mpz_t z_int; diff --git a/py/objlist.c b/py/objlist.c index 86d430062..6ac33e80e 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -99,7 +99,7 @@ STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); } -STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0); @@ -114,7 +114,7 @@ STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { +STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs); switch (op) { case MP_BINARY_OP_ADD: { diff --git a/py/objrange.c b/py/objrange.c index 33b07a9d4..fa99c4c2d 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -130,7 +130,7 @@ STATIC mp_int_t range_len(mp_obj_range_t *self) { return len; } -STATIC mp_obj_t range_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = range_len(self); switch (op) { diff --git a/py/objset.c b/py/objset.c index 376439b73..d4a8a1a39 100644 --- a/py/objset.c +++ b/py/objset.c @@ -455,7 +455,7 @@ STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union); -STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t set_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->set.used != 0); @@ -480,7 +480,7 @@ STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t set_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { +STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_t args[] = {lhs, rhs}; #if MICROPY_PY_BUILTINS_FROZENSET bool update = MP_OBJ_IS_TYPE(lhs, &mp_type_set); diff --git a/py/objstr.c b/py/objstr.c index f04bd90be..4c287af04 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -280,7 +280,7 @@ const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, // Note: this function is used to check if an object is a str or bytes, which // works because both those types use it as their binary_op method. Revisit // MP_OBJ_IS_STR_OR_BYTES if this fact changes. -mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // check for modulo if (op == MP_BINARY_OP_MODULO) { mp_obj_t *args = &rhs_in; @@ -380,9 +380,10 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_data, lhs_len, rhs_data, rhs_len)); - } - return MP_OBJ_NULL; // op not supported + default: + return MP_OBJ_NULL; // op not supported + } } #if !MICROPY_PY_BUILTINS_STR_UNICODE diff --git a/py/objstr.h b/py/objstr.h index 3aef8c68e..82501a763 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -67,7 +67,7 @@ mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args); mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len); -mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); +mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 036f7f3c1..785317406 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -100,7 +100,7 @@ STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } } -STATIC mp_obj_t uni_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, str_data, str_len); switch (op) { case MP_UNARY_OP_BOOL: diff --git a/py/objtuple.c b/py/objtuple.c index 765edb907..079b5cbdb 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -118,7 +118,7 @@ STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); } -mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) { +mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0); @@ -135,7 +135,7 @@ mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) { } } -mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { +mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs); switch (op) { case MP_BINARY_OP_ADD: diff --git a/py/objtuple.h b/py/objtuple.h index 05c6490fe..74cde88d3 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -41,8 +41,8 @@ typedef struct _mp_rom_obj_tuple_t { } mp_rom_obj_tuple_t; void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); -mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in); -mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs); +mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in); +mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value); mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf); diff --git a/py/objtype.c b/py/objtype.c index e1a24da7e..08e276d72 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -345,7 +345,7 @@ const qstr mp_unary_op_method_name[] = { [MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size }; -STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_SYS_GETSIZEOF @@ -452,7 +452,7 @@ const qstr mp_binary_op_method_name[] = { [MP_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size }; -STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // Note: For ducktyping, CPython does not look in the instance members or use // __getattr__ or __getattribute__. It only looks in the class dictionary. mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in); diff --git a/py/runtime.c b/py/runtime.c index eb1298813..1db6c93c3 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -209,7 +209,7 @@ void mp_delete_global(qstr qst) { mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst)); } -mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) { +mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg); if (op == MP_UNARY_OP_NOT) { @@ -261,7 +261,7 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) { } } -mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { +mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { DEBUG_OP_printf("binary " UINT_FMT " %p %p\n", op, lhs, rhs); // TODO correctly distinguish inplace operators for mutable objects diff --git a/py/runtime.h b/py/runtime.h index 428e2571c..4abdea584 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -96,8 +96,8 @@ void mp_store_global(qstr qst, mp_obj_t obj); void mp_delete_name(qstr qst); void mp_delete_global(qstr qst); -mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg); -mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs); +mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg); +mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t mp_call_function_0(mp_obj_t fun); mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg); diff --git a/unix/modjni.c b/unix/modjni.c index df9cd9d67..85fc89144 100644 --- a/unix/modjni.c +++ b/unix/modjni.c @@ -293,7 +293,7 @@ STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) return MP_OBJ_NULL; } -STATIC mp_obj_t jobject_unary_op(mp_uint_t op, mp_obj_t self_in) { +STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_jobject_t *self = self_in; switch (op) { case MP_UNARY_OP_BOOL: -- cgit v1.2.3 From 784909ce1655bf8b2a97ac81a3842e844992082f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 30 Aug 2017 01:35:48 +0300 Subject: py/objtype: Handle NotImplemented return from binary special methods. NotImplemented means "try other fallbacks (like calling __rop__ instead of __op__) and if nothing works, raise TypeError". As MicroPython doesn't implement any fallbacks, signal to raise TypeError right away. --- py/obj.h | 1 + py/objtype.c | 18 ++++++++++++++-- tests/basics/class_notimpl.py | 50 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 tests/basics/class_notimpl.py (limited to 'py') diff --git a/py/obj.h b/py/obj.h index 2adcab1a6..323423b3e 100644 --- a/py/obj.h +++ b/py/obj.h @@ -616,6 +616,7 @@ extern const mp_obj_type_t mp_type_ZeroDivisionError; #define mp_const_true (MP_OBJ_FROM_PTR(&mp_const_true_obj)) #define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj)) #define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj)) +#define mp_const_notimplemented (MP_OBJ_FROM_PTR(&mp_const_notimplemented_obj)) extern const struct _mp_obj_none_t mp_const_none_obj; extern const struct _mp_obj_bool_t mp_const_false_obj; extern const struct _mp_obj_bool_t mp_const_true_obj; diff --git a/py/objtype.c b/py/objtype.c index 08e276d72..4973236a4 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -471,14 +471,28 @@ STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t .is_type = false, }; mp_obj_class_lookup(&lookup, lhs->base.type); + + mp_obj_t res; if (dest[0] == MP_OBJ_SENTINEL) { - return mp_binary_op(op, lhs->subobj[0], rhs_in); + res = mp_binary_op(op, lhs->subobj[0], rhs_in); } else if (dest[0] != MP_OBJ_NULL) { dest[2] = rhs_in; - return mp_call_method_n_kw(1, 0, dest); + res = mp_call_method_n_kw(1, 0, dest); } else { return MP_OBJ_NULL; // op not supported } + + #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED + // NotImplemented means "try other fallbacks (like calling __rop__ + // instead of __op__) and if nothing works, raise TypeError". As + // MicroPython doesn't implement any fallbacks, signal to raise + // TypeError right away. + if (res == mp_const_notimplemented) { + return MP_OBJ_NULL; // op not supported + } + #endif + + return res; } STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { diff --git a/tests/basics/class_notimpl.py b/tests/basics/class_notimpl.py new file mode 100644 index 000000000..7fd8166f9 --- /dev/null +++ b/tests/basics/class_notimpl.py @@ -0,0 +1,50 @@ +# Test that returning of NotImplemented from binary op methods leads to +# TypeError. +try: + NotImplemented +except NameError: + print("SKIP") + raise SystemExit + +class C: + def __init__(self, value): + self.value = value + + def __str__(self): + return "C(%s)" % self.value + + def __add__(self, rhs): + print(self, '+', rhs) + return NotImplemented + + def __sub__(self, rhs): + print(self, '-', rhs) + return NotImplemented + + def __lt__(self, rhs): + print(self, '<', rhs) + return NotImplemented + + def __neg__(self): + print('-', self) + return NotImplemented + +c = C(0) + +try: + c + 1 +except TypeError: + print("TypeError") + +try: + c - 2 +except TypeError: + print("TypeError") + +try: + c < 1 +except TypeError: + print("TypeError") + +# NotImplemented isn't handled specially in unary methods +print(-c) -- cgit v1.2.3 From 0102ee092b590be2736521ebf165c96bcf0bcbe6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 30 Aug 2017 21:02:00 +1000 Subject: py: Change obsolete "///" comment formatting to normal comments. This comment style is no longer used because the docs are written by hand, not generated. --- py/modcmath.c | 32 +++++++--------------- py/modgc.c | 17 ++++-------- py/modmath.c | 86 +++++++++++++++++++++++++---------------------------------- py/modsys.c | 15 +++-------- 4 files changed, 55 insertions(+), 95 deletions(-) (limited to 'py') diff --git a/py/modcmath.c b/py/modcmath.c index 627a2cbad..70fd542af 100644 --- a/py/modcmath.c +++ b/py/modcmath.c @@ -30,13 +30,7 @@ #include -/// \module cmath - mathematical functions for complex numbers -/// -/// The `cmath` module provides some basic mathematical funtions for -/// working with complex numbers. - -/// \function phase(z) -/// Returns the phase of the number `z`, in the range (-pi, +pi]. +// phase(z): returns the phase of the number z in the range (-pi, +pi] STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); @@ -44,8 +38,7 @@ STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase); -/// \function polar(z) -/// Returns, as a tuple, the polar form of `z`. +// polar(z): returns the polar form of z as a tuple STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); @@ -57,8 +50,7 @@ STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar); -/// \function rect(r, phi) -/// Returns the complex number with modulus `r` and phase `phi`. +// rect(r, phi): returns the complex number with modulus r and phase phi STATIC 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); @@ -66,8 +58,7 @@ STATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect); -/// \function exp(z) -/// Return the exponential of `z`. +// exp(z): return the exponential of z STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); @@ -76,8 +67,7 @@ STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp); -/// \function log(z) -/// Return the natural logarithm of `z`. The branch cut is along the negative real axis. +// log(z): return the natural logarithm of z, with branch cut along the negative real axis // TODO can take second argument, being the base STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) { mp_float_t real, imag; @@ -87,8 +77,7 @@ STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log); #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS -/// \function log10(z) -/// Return the base-10 logarithm of `z`. The branch cut is along the negative real axis. +// log10(z): return the base-10 logarithm of z, with branch cut along the negative real axis STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); @@ -97,8 +86,7 @@ STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10); #endif -/// \function sqrt(z) -/// Return the square-root of `z`. +// sqrt(z): return the square-root of z STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); @@ -108,8 +96,7 @@ STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt); -/// \function cos(z) -/// Return the cosine of `z`. +// cos(z): return the cosine of z STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); @@ -117,8 +104,7 @@ STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos); -/// \function sin(z) -/// Return the sine of `z`. +// sin(z): return the sine of z STATIC mp_obj_t mp_cmath_sin(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); diff --git a/py/modgc.c b/py/modgc.c index d45e007eb..55e73defc 100644 --- a/py/modgc.c +++ b/py/modgc.c @@ -30,10 +30,7 @@ #if MICROPY_PY_GC && MICROPY_ENABLE_GC -/// \module gc - control the garbage collector - -/// \function collect() -/// Run a garbage collection. +// collect(): run a garbage collection STATIC mp_obj_t py_gc_collect(void) { gc_collect(); #if MICROPY_PY_GC_COLLECT_RETVAL @@ -44,16 +41,14 @@ STATIC mp_obj_t py_gc_collect(void) { } MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect); -/// \function disable() -/// Disable the garbage collector. +// disable(): disable the garbage collector STATIC mp_obj_t gc_disable(void) { MP_STATE_MEM(gc_auto_collect_enabled) = 0; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable); -/// \function enable() -/// Enable the garbage collector. +// enable(): enable the garbage collector STATIC mp_obj_t gc_enable(void) { MP_STATE_MEM(gc_auto_collect_enabled) = 1; return mp_const_none; @@ -65,8 +60,7 @@ STATIC mp_obj_t gc_isenabled(void) { } MP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled); -/// \function mem_free() -/// Return the number of bytes of available heap RAM. +// mem_free(): return the number of bytes of available heap RAM STATIC mp_obj_t gc_mem_free(void) { gc_info_t info; gc_info(&info); @@ -74,8 +68,7 @@ STATIC mp_obj_t gc_mem_free(void) { } MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free); -/// \function mem_alloc() -/// Return the number of bytes of heap RAM that are allocated. +// mem_alloc(): return the number of bytes of heap RAM that are allocated STATIC mp_obj_t gc_mem_alloc(void) { gc_info_t info; gc_info(&info); diff --git a/py/modmath.c b/py/modmath.c index c56056a5d..4d627c67f 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -35,11 +35,6 @@ // And by defining our own we can ensure it uses the correct const format. #define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846) -/// \module math - mathematical functions -/// -/// The `math` module provides some basic mathematical funtions for -/// working with floating-point numbers. - STATIC NORETURN void math_error(void) { mp_raise_ValueError("math domain error"); } @@ -75,80 +70,74 @@ STATIC NORETURN void math_error(void) { #define log2(x) (log(x) * 1.442695040888963407354163704) #endif -/// \function sqrt(x) -/// Returns the square root of `x`. +// sqrt(x): returns the square root of x MATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0)) -/// \function pow(x, y) -/// Returns `x` to the power of `y`. +// pow(x, y): returns x to the power of y MATH_FUN_2(pow, pow) -/// \function exp(x) +// exp(x) MATH_FUN_1(exp, exp) #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS -/// \function expm1(x) +// expm1(x) MATH_FUN_1(expm1, expm1) -/// \function log2(x) +// log2(x) MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0)) -/// \function log10(x) +// log10(x) MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0)) -/// \function cosh(x) +// cosh(x) MATH_FUN_1(cosh, cosh) -/// \function sinh(x) +// sinh(x) MATH_FUN_1(sinh, sinh) -/// \function tanh(x) +// tanh(x) MATH_FUN_1(tanh, tanh) -/// \function acosh(x) +// acosh(x) MATH_FUN_1(acosh, acosh) -/// \function asinh(x) +// asinh(x) MATH_FUN_1(asinh, asinh) -/// \function atanh(x) +// atanh(x) MATH_FUN_1(atanh, atanh) #endif -/// \function cos(x) +// cos(x) MATH_FUN_1(cos, cos) -/// \function sin(x) +// sin(x) MATH_FUN_1(sin, sin) -/// \function tan(x) +// tan(x) MATH_FUN_1(tan, tan) -/// \function acos(x) +// acos(x) MATH_FUN_1(acos, acos) -/// \function asin(x) +// asin(x) MATH_FUN_1(asin, asin) -/// \function atan(x) +// atan(x) MATH_FUN_1(atan, atan) -/// \function atan2(y, x) +// atan2(y, x) MATH_FUN_2(atan2, atan2) -/// \function ceil(x) +// ceil(x) MATH_FUN_1_TO_INT(ceil, ceil) -/// \function copysign(x, y) +// copysign(x, y) MATH_FUN_2(copysign, copysign) -/// \function fabs(x) +// fabs(x) MATH_FUN_1(fabs, fabs) -/// \function floor(x) +// floor(x) MATH_FUN_1_TO_INT(floor, floor) //TODO: delegate to x.__floor__() if x is not a float -/// \function fmod(x, y) +// fmod(x, y) MATH_FUN_2(fmod, fmod) -/// \function isfinite(x) +// isfinite(x) MATH_FUN_1_TO_BOOL(isfinite, isfinite) -/// \function isinf(x) +// isinf(x) MATH_FUN_1_TO_BOOL(isinf, isinf) -/// \function isnan(x) +// isnan(x) MATH_FUN_1_TO_BOOL(isnan, isnan) -/// \function trunc(x) +// trunc(x) MATH_FUN_1_TO_INT(trunc, trunc) -/// \function ldexp(x, exp) +// ldexp(x, exp) MATH_FUN_2(ldexp, ldexp) #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS -/// \function erf(x) -/// Return the error function of `x`. +// erf(x): return the error function of x MATH_FUN_1(erf, erf) -/// \function erfc(x) -/// Return the complementary error function of `x`. +// erfc(x): return the complementary error function of x MATH_FUN_1(erfc, erfc) -/// \function gamma(x) -/// Return the gamma function of `x`. +// gamma(x): return the gamma function of x MATH_FUN_1(gamma, tgamma) -/// \function lgamma(x) -/// return the natural logarithm of the gamma function of `x`. +// lgamma(x): return the natural logarithm of the gamma function of x MATH_FUN_1(lgamma, lgamma) #endif //TODO: factorial, fsum @@ -178,8 +167,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_math_log_obj, 1, 2, mp_math_log); // Functions that return a tuple -/// \function frexp(x) -/// Converts a floating-point number to fractional and integral components. +// frexp(x): converts a floating-point number to fractional and integral components STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) { int int_exponent = 0; mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent); @@ -190,7 +178,7 @@ STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp); -/// \function modf(x) +// modf(x) STATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) { mp_float_t int_part = 0.0; mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(mp_obj_get_float(x_obj), &int_part); @@ -203,13 +191,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf); // Angular conversions -/// \function radians(x) +// radians(x) STATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) { return mp_obj_new_float(mp_obj_get_float(x_obj) * (MP_PI / MICROPY_FLOAT_CONST(180.0))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians); -/// \function degrees(x) +// degrees(x) STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) { return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI)); } diff --git a/py/modsys.c b/py/modsys.c index b7d55fdcc..ecc0b6065 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -42,8 +42,6 @@ #include "genhdr/mpversion.h" -/// \module sys - system specific functions - // defined per port; type of these is irrelevant, just need pointer extern struct _mp_dummy_t mp_sys_stdin_obj; extern struct _mp_dummy_t mp_sys_stdout_obj; @@ -53,10 +51,10 @@ extern struct _mp_dummy_t mp_sys_stderr_obj; const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adaptor}; #endif -/// \constant version - Python language version that this implementation conforms to, as a string +// version - Python language version that this implementation conforms to, as a string STATIC const MP_DEFINE_STR_OBJ(version_obj, "3.4.0"); -/// \constant version_info - Python language version that this implementation conforms to, as a tuple of ints +// version_info - Python language version that this implementation conforms to, as a tuple of ints #define I(n) MP_OBJ_NEW_SMALL_INT(n) // TODO: CPython is now at 5-element array, but save 2 els so far... STATIC const mp_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {I(3), I(4), I(0)}}; @@ -91,13 +89,11 @@ STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { #undef I #ifdef MICROPY_PY_SYS_PLATFORM -/// \constant platform - the platform that MicroPython is running on +// platform - the platform that MicroPython is running on STATIC const MP_DEFINE_STR_OBJ(platform_obj, MICROPY_PY_SYS_PLATFORM); #endif -/// \function exit([retval]) -/// Raise a `SystemExit` exception. If an argument is given, it is the -/// value given to `SystemExit`. +// exit([retval]): raise SystemExit, with optional argument given to the exception STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { mp_obj_t exc; if (n_args == 0) { @@ -163,7 +159,6 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { #ifdef MICROPY_PY_SYS_PLATFORM { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) }, #endif - /// \constant byteorder - the byte order of the system ("little" or "big") #if MP_ENDIANNESS_LITTLE { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_little) }, #else @@ -184,12 +179,10 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { #endif #if MICROPY_PY_SYS_EXIT - // documented per-port { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) }, #endif #if MICROPY_PY_SYS_STDFILES - // documented per-port { MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) }, { MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) }, { MP_ROM_QSTR(MP_QSTR_stderr), MP_ROM_PTR(&mp_sys_stderr_obj) }, -- cgit v1.2.3 From df6605eaba1b07a8e95349b0b8fb8dec9a13fa36 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 30 Aug 2017 20:44:18 +0300 Subject: py/objtype: mp_obj_instance_make_new: Fix typos in comment. --- py/objtype.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'py') diff --git a/py/objtype.c b/py/objtype.c index 4973236a4..54cf844b6 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -251,9 +251,9 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self, num_native_bases)); - // This executes only "__new__" part of obejection creation. - // TODO: This won't work will for classes with native bases. - // TODO: This is hack, should be resolved along the lines of + // This executes only "__new__" part of instance creation. + // TODO: This won't work well for classes with native bases. + // TODO: This is a hack, should be resolved along the lines of // https://github.com/micropython/micropython/issues/606#issuecomment-43685883 if (n_args == 1 && *args == MP_OBJ_SENTINEL) { return MP_OBJ_FROM_PTR(o); -- cgit v1.2.3 From 4556bd2acd16b32d5e1c60042f4f43a20285c313 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 31 Aug 2017 00:44:51 +0300 Subject: py/objtype: mp_obj_class_lookup: Improve debug logging. Now traces more explicitly thru the lookup process. --- py/objtype.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'py') diff --git a/py/objtype.c b/py/objtype.c index 54cf844b6..68c1da7b8 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -113,13 +113,15 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ assert(lookup->dest[0] == MP_OBJ_NULL); assert(lookup->dest[1] == MP_OBJ_NULL); for (;;) { + DEBUG_printf("mp_obj_class_lookup: Looking up %s in %s\n", qstr_str(lookup->attr), qstr_str(type->name)); // Optimize special method lookup for native types // This avoids extra method_name => slot lookup. On the other hand, // this should not be applied to class types, as will result in extra // lookup either. if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) { if (*(void**)((char*)type + lookup->meth_offset) != NULL) { - DEBUG_printf("mp_obj_class_lookup: matched special meth slot for %s\n", qstr_str(lookup->attr)); + DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n", + lookup->meth_offset, qstr_str(lookup->attr)); lookup->dest[0] = MP_OBJ_SENTINEL; return; } @@ -150,7 +152,8 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ #if DEBUG_PRINT printf("mp_obj_class_lookup: Returning: "); mp_obj_print(lookup->dest[0], PRINT_REPR); printf(" "); - mp_obj_print(lookup->dest[1], PRINT_REPR); printf("\n"); + // Don't try to repr() lookup->dest[1], as we can be called recursively + printf("<%s @%p>\n", mp_obj_get_type_str(lookup->dest[1]), lookup->dest[1]); #endif return; } @@ -169,6 +172,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ // attribute not found, keep searching base classes if (type->parent == NULL) { + DEBUG_printf("mp_obj_class_lookup: No more parents\n"); return; } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { const mp_obj_tuple_t *parent_tuple = type->parent; -- cgit v1.2.3 From 0e420d48eea1357275a7e418463f88d254049fb6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Aug 2017 16:45:02 +1000 Subject: py/map: Replace always-false condition with assertion. --- py/map.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'py') diff --git a/py/map.c b/py/map.c index 7f3c90059..6d6337229 100644 --- a/py/map.c +++ b/py/map.c @@ -148,11 +148,8 @@ STATIC void mp_map_rehash(mp_map_t *map) { // MP_MAP_LOOKUP_REMOVE_IF_FOUND behaviour: // - returns NULL if not found, else the slot if was found in with key null and value non-null mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) { - - if (map->is_fixed && lookup_kind != MP_MAP_LOOKUP) { - // can't add/remove from a fixed array - return NULL; - } + // If the map is a fixed array then we must only be called for a lookup + assert(!map->is_fixed || lookup_kind == MP_MAP_LOOKUP); // Work out if we can compare just pointers bool compare_only_ptrs = map->all_keys_are_qstrs; -- cgit v1.2.3 From 6c9fca2aa911e31f6c1b48d3b950b4dc058473d4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Aug 2017 16:46:13 +1000 Subject: py/map: Remove unused new/free functions. Maps are always allocated "statically" and (de)initialised via mp_map_init and mp_map_deinit. --- py/map.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'py') diff --git a/py/map.c b/py/map.c index 6d6337229..f07b8fbd2 100644 --- a/py/map.c +++ b/py/map.c @@ -93,12 +93,6 @@ void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table) { map->table = (mp_map_elem_t*)table; } -mp_map_t *mp_map_new(size_t n) { - mp_map_t *map = m_new(mp_map_t, 1); - mp_map_init(map, n); - return map; -} - // Differentiate from mp_map_clear() - semantics is different void mp_map_deinit(mp_map_t *map) { if (!map->is_fixed) { @@ -107,11 +101,6 @@ void mp_map_deinit(mp_map_t *map) { map->used = map->alloc = 0; } -void mp_map_free(mp_map_t *map) { - mp_map_deinit(map); - m_del_obj(mp_map_t, map); -} - void mp_map_clear(mp_map_t *map) { if (!map->is_fixed) { m_del(mp_map_elem_t, map->table, map->alloc); -- cgit v1.2.3 From ca21aed0a11903db04fc96056f8a08e452aaf504 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Aug 2017 17:00:14 +1000 Subject: py: Make m_malloc_fail() have void return type, since it doesn't return. --- py/malloc.c | 8 ++++---- py/misc.h | 2 +- py/runtime.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'py') diff --git a/py/malloc.c b/py/malloc.c index af4ccf2e8..ea1d4c4b9 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -74,7 +74,7 @@ STATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { void *m_malloc(size_t num_bytes) { void *ptr = malloc(num_bytes); if (ptr == NULL && num_bytes != 0) { - return m_malloc_fail(num_bytes); + m_malloc_fail(num_bytes); } #if MICROPY_MEM_STATS MP_STATE_MEM(total_bytes_allocated) += num_bytes; @@ -100,7 +100,7 @@ void *m_malloc_maybe(size_t num_bytes) { void *m_malloc_with_finaliser(size_t num_bytes) { void *ptr = malloc_with_finaliser(num_bytes); if (ptr == NULL && num_bytes != 0) { - return m_malloc_fail(num_bytes); + m_malloc_fail(num_bytes); } #if MICROPY_MEM_STATS MP_STATE_MEM(total_bytes_allocated) += num_bytes; @@ -115,7 +115,7 @@ void *m_malloc_with_finaliser(size_t num_bytes) { void *m_malloc0(size_t num_bytes) { void *ptr = m_malloc(num_bytes); if (ptr == NULL && num_bytes != 0) { - return m_malloc_fail(num_bytes); + m_malloc_fail(num_bytes); } // If this config is set then the GC clears all memory, so we don't need to. #if !MICROPY_GC_CONSERVATIVE_CLEAR @@ -131,7 +131,7 @@ void *m_realloc(void *ptr, size_t new_num_bytes) { #endif void *new_ptr = realloc(ptr, new_num_bytes); if (new_ptr == NULL && new_num_bytes != 0) { - return m_malloc_fail(new_num_bytes); + m_malloc_fail(new_num_bytes); } #if MICROPY_MEM_STATS // At first thought, "Total bytes allocated" should only grow, diff --git a/py/misc.h b/py/misc.h index 71425b85e..b9f2dae90 100644 --- a/py/misc.h +++ b/py/misc.h @@ -92,7 +92,7 @@ void *m_realloc(void *ptr, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move); void m_free(void *ptr); #endif -NORETURN void *m_malloc_fail(size_t num_bytes); +NORETURN void m_malloc_fail(size_t num_bytes); #if MICROPY_MEM_STATS size_t m_get_total_bytes_allocated(void); diff --git a/py/runtime.c b/py/runtime.c index 1db6c93c3..21ef42577 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1408,7 +1408,7 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i #endif // MICROPY_ENABLE_COMPILER -NORETURN void *m_malloc_fail(size_t num_bytes) { +NORETURN void m_malloc_fail(size_t num_bytes) { DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes); #if MICROPY_ENABLE_GC if (gc_is_locked()) { -- cgit v1.2.3 From 793d826d9df67c3f544505beda63ca36d8dfa1c4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Sep 2017 10:10:51 +1000 Subject: py/modstruct: In struct.pack, stop converting if there are no args left. This patch makes a repeat counter behave the same as repeating the typecode, when there are not enough args. For example: struct.pack('2I', 1) now behave the same as struct.pack('II', 1). --- py/modstruct.c | 3 ++- tests/basics/struct_micropython.py | 3 +++ tests/basics/struct_micropython.py.exp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'py') diff --git a/py/modstruct.c b/py/modstruct.c index 1daa33338..0d4a45f6b 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -206,7 +206,8 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, siz memset(p + to_copy, 0, sz - to_copy); p += sz; } else { - while (sz--) { + // If we run out of args then we just finish; CPython would raise struct.error + while (sz-- && i < n_args) { mp_binary_set_val(fmt_type, *fmt, args[i++], &p); } } diff --git a/tests/basics/struct_micropython.py b/tests/basics/struct_micropython.py index 4b9dfe137..f203a4666 100644 --- a/tests/basics/struct_micropython.py +++ b/tests/basics/struct_micropython.py @@ -18,6 +18,9 @@ s = struct.pack(" Date: Fri, 1 Sep 2017 10:53:29 +1000 Subject: py/modstruct: Check and prevent buffer-read overflow in struct unpacking Prior to this patch, the size of the buffer given to unpack/unpack_from was checked for being too small by using the count of the arguments, not their actual size. For example, a format spec of '4I' would only check that there was 4 bytes available, not 16; and 'I' would check for 1 byte, not 4. This bug is fixed in this patch by calculating the total size of the format spec at the start of the unpacking function. This function anyway needs to calculate the number of items at the start, so calculating the total size can be done at the same time. --- py/modstruct.c | 55 +++++++++++++++++++++++-------------------------- tests/basics/struct1.py | 6 ++++++ tests/basics/struct2.py | 6 ++++++ 3 files changed, 38 insertions(+), 29 deletions(-) (limited to 'py') diff --git a/py/modstruct.c b/py/modstruct.c index 0d4a45f6b..61dd0f81b 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -82,26 +82,10 @@ STATIC mp_uint_t get_fmt_num(const char **p) { return val; } -STATIC uint calcsize_items(const char *fmt) { - uint cnt = 0; - while (*fmt) { - int num = 1; - if (unichar_isdigit(*fmt)) { - num = get_fmt_num(&fmt); - if (*fmt == 's') { - num = 1; - } - } - cnt += num; - fmt++; - } - return cnt; -} - -STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { - const char *fmt = mp_obj_str_get_str(fmt_in); +STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) { char fmt_type = get_fmt_type(&fmt); - mp_uint_t size; + size_t total_cnt = 0; + size_t size; for (size = 0; *fmt; fmt++) { mp_uint_t cnt = 1; if (unichar_isdigit(*fmt)) { @@ -109,8 +93,10 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { } if (*fmt == 's') { + total_cnt += 1; size += cnt; } else { + total_cnt += cnt; mp_uint_t align; size_t sz = mp_binary_get_size(fmt_type, *fmt, &align); while (cnt--) { @@ -120,6 +106,14 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { } } } + *total_sz = size; + return total_cnt; +} + +STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { + const char *fmt = mp_obj_str_get_str(fmt_in); + size_t size; + calc_size_items(fmt, &size); return MP_OBJ_NEW_SMALL_INT(size); } MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize); @@ -130,8 +124,9 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { // Since we implement unpack and unpack_from using the same function // we relax the "exact" requirement, and only implement "big enough". const char *fmt = mp_obj_str_get_str(args[0]); + size_t total_sz; + size_t num_items = calc_size_items(fmt, &total_sz); char fmt_type = get_fmt_type(&fmt); - uint num_items = calcsize_items(fmt); mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_items, NULL)); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); @@ -152,21 +147,23 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { p += offset; } - for (uint i = 0; i < num_items;) { - mp_uint_t sz = 1; + // Check that the input buffer is big enough to unpack all the values + if (p + total_sz > end_p) { + mp_raise_ValueError("buffer too small"); + } + + for (size_t i = 0; i < num_items;) { + mp_uint_t cnt = 1; if (unichar_isdigit(*fmt)) { - sz = get_fmt_num(&fmt); - } - if (p + sz > end_p) { - mp_raise_ValueError("buffer too small"); + cnt = get_fmt_num(&fmt); } mp_obj_t item; if (*fmt == 's') { - item = mp_obj_new_bytes(p, sz); - p += sz; + item = mp_obj_new_bytes(p, cnt); + p += cnt; res->items[i++] = item; } else { - while (sz--) { + while (cnt--) { item = mp_binary_get_val(fmt_type, *fmt, &p); res->items[i++] = item; } diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index a442beb1e..2cf75137b 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -39,6 +39,12 @@ print(v == (10, 100, 200, 300)) # network byte order print(struct.pack('!i', 123)) +# check that we get an error if the buffer is too small +try: + struct.unpack('I', b'\x00\x00\x00') +except: + print('struct.error') + # first arg must be a string try: struct.pack(1, 2) diff --git a/tests/basics/struct2.py b/tests/basics/struct2.py index 3b9dd5c1f..e3336c0c7 100644 --- a/tests/basics/struct2.py +++ b/tests/basics/struct2.py @@ -25,6 +25,12 @@ print(struct.calcsize('0s1s0H2H')) print(struct.unpack('<0s1s0H2H', b'01234')) print(struct.pack('<0s1s0H2H', b'abc', b'abc', 258, 515)) +# check that we get an error if the buffer is too small +try: + struct.unpack('2H', b'\x00\x00') +except: + print('Exception') + # check that unknown types raise an exception try: struct.unpack('z', b'1') -- cgit v1.2.3 From 2daacc5ceef7e36ac3c88b8946088b6b3513993b Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Sep 2017 11:11:09 +1000 Subject: py/modstruct: Check and prevent buffer-write overflow in struct packing. Prior to this patch, the size of the buffer given to pack_into() was checked for being too small by using the count of the arguments, not their actual size. For example, a format spec of '4I' would only check that there was 4 bytes available, not 16; and 'I' would check for 1 byte, not 4. The pack() function is ok because its buffer is created to be exactly the correct size. The fix in this patch calculates the total size of the format spec at the start of pack_into() and verifies that the buffer is large enough. This adds some computational overhead, to iterate through the whole format spec. The alternative is to check during the packing, but that requires extra code to handle alignment, and the check is anyway not needed for pack(). So to maintain minimal code size the check is done using struct_calcsize. --- py/modstruct.c | 29 ++++++++++++++++------------- tests/basics/struct1.py | 6 ++++++ tests/basics/struct2.py | 4 ++++ 3 files changed, 26 insertions(+), 13 deletions(-) (limited to 'py') diff --git a/py/modstruct.c b/py/modstruct.c index 61dd0f81b..8617a8e0d 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -174,37 +174,35 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_from_obj, 2, 3, struct_unpack_from); -STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, size_t n_args, const mp_obj_t *args) { +// This function assumes there is enough room in p to store all the values +STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, const mp_obj_t *args) { const char *fmt = mp_obj_str_get_str(fmt_in); char fmt_type = get_fmt_type(&fmt); size_t i; for (i = 0; i < n_args;) { - mp_uint_t sz = 1; + mp_uint_t cnt = 1; if (*fmt == '\0') { // more arguments given than used by format string; CPython raises struct.error here break; } if (unichar_isdigit(*fmt)) { - sz = get_fmt_num(&fmt); - } - if (p + sz > end_p) { - mp_raise_ValueError("buffer too small"); + cnt = get_fmt_num(&fmt); } if (*fmt == 's') { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ); - mp_uint_t to_copy = sz; + mp_uint_t to_copy = cnt; if (bufinfo.len < to_copy) { to_copy = bufinfo.len; } memcpy(p, bufinfo.buf, to_copy); - memset(p + to_copy, 0, sz - to_copy); - p += sz; + memset(p + to_copy, 0, cnt - to_copy); + p += cnt; } else { // If we run out of args then we just finish; CPython would raise struct.error - while (sz-- && i < n_args) { + while (cnt-- && i < n_args) { mp_binary_set_val(fmt_type, *fmt, args[i++], &p); } } @@ -219,8 +217,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { vstr_init_len(&vstr, size); byte *p = (byte*)vstr.buf; memset(p, 0, size); - byte *end_p = &p[size]; - struct_pack_into_internal(args[0], p, end_p, n_args - 1, &args[1]); + struct_pack_into_internal(args[0], p, n_args - 1, &args[1]); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); @@ -240,7 +237,13 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { byte *end_p = &p[bufinfo.len]; p += offset; - struct_pack_into_internal(args[0], p, end_p, n_args - 3, &args[3]); + // Check that the output buffer is big enough to hold all the values + mp_int_t sz = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0])); + if (p + sz > end_p) { + mp_raise_ValueError("buffer too small"); + } + + struct_pack_into_internal(args[0], p, n_args - 3, &args[3]); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX, struct_pack_into); diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index 2cf75137b..db34342a1 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -69,6 +69,12 @@ print(buf) struct.pack_into(' Date: Fri, 1 Sep 2017 15:22:25 +1000 Subject: py/qstrdefs: Remove unused qstrs. They are not used by any component and take up valuable flash space. --- py/qstrdefs.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'py') diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 9375b9101..4ded5be08 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -51,11 +51,3 @@ Q() Q() Q() Q(utf-8) - -// The following qstrings not referenced from anywhere in the sources -Q(__locals__) -Q(BufferError) -Q(FileExistsError) -Q(FileNotFoundError) -Q(FloatingPointError) -Q(UnboundLocalError) -- cgit v1.2.3 From dd376a239dc4f47b0ee7866810fcda151f3cf6dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Sep 2017 15:25:29 +1000 Subject: py/nlrthumb: Get working again on standard Thumb arch (ie not Thumb2). "b" on Thumb might not be long enough for the jump to nlr_push_tail so it must be done indirectly. --- py/nlrthumb.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'py') diff --git a/py/nlrthumb.c b/py/nlrthumb.c index 08a71ac7d..8ff1bb2d2 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -67,7 +67,14 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { "str lr, [r0, #8] \n" // store lr into nlr_buf #endif +#if defined(__ARM_ARCH_6M__) + "ldr r1, nlr_push_tail_var \n" + "bx r1 \n" // do the rest in C + ".align 2 \n" + "nlr_push_tail_var: .word nlr_push_tail \n" +#else "b nlr_push_tail \n" // do the rest in C +#endif ); return 0; // needed to silence compiler warning -- cgit v1.2.3 From 9950865c39044e9fef295d0676af7c5fd55289ea Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 2 Sep 2017 21:19:01 +0300 Subject: py/objfloat: Fix binary ops with incompatible objects. These are now returned as "operation not supported" instead of raising TypeError. In particular, this fixes equality for float vs incompatible types, which now properly results in False instead of exception. This also paves the road to support reverse operation (e.g. __radd__) with float objects. This is achieved by introducing mp_obj_get_float_maybe(), similar to existing mp_obj_get_int_maybe(). --- py/obj.c | 27 +++++++++++++++++++++------ py/obj.h | 1 + py/objfloat.c | 6 +++++- tests/float/float_compare.py | 22 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 tests/float/float_compare.py (limited to 'py') diff --git a/py/obj.c b/py/obj.c index 0dab5f2ac..90ce47e8f 100644 --- a/py/obj.c +++ b/py/obj.c @@ -264,20 +264,33 @@ bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) { } #if MICROPY_PY_BUILTINS_FLOAT -mp_float_t mp_obj_get_float(mp_obj_t arg) { +bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) { + mp_float_t val; + if (arg == mp_const_false) { - return 0; + val = 0; } else if (arg == mp_const_true) { - return 1; + val = 1; } else if (MP_OBJ_IS_SMALL_INT(arg)) { - return MP_OBJ_SMALL_INT_VALUE(arg); + val = MP_OBJ_SMALL_INT_VALUE(arg); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) { - return mp_obj_int_as_float_impl(arg); + val = mp_obj_int_as_float_impl(arg); #endif } else if (mp_obj_is_float(arg)) { - return mp_obj_float_get(arg); + val = mp_obj_float_get(arg); } else { + return false; + } + + *value = val; + return true; +} + +mp_float_t mp_obj_get_float(mp_obj_t arg) { + mp_float_t val; + + if (!mp_obj_get_float_maybe(arg, &val)) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("can't convert to float"); } else { @@ -285,6 +298,8 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { "can't convert %s to float", mp_obj_get_type_str(arg))); } } + + return val; } #if MICROPY_PY_BUILTINS_COMPLEX diff --git a/py/obj.h b/py/obj.h index 323423b3e..70cdd15fa 100644 --- a/py/obj.h +++ b/py/obj.h @@ -686,6 +686,7 @@ mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value); #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_get_float(mp_obj_t self_in); +bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); #endif //qstr mp_obj_get_qstr(mp_obj_t arg); diff --git a/py/objfloat.c b/py/objfloat.c index b1900b236..fadbbcb79 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -240,7 +240,11 @@ STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) { } mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs_in) { - mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible) + mp_float_t rhs_val; + if (!mp_obj_get_float_maybe(rhs_in, &rhs_val)) { + return MP_OBJ_NULL; // op not supported + } + switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; diff --git a/tests/float/float_compare.py b/tests/float/float_compare.py new file mode 100644 index 000000000..105923ac7 --- /dev/null +++ b/tests/float/float_compare.py @@ -0,0 +1,22 @@ +# Extended float comparisons + +class Foo: + pass + +foo = Foo() + +print(foo == 1.0) +print(1.0 == foo) +print(1.0 == Foo) +print(1.0 == []) +print(1.0 == {}) + +try: + print(foo < 1.0) +except TypeError: + print("TypeError") + +try: + print(1.0 < foo) +except TypeError: + print("TypeError") -- cgit v1.2.3 From d4b75f6b6822885e331c69a74e56e23af40a6264 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 4 Sep 2017 14:16:27 +1000 Subject: py/obj: Fix comparison of float/complex NaN with itself. IEEE floating point is specified such that a comparison of NaN with itself returns false, and Python respects these semantics. This patch makes uPy also have these semantics. The fix has a minor impact on the speed of the object-equality fast-path, but that seems to be unavoidable and it's much more important to have correct behaviour (especially in this case where the wrong answer for nan==nan is silently returned). --- py/obj.c | 11 ++++++++++- tests/float/complex1.py | 5 +++++ tests/float/float1.py | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'py') diff --git a/py/obj.c b/py/obj.c index 90ce47e8f..857fe373f 100644 --- a/py/obj.c +++ b/py/obj.c @@ -162,7 +162,16 @@ bool mp_obj_is_callable(mp_obj_t o_in) { // comparison returns NotImplemented, == and != are decided by comparing the object // pointer." bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { - if (o1 == o2) { + // Float (and complex) NaN is never equal to anything, not even itself, + // so we must have a special check here to cover those cases. + if (o1 == o2 + #if MICROPY_PY_BUILTINS_FLOAT + && !mp_obj_is_float(o1) + #endif + #if MICROPY_PY_BUILTINS_COMPLEX + && !MP_OBJ_IS_TYPE(o1, &mp_type_complex) + #endif + ) { return true; } if (o1 == mp_const_none || o2 == mp_const_none) { diff --git a/tests/float/complex1.py b/tests/float/complex1.py index a6038de04..7f0b317b3 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -37,6 +37,11 @@ ans = 1j ** 2.5j; print("%.5g %.5g" % (ans.real, ans.imag)) print(1j == 1) print(1j == 1j) +# comparison of nan is special +nan = float('nan') * 1j +print(nan == 1j) +print(nan == nan) + # builtin abs print(abs(1j)) print("%.5g" % abs(1j + 2)) diff --git a/tests/float/float1.py b/tests/float/float1.py index 93f6f014c..137dacc23 100644 --- a/tests/float/float1.py +++ b/tests/float/float1.py @@ -60,6 +60,11 @@ print(1.2 <= -3.4) print(1.2 >= 3.4) print(1.2 >= -3.4) +# comparison of nan is special +nan = float('nan') +print(nan == 1.2) +print(nan == nan) + try: 1.0 / 0 except ZeroDivisionError: -- cgit v1.2.3 From 77a48e8cd493c0b0e0ca2d2ad58a110a23c6a232 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 4 Sep 2017 23:35:46 +1000 Subject: py/obj: Remove declaration for mp_obj_new_none(), it's never defined. --- py/obj.h | 1 - 1 file changed, 1 deletion(-) (limited to 'py') diff --git a/py/obj.h b/py/obj.h index 70cdd15fa..77f0f2298 100644 --- a/py/obj.h +++ b/py/obj.h @@ -630,7 +630,6 @@ extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; // General API for objects mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); -mp_obj_t mp_obj_new_none(void); static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; } mp_obj_t mp_obj_new_cell(mp_obj_t obj); mp_obj_t mp_obj_new_int(mp_int_t value); -- cgit v1.2.3 From 60749e57f24741c685d2ae125cfff27d021eb90d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 2 Sep 2017 02:39:27 +0300 Subject: py/objtype: Implement fallback for instance inplace special methods. If __iop__ is not defined, call __op__ instead. This is desired behavior for immutable types, __iop__ needs to be defined only for mutable types. --- py/objtype.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'py') diff --git a/py/objtype.c b/py/objtype.c index 68c1da7b8..83a9836c3 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -460,6 +460,7 @@ STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t // Note: For ducktyping, CPython does not look in the instance members or use // __getattr__ or __getattribute__. It only looks in the class dictionary. mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in); +retry:; qstr op_name = mp_binary_op_method_name[op]; /* Still try to lookup native slot if (op_name == 0) { @@ -483,6 +484,14 @@ STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t dest[2] = rhs_in; res = mp_call_method_n_kw(1, 0, dest); } else { + // If this was an inplace method, fallback to normal method + // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ : + // "If a specific method is not defined, the augmented assignment + // falls back to the normal methods." + if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) { + op -= MP_BINARY_OP_INPLACE_OR - MP_BINARY_OP_OR; + goto retry; + } return MP_OBJ_NULL; // op not supported } -- cgit v1.2.3 From 1aaba5cabe48fa5168279a51f62124bbfedd5d59 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 6 Sep 2017 00:23:41 +0300 Subject: py/objtuple: Properly implement comparison with incompatible types. Should raise TypeError, unless it's (in)equality comparison. --- py/objtuple.c | 11 +++++++---- tests/basics/tuple_compare.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'py') diff --git a/py/objtuple.c b/py/objtuple.c index 079b5cbdb..b8916a1a7 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -101,7 +101,7 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg } // Don't pass MP_BINARY_OP_NOT_EQUAL here -STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { +STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { // type check is done on getiter method to allow tuple, namedtuple, attrtuple mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter); mp_obj_type_t *another_type = mp_obj_get_type(another_in); @@ -110,12 +110,15 @@ STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in // Slow path for user subclasses another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple)); if (another_in == MP_OBJ_NULL) { - return false; + if (op == MP_BINARY_OP_EQUAL) { + return mp_const_false; + } + return MP_OBJ_NULL; } } mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in); - return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); + return mp_obj_new_bool(mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len)); } mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in) { @@ -166,7 +169,7 @@ mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: - return mp_obj_new_bool(tuple_cmp_helper(op, lhs, rhs)); + return tuple_cmp_helper(op, lhs, rhs); default: return MP_OBJ_NULL; // op not supported diff --git a/tests/basics/tuple_compare.py b/tests/basics/tuple_compare.py index ad813f702..9558eb1db 100644 --- a/tests/basics/tuple_compare.py +++ b/tests/basics/tuple_compare.py @@ -53,3 +53,13 @@ print((10, 0) > (1, 1)) print((10, 0) < (1, 1)) print((0, 0, 10, 0) > (0, 0, 1, 1)) print((0, 0, 10, 0) < (0, 0, 1, 1)) + + +print(() == {}) +print(() != {}) +print((1,) == [1]) + +try: + print(() < {}) +except TypeError: + print("TypeError") -- cgit v1.2.3 From 4a93801c12898898744131f57d79cf216d0861b3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 6 Sep 2017 14:09:13 +1000 Subject: all: Update Makefiles and others to build with new ports/ dir layout. Also renames "stmhal" to "stm32" in documentation and everywhere else. --- .gitattributes | 11 -- .travis.yml | 46 ++++---- README.md | 34 +++--- docs/reference/constrained.rst | 2 +- examples/pins.py | 2 +- extmod/modframebuf.c | 2 +- mpy-cross/Makefile | 2 +- mpy-cross/main.c | 2 +- ports/bare-arm/Makefile | 2 +- ports/cc3200/Makefile | 2 +- ports/cc3200/application.mk | 4 +- ports/cc3200/bootmgr/bootloader.mk | 2 +- ports/esp8266/Makefile | 2 +- ports/esp8266/esp_mphal.h | 2 +- ports/esp8266/modules/ds18x20.py | 2 +- ports/esp8266/modules/onewire.py | 2 +- ports/esp8266/modules/upip.py | 2 +- ports/esp8266/modules/upip_utarfile.py | 2 +- ports/minimal/Makefile | 2 +- ports/pic16bit/Makefile | 2 +- ports/qemu-arm/Makefile | 2 +- ports/stm32/Makefile | 4 +- ports/stm32/README.md | 6 +- .../boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h | 2 +- .../boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h | 2 +- .../boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h | 2 +- ports/stm32/help.c | 2 +- ports/stm32/modules/lcd160cr.py | 2 +- ports/stm32/modules/lcd160cr_test.py | 2 +- ports/stm32/modules/onewire.py | 2 +- ports/stm32/mpconfigport.h | 4 +- ports/stm32/mphalport.h | 4 +- ports/stm32/pin_defs_stm32.c | 31 +++++ ports/stm32/pin_defs_stm32.h | 131 +++++++++++++++++++++ ports/stm32/pin_defs_stmhal.c | 31 ----- ports/stm32/pin_defs_stmhal.h | 131 --------------------- ports/teensy/Makefile | 8 +- ports/teensy/lcd.c | 2 +- ports/unix/Makefile | 6 +- ports/unix/modules/upip.py | 2 +- ports/unix/modules/upip_utarfile.py | 2 +- ports/windows/.appveyor.yml | 2 +- ports/windows/Makefile | 16 +-- ports/windows/README.md | 4 +- ports/windows/msvc/genhdr.targets | 2 +- ports/windows/msvc/paths.props | 26 ++-- ports/windows/msvc/sources.props | 22 ++-- ports/windows/windows_mphal.h | 2 +- ports/zephyr/Makefile | 2 +- py/mkrules.mk | 2 +- tests/run-tests | 4 +- tools/check_code_size.sh | 2 +- tools/codestats.sh | 44 +++---- 53 files changed, 311 insertions(+), 322 deletions(-) create mode 100644 ports/stm32/pin_defs_stm32.c create mode 100644 ports/stm32/pin_defs_stm32.h delete mode 100644 ports/stm32/pin_defs_stmhal.c delete mode 100644 ports/stm32/pin_defs_stmhal.h (limited to 'py') diff --git a/.gitattributes b/.gitattributes index 6822bd21c..1ac507944 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,17 +15,6 @@ # These should also not be modified by git. tests/basics/string_cr_conversion.py -text tests/basics/string_crlf_conversion.py -text -stmhal/pybcdc.inf_template -text -stmhal/usbd_* -text -stmhal/boards/*/stm32f4xx_hal_conf.h -text -stmhal/usbdev/** -text -stmhal/usbhost/** -text -cc3200/hal/aes.c -text -cc3200/hal/aes.h -text -cc3200/hal/des.c -text -cc3200/hal/i2s.c -text -cc3200/hal/i2s.h -text -cc3200/version.h -text ports/stm32/pybcdc.inf_template -text ports/stm32/usbd_* -text ports/stm32/boards/*/stm32f4xx_hal_conf.h -text diff --git a/.travis.yml b/.travis.yml index 14d5df0a4..db51567f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,40 +28,40 @@ before_script: script: - make -C mpy-cross - - make -C minimal CROSS=1 build/firmware.bin - - ls -l minimal/build/firmware.bin + - make -C ports/minimal CROSS=1 build/firmware.bin + - ls -l ports/minimal/build/firmware.bin - tools/check_code_size.sh - mkdir -p ${HOME}/persist # Save new firmware for reference, but only if building a main branch, not a pull request - - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp minimal/build/firmware.bin ${HOME}/persist/; fi' - - make -C unix deplibs - - make -C unix - - make -C unix nanbox - - make -C bare-arm - - make -C qemu-arm test - - make -C stmhal - - make -C stmhal BOARD=PYBV11 MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 - - make -C stmhal BOARD=STM32F769DISC - - make -C stmhal BOARD=STM32L476DISC - - make -C teensy - - make -C cc3200 BTARGET=application BTYPE=release - - make -C cc3200 BTARGET=bootloader BTYPE=release - - make -C windows CROSS_COMPILE=i686-w64-mingw32- + - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp ports/minimal/build/firmware.bin ${HOME}/persist/; fi' + - make -C ports/unix deplibs + - make -C ports/unix + - make -C ports/unix nanbox + - make -C ports/bare-arm + - make -C ports/qemu-arm test + - make -C ports/stm32 + - make -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 + - make -C ports/stm32 BOARD=STM32F769DISC + - make -C ports/stm32 BOARD=STM32L476DISC + - make -C ports/teensy + - make -C ports/cc3200 BTARGET=application BTYPE=release + - make -C ports/cc3200 BTARGET=bootloader BTYPE=release + - make -C ports/windows CROSS_COMPILE=i686-w64-mingw32- # run tests without coverage info #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests) #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests --emit native) # run tests with coverage info - - make -C unix coverage - - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests) - - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests -d thread) - - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --emit native) - - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --via-mpy -d basics float) + - make -C ports/unix coverage + - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) + - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) + - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native) + - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy -d basics float) # run coveralls coverage analysis (try to, even if some builds/tests failed) - - (cd unix && coveralls --root .. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) + - (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) after_failure: - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) - - (grep "FAIL" qemu-arm/build/console.out) + - (grep "FAIL" ports/qemu-arm/build/console.out) diff --git a/README.md b/README.md index 481cac4e4..ff609dba3 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,10 @@ Major components in this repository: core library. - mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts into precompiled bytecode. -- unix/ -- a version of MicroPython that runs on Unix. -- stmhal/ -- a version of MicroPython that runs on the PyBoard and similar +- ports/unix/ -- a version of MicroPython that runs on Unix. +- ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar STM32 boards (using ST's Cube HAL drivers). -- minimal/ -- a minimal MicroPython port. Start with this if you want +- ports/minimal/ -- a minimal MicroPython port. Start with this if you want to port MicroPython to another microcontroller. - tests/ -- test framework and test scripts. - docs/ -- user documentation in Sphinx reStructuredText format. Rendered @@ -45,13 +45,13 @@ Major components in this repository: to select needed board/port at the bottom left corner). Additional components: -- bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used +- ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used mostly to control code size. -- teensy/ -- a version of MicroPython that runs on the Teensy 3.1 +- ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1 (preliminary but functional). -- pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers. -- cc3200/ -- a version of MicroPython that runs on the CC3200 from TI. -- esp8266/ -- an experimental port for ESP8266 WiFi modules. +- ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers. +- ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI. +- ports/esp8266/ -- an experimental port for ESP8266 WiFi modules. - extmod/ -- additional (non-core) modules implemented in C. - tools/ -- various tools, including the pyboard.py module. - examples/ -- a few example Python scripts. @@ -72,7 +72,7 @@ Alternatively, fallback implementation based on setjmp/longjmp can be used. To build (see section below for required dependencies): - $ cd unix + $ cd ports/unix $ make axtls $ make @@ -115,7 +115,7 @@ these additional dependencies, first fetch git submodules for them: $ git submodule update --init Use this same command to get the latest versions of dependencies, as -they are updated from time to time. After that, in `unix/` dir, execute: +they are updated from time to time. After that, in `ports/unix/` dir, execute: $ make deplibs @@ -123,25 +123,25 @@ This will build all available dependencies (regardless whether they are used or not). If you intend to build MicroPython with additional options (like cross-compiling), the same set of options should be passed to `make deplibs`. To actually enabled use of dependencies, edit -`unix/mpconfigport.mk` file, which has inline descriptions of the options. +`ports/unix/mpconfigport.mk` file, which has inline descriptions of the options. For example, to build SSL module (required for `upip` tool described above), set `MICROPY_PY_USSL` to 1. -In `unix/mpconfigport.mk`, you can also disable some dependencies enabled +In `ports/unix/mpconfigport.mk`, you can also disable some dependencies enabled by default, like FFI support, which requires libffi development files to be installed. -The STM version ---------------- +The STM32 version +----------------- -The "stmhal" port requires an ARM compiler, arm-none-eabi-gcc, and associated +The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils and arm-none-eabi-gcc packages. Otherwise, try here: https://launchpad.net/gcc-arm-embedded To build: - $ cd stmhal + $ cd ports/stm32 $ make You then need to get your board into DFU mode. On the pyboard, connect the @@ -155,4 +155,4 @@ Then to flash the code via USB DFU to your device: This will use the included `tools/pydfu.py` script. If flashing the firmware does not work it may be because you don't have the correct permissions, and need to use `sudo make deploy`. -See the README.md file in the stmhal/ directory for further details. +See the README.md file in the ports/stm32/ directory for further details. diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst index 14286aa26..e7de459bc 100644 --- a/docs/reference/constrained.rst +++ b/docs/reference/constrained.rst @@ -279,7 +279,7 @@ After importing the modules, execute: Then copy and paste all the Q(xxx) lines into a text editor. Check for and remove lines which are obviously invalid. Open the file qstrdefsport.h which -will be found in stmhal (or the equivalent directory for the architecture in +will be found in ports/stm32 (or the equivalent directory for the architecture in use). Copy and paste the corrected lines at the end of the file. Save the file, rebuild and flash the firmware. The outcome can be checked by importing the modules and again issuing: diff --git a/examples/pins.py b/examples/pins.py index ab359f692..aafdb4813 100644 --- a/examples/pins.py +++ b/examples/pins.py @@ -1,5 +1,5 @@ # Print a nice list of pins, their current settings, and available afs. -# Requires pins_af.py from stmhal/build-PYBV10/ directory. +# Requires pins_af.py from ports/stm32/build-PYBV10/ directory. import pyb import pins_af diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index f4e857129..239302295 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -33,7 +33,7 @@ #if MICROPY_PY_FRAMEBUF -#include "stmhal/font_petme128_8x8.h" +#include "ports/stm32/font_petme128_8x8.h" typedef struct _mp_obj_framebuf_t { mp_obj_base_t base; diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index 5399b5ae7..53ce50c7f 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -65,7 +65,7 @@ SRC_C = \ # Add fmode when compiling with mingw gcc COMPILER_TARGET := $(shell $(CC) -dumpmachine) ifneq (,$(findstring mingw,$(COMPILER_TARGET))) - SRC_C += windows/fmode.c + SRC_C += ports/windows/fmode.c endif OBJ = $(PY_O) diff --git a/mpy-cross/main.c b/mpy-cross/main.c index ca8d9633f..225bc4309 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -36,7 +36,7 @@ #include "py/gc.h" #include "py/stackctrl.h" #ifdef _WIN32 -#include "windows/fmode.h" +#include "ports/windows/fmode.h" #endif // Command line options, with their defaults diff --git a/ports/bare-arm/Makefile b/ports/bare-arm/Makefile index 90c13de11..0fcd5d027 100644 --- a/ports/bare-arm/Makefile +++ b/ports/bare-arm/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile index 4c8b0b832..81531b108 100644 --- a/ports/cc3200/Makefile +++ b/ports/cc3200/Makefile @@ -14,7 +14,7 @@ PORT ?= /dev/ttyUSB1 # If the build directory is not given, make it reflect the board name. BUILD ?= build/$(BOARD)/$(BTYPE) -include ../py/mkenv.mk +include ../../py/mkenv.mk -include ../../localconfig.mk CROSS_COMPILE ?= arm-none-eabi- diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk index 64891a2e7..19abe6616 100644 --- a/ports/cc3200/application.mk +++ b/ports/cc3200/application.mk @@ -18,7 +18,7 @@ APP_INC += -Iutil APP_INC += -Ibootmgr APP_INC += -I$(BUILD) APP_INC += -I$(BUILD)/genhdr -APP_INC += -I$(TOP)/stmhal +APP_INC += -I$(TOP)/ports/stm32 APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS @@ -151,7 +151,7 @@ APP_LIB_SRC_C = $(addprefix lib/,\ utils/sys_stdio_mphal.c \ ) -APP_STM_SRC_C = $(addprefix stmhal/,\ +APP_STM_SRC_C = $(addprefix ports/stm32/,\ bufhelper.c \ irq.c \ ) diff --git a/ports/cc3200/bootmgr/bootloader.mk b/ports/cc3200/bootmgr/bootloader.mk index b8aa9082c..44f1b7f42 100644 --- a/ports/cc3200/bootmgr/bootloader.mk +++ b/ports/cc3200/bootmgr/bootloader.mk @@ -98,7 +98,7 @@ $(BUILD)/misc/%.o: CFLAGS += -Os $(BUILD)/simplelink/%.o: CFLAGS += -Os $(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os $(BUILD)/py/%.o: CFLAGS += -Os -$(BUILD)/stmhal/%.o: CFLAGS += -Os +$(BUILD)/ports/stm32/%.o: CFLAGS += -Os else $(error Invalid BTYPE specified) endif diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index fce11a7d4..70b4ce35c 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h diff --git a/ports/esp8266/esp_mphal.h b/ports/esp8266/esp_mphal.h index 913bd70dc..194e56f64 100644 --- a/ports/esp8266/esp_mphal.h +++ b/ports/esp8266/esp_mphal.h @@ -72,7 +72,7 @@ void ets_event_poll(void); // C-level pin HAL #include "etshal.h" #include "gpio.h" -#include "esp8266/modmachine.h" +#include "modmachine.h" #define MP_HAL_PIN_FMT "%u" #define mp_hal_pin_obj_t uint32_t #define mp_hal_get_pin_obj(o) mp_obj_get_pin(o) diff --git a/ports/esp8266/modules/ds18x20.py b/ports/esp8266/modules/ds18x20.py index faae59d90..1ec92d1c9 120000 --- a/ports/esp8266/modules/ds18x20.py +++ b/ports/esp8266/modules/ds18x20.py @@ -1 +1 @@ -../../drivers/onewire/ds18x20.py \ No newline at end of file +../../../drivers/onewire/ds18x20.py \ No newline at end of file diff --git a/ports/esp8266/modules/onewire.py b/ports/esp8266/modules/onewire.py index f6ec745e8..33f30e84f 120000 --- a/ports/esp8266/modules/onewire.py +++ b/ports/esp8266/modules/onewire.py @@ -1 +1 @@ -../../drivers/onewire/onewire.py \ No newline at end of file +../../../drivers/onewire/onewire.py \ No newline at end of file diff --git a/ports/esp8266/modules/upip.py b/ports/esp8266/modules/upip.py index 20d52a4ab..130eb6901 120000 --- a/ports/esp8266/modules/upip.py +++ b/ports/esp8266/modules/upip.py @@ -1 +1 @@ -../../tools/upip.py \ No newline at end of file +../../../tools/upip.py \ No newline at end of file diff --git a/ports/esp8266/modules/upip_utarfile.py b/ports/esp8266/modules/upip_utarfile.py index 149886291..d9653d6a6 120000 --- a/ports/esp8266/modules/upip_utarfile.py +++ b/ports/esp8266/modules/upip_utarfile.py @@ -1 +1 @@ -../../tools/upip_utarfile.py \ No newline at end of file +../../../tools/upip_utarfile.py \ No newline at end of file diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index c95d639af..ae295d655 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk CROSS = 0 diff --git a/ports/pic16bit/Makefile b/ports/pic16bit/Makefile index ebf4fc2e8..970e75d1f 100644 --- a/ports/pic16bit/Makefile +++ b/ports/pic16bit/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 71403cb5e..39e13853f 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk -include mpconfigport.mk # qstr definitions (must come before including py.mk) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 58a0a7c7a..913f0913e 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -8,7 +8,7 @@ endif # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) -include ../py/mkenv.mk +include ../../py/mkenv.mk -include mpconfigport.mk include boards/$(BOARD)/mpconfigboard.mk @@ -206,7 +206,7 @@ SRC_C = \ timer.c \ led.c \ pin.c \ - pin_defs_stmhal.c \ + pin_defs_stm32.c \ pin_named_pins.c \ bufhelper.c \ dma.c \ diff --git a/ports/stm32/README.md b/ports/stm32/README.md index 32b6d4176..bb184e8db 100644 --- a/ports/stm32/README.md +++ b/ports/stm32/README.md @@ -24,7 +24,7 @@ bytecode. The cross-compiler is built and run on the host machine, using: $ make -C mpy-cross ``` This command should be executed from the root directory of this repository. -All other commands below should be executed from the stmhal/ directory. +All other commands below should be executed from the ports/stm32/ directory. An ARM compiler is required for the build, along with the associated binary utilities. The default compiler is `arm-none-eabi-gcc`, which is available for @@ -71,7 +71,7 @@ Or using `dfu-util` directly: ST Discovery or Nucleo boards have a builtin programmer called ST-LINK. With these boards and using Linux or OS X, you have the option to upload the -`stmhal` firmware using the `st-flash` utility from the +`stm32` firmware using the `st-flash` utility from the [stlink](https://github.com/texane/stlink) project. To do so, connect the board with a mini USB cable to its ST-LINK USB port and then use the make target `deploy-stlink`. For example, if you have the STM32F4DISCOVERY board, you can @@ -101,7 +101,7 @@ a mini USB cable to its ST-LINK USB port and then use the make target $ make BOARD=STM32F4DISC deploy-openocd The `openocd` program, which writes the firmware to the target board's flash, -is configured via the file `stmhal/boards/openocd_stm32f4.cfg`. This +is configured via the file `ports/stm32/boards/openocd_stm32f4.cfg`. This configuration should work for all boards based on a STM32F4xx MCU with a ST-LINKv2 interface. You can override the path to this configuration by setting `OPENOCD_CONFIG` in your Makefile or on the command line. diff --git a/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h index c20421f0f..a1fd2e083 100644 --- a/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h @@ -46,7 +46,7 @@ /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ -// This board doesn't really have USB, but the stmhal codebase doesn't build +// This board doesn't really have USB, but the stm32 codebase doesn't build // without some USB defined, so we leave this on for now. #define USE_USB_FS diff --git a/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h index e16fba155..0c424888f 100644 --- a/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h @@ -46,7 +46,7 @@ /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ -// This board doesn't really have USB, but the stmhal codebase doesn't build +// This board doesn't really have USB, but the stm32 codebase doesn't build // without some USB defined, so we leave this on for now. #define USE_USB_FS diff --git a/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h index 3d0ce926b..487ca009f 100644 --- a/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h @@ -46,7 +46,7 @@ /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ -// This board doesn't really have USB, but the stmhal codebase doesn't build +// This board doesn't really have USB, but the stm32 codebase doesn't build // without some USB defined, so we leave this on for now. #define USE_USB_FS diff --git a/ports/stm32/help.c b/ports/stm32/help.c index 87b2af526..ea0b6921b 100644 --- a/ports/stm32/help.c +++ b/ports/stm32/help.c @@ -26,7 +26,7 @@ #include "py/builtin.h" -const char *stmhal_help_text = +const char *stm32_help_text = "Welcome to MicroPython!\n" "\n" "For online help please visit http://micropython.org/help/.\n" diff --git a/ports/stm32/modules/lcd160cr.py b/ports/stm32/modules/lcd160cr.py index c0e180714..9e63f1d23 120000 --- a/ports/stm32/modules/lcd160cr.py +++ b/ports/stm32/modules/lcd160cr.py @@ -1 +1 @@ -../../drivers/display/lcd160cr.py \ No newline at end of file +../../../drivers/display/lcd160cr.py \ No newline at end of file diff --git a/ports/stm32/modules/lcd160cr_test.py b/ports/stm32/modules/lcd160cr_test.py index 56f091351..5f5bcc128 120000 --- a/ports/stm32/modules/lcd160cr_test.py +++ b/ports/stm32/modules/lcd160cr_test.py @@ -1 +1 @@ -../../drivers/display/lcd160cr_test.py \ No newline at end of file +../../../drivers/display/lcd160cr_test.py \ No newline at end of file diff --git a/ports/stm32/modules/onewire.py b/ports/stm32/modules/onewire.py index f6ec745e8..33f30e84f 120000 --- a/ports/stm32/modules/onewire.py +++ b/ports/stm32/modules/onewire.py @@ -1 +1 @@ -../../drivers/onewire/onewire.py \ No newline at end of file +../../../drivers/onewire/onewire.py \ No newline at end of file diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 326aa2c20..21142c17b 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -92,7 +92,7 @@ #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_BUILTINS_HELP (1) -#define MICROPY_PY_BUILTINS_HELP_TEXT stmhal_help_text +#define MICROPY_PY_BUILTINS_HELP_TEXT stm32_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) @@ -345,4 +345,4 @@ static inline mp_uint_t disable_irq(void) { // We need to provide a declaration/definition of alloca() #include -#define MICROPY_PIN_DEFS_PORT_H "pin_defs_stmhal.h" +#define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h" diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 8dd95c470..939df0b3d 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -27,7 +27,7 @@ void mp_hal_set_interrupt_char(int c); // -1 to disable // timing functions -#include "stmhal/irq.h" +#include "irq.h" #define mp_hal_quiet_timing_enter() raise_irq_pri(1) #define mp_hal_quiet_timing_exit(irq_state) restore_irq_pri(irq_state) @@ -44,7 +44,7 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { // C-level pin HAL -#include "stmhal/pin.h" +#include "pin.h" #define MP_HAL_PIN_FMT "%q" #define MP_HAL_PIN_MODE_INPUT (0) diff --git a/ports/stm32/pin_defs_stm32.c b/ports/stm32/pin_defs_stm32.c new file mode 100644 index 000000000..0aef5f95f --- /dev/null +++ b/ports/stm32/pin_defs_stm32.c @@ -0,0 +1,31 @@ +#include "py/obj.h" +#include "pin.h" + +// Returns the pin mode. This value returned by this macro should be one of: +// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, +// GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG. + +uint32_t pin_get_mode(const pin_obj_t *pin) { + GPIO_TypeDef *gpio = pin->gpio; + uint32_t mode = (gpio->MODER >> (pin->pin * 2)) & 3; + if (mode != GPIO_MODE_ANALOG) { + if (gpio->OTYPER & pin->pin_mask) { + mode |= 1 << 4; + } + } + return mode; +} + +// Returns the pin pullup/pulldown. The value returned by this macro should +// be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN. + +uint32_t pin_get_pull(const pin_obj_t *pin) { + return (pin->gpio->PUPDR >> (pin->pin * 2)) & 3; +} + +// Returns the af (alternate function) index currently set for a pin. + +uint32_t pin_get_af(const pin_obj_t *pin) { + return (pin->gpio->AFR[pin->pin >> 3] >> ((pin->pin & 7) * 4)) & 0xf; +} + diff --git a/ports/stm32/pin_defs_stm32.h b/ports/stm32/pin_defs_stm32.h new file mode 100644 index 000000000..c5b286283 --- /dev/null +++ b/ports/stm32/pin_defs_stm32.h @@ -0,0 +1,131 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This file contains pin definitions that are specific to the stm32 port. +// This file should only ever be #included by pin.h and not directly. + +enum { + PORT_A, + PORT_B, + PORT_C, + PORT_D, + PORT_E, + PORT_F, + PORT_G, + PORT_H, + PORT_I, + PORT_J, + PORT_K, +}; + +enum { + AF_FN_TIM, + AF_FN_I2C, + AF_FN_USART, + AF_FN_UART = AF_FN_USART, + AF_FN_SPI, + AF_FN_I2S, + AF_FN_SDMMC, +}; + +enum { + AF_PIN_TYPE_TIM_CH1 = 0, + AF_PIN_TYPE_TIM_CH2, + AF_PIN_TYPE_TIM_CH3, + AF_PIN_TYPE_TIM_CH4, + AF_PIN_TYPE_TIM_CH1N, + AF_PIN_TYPE_TIM_CH2N, + AF_PIN_TYPE_TIM_CH3N, + AF_PIN_TYPE_TIM_CH1_ETR, + AF_PIN_TYPE_TIM_ETR, + AF_PIN_TYPE_TIM_BKIN, + + AF_PIN_TYPE_I2C_SDA = 0, + AF_PIN_TYPE_I2C_SCL, + + AF_PIN_TYPE_USART_TX = 0, + AF_PIN_TYPE_USART_RX, + AF_PIN_TYPE_USART_CTS, + AF_PIN_TYPE_USART_RTS, + AF_PIN_TYPE_USART_CK, + AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX, + AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX, + AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS, + AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS, + + AF_PIN_TYPE_SPI_MOSI = 0, + AF_PIN_TYPE_SPI_MISO, + AF_PIN_TYPE_SPI_SCK, + AF_PIN_TYPE_SPI_NSS, + + AF_PIN_TYPE_I2S_CK = 0, + AF_PIN_TYPE_I2S_MCK, + AF_PIN_TYPE_I2S_SD, + AF_PIN_TYPE_I2S_WS, + AF_PIN_TYPE_I2S_EXTSD, + + AF_PIN_TYPE_SDMMC_CK = 0, + AF_PIN_TYPE_SDMMC_CMD, + AF_PIN_TYPE_SDMMC_D0, + AF_PIN_TYPE_SDMMC_D1, + AF_PIN_TYPE_SDMMC_D2, + AF_PIN_TYPE_SDMMC_D3, +}; + +// The HAL uses a slightly different naming than we chose, so we provide +// some #defines to massage things. Also I2S and SPI share the same +// peripheral. + +#define GPIO_AF5_I2S2 GPIO_AF5_SPI2 +#define GPIO_AF5_I2S3 GPIO_AF5_I2S3ext +#define GPIO_AF6_I2S2 GPIO_AF6_I2S2ext +#define GPIO_AF6_I2S3 GPIO_AF6_SPI3 +#define GPIO_AF7_I2S2 GPIO_AF7_SPI2 +#define GPIO_AF7_I2S3 GPIO_AF7_I2S3ext + +#define I2S2 SPI2 +#define I2S3 SPI3 + +enum { + PIN_ADC1 = (1 << 0), + PIN_ADC2 = (1 << 1), + PIN_ADC3 = (1 << 2), +}; + +// Note that SPI and I2S are really the same peripheral as far as the HAL +// is concerned, so there is no I2S_TypeDef. +// We use void* for SDMMC because not all MCUs have the SDMMC_TypeDef type. +#define PIN_DEFS_PORT_AF_UNION \ + TIM_TypeDef *TIM; \ + I2C_TypeDef *I2C; \ + USART_TypeDef *USART; \ + USART_TypeDef *UART; \ + SPI_TypeDef *SPI;\ + SPI_TypeDef *I2S; \ + void *SDMMC; \ + +typedef GPIO_TypeDef pin_gpio_t; + diff --git a/ports/stm32/pin_defs_stmhal.c b/ports/stm32/pin_defs_stmhal.c deleted file mode 100644 index 0aef5f95f..000000000 --- a/ports/stm32/pin_defs_stmhal.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "py/obj.h" -#include "pin.h" - -// Returns the pin mode. This value returned by this macro should be one of: -// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, -// GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG. - -uint32_t pin_get_mode(const pin_obj_t *pin) { - GPIO_TypeDef *gpio = pin->gpio; - uint32_t mode = (gpio->MODER >> (pin->pin * 2)) & 3; - if (mode != GPIO_MODE_ANALOG) { - if (gpio->OTYPER & pin->pin_mask) { - mode |= 1 << 4; - } - } - return mode; -} - -// Returns the pin pullup/pulldown. The value returned by this macro should -// be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN. - -uint32_t pin_get_pull(const pin_obj_t *pin) { - return (pin->gpio->PUPDR >> (pin->pin * 2)) & 3; -} - -// Returns the af (alternate function) index currently set for a pin. - -uint32_t pin_get_af(const pin_obj_t *pin) { - return (pin->gpio->AFR[pin->pin >> 3] >> ((pin->pin & 7) * 4)) & 0xf; -} - diff --git a/ports/stm32/pin_defs_stmhal.h b/ports/stm32/pin_defs_stmhal.h deleted file mode 100644 index 6cf3b1b83..000000000 --- a/ports/stm32/pin_defs_stmhal.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// This file contains pin definitions that are specific to the stmhal port. -// This file should only ever be #included by pin.h and not directly. - -enum { - PORT_A, - PORT_B, - PORT_C, - PORT_D, - PORT_E, - PORT_F, - PORT_G, - PORT_H, - PORT_I, - PORT_J, - PORT_K, -}; - -enum { - AF_FN_TIM, - AF_FN_I2C, - AF_FN_USART, - AF_FN_UART = AF_FN_USART, - AF_FN_SPI, - AF_FN_I2S, - AF_FN_SDMMC, -}; - -enum { - AF_PIN_TYPE_TIM_CH1 = 0, - AF_PIN_TYPE_TIM_CH2, - AF_PIN_TYPE_TIM_CH3, - AF_PIN_TYPE_TIM_CH4, - AF_PIN_TYPE_TIM_CH1N, - AF_PIN_TYPE_TIM_CH2N, - AF_PIN_TYPE_TIM_CH3N, - AF_PIN_TYPE_TIM_CH1_ETR, - AF_PIN_TYPE_TIM_ETR, - AF_PIN_TYPE_TIM_BKIN, - - AF_PIN_TYPE_I2C_SDA = 0, - AF_PIN_TYPE_I2C_SCL, - - AF_PIN_TYPE_USART_TX = 0, - AF_PIN_TYPE_USART_RX, - AF_PIN_TYPE_USART_CTS, - AF_PIN_TYPE_USART_RTS, - AF_PIN_TYPE_USART_CK, - AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX, - AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX, - AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS, - AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS, - - AF_PIN_TYPE_SPI_MOSI = 0, - AF_PIN_TYPE_SPI_MISO, - AF_PIN_TYPE_SPI_SCK, - AF_PIN_TYPE_SPI_NSS, - - AF_PIN_TYPE_I2S_CK = 0, - AF_PIN_TYPE_I2S_MCK, - AF_PIN_TYPE_I2S_SD, - AF_PIN_TYPE_I2S_WS, - AF_PIN_TYPE_I2S_EXTSD, - - AF_PIN_TYPE_SDMMC_CK = 0, - AF_PIN_TYPE_SDMMC_CMD, - AF_PIN_TYPE_SDMMC_D0, - AF_PIN_TYPE_SDMMC_D1, - AF_PIN_TYPE_SDMMC_D2, - AF_PIN_TYPE_SDMMC_D3, -}; - -// The HAL uses a slightly different naming than we chose, so we provide -// some #defines to massage things. Also I2S and SPI share the same -// peripheral. - -#define GPIO_AF5_I2S2 GPIO_AF5_SPI2 -#define GPIO_AF5_I2S3 GPIO_AF5_I2S3ext -#define GPIO_AF6_I2S2 GPIO_AF6_I2S2ext -#define GPIO_AF6_I2S3 GPIO_AF6_SPI3 -#define GPIO_AF7_I2S2 GPIO_AF7_SPI2 -#define GPIO_AF7_I2S3 GPIO_AF7_I2S3ext - -#define I2S2 SPI2 -#define I2S3 SPI3 - -enum { - PIN_ADC1 = (1 << 0), - PIN_ADC2 = (1 << 1), - PIN_ADC3 = (1 << 2), -}; - -// Note that SPI and I2S are really the same peripheral as far as the HAL -// is concerned, so there is no I2S_TypeDef. -// We use void* for SDMMC because not all MCUs have the SDMMC_TypeDef type. -#define PIN_DEFS_PORT_AF_UNION \ - TIM_TypeDef *TIM; \ - I2C_TypeDef *I2C; \ - USART_TypeDef *USART; \ - USART_TypeDef *UART; \ - SPI_TypeDef *SPI;\ - SPI_TypeDef *I2S; \ - void *SDMMC; \ - -typedef GPIO_TypeDef pin_gpio_t; - diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index 944e281a4..08ecf0f91 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h @@ -31,7 +31,7 @@ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -mfloat INC += -I. INC += -I$(TOP) -INC += -I$(TOP)/stmhal +INC += -I$(TOP)/ports/stm32 INC += -I$(BUILD) INC += -Icore @@ -91,14 +91,14 @@ SRC_C = \ uart.c \ usb.c \ -STM_SRC_C = $(addprefix stmhal/,\ +STM_SRC_C = $(addprefix ports/stm32/,\ gccollect.c \ irq.c \ pin.c \ pin_named_pins.c \ ) -STM_SRC_S = $(addprefix stmhal/,\ +STM_SRC_S = $(addprefix ports/stm32/,\ gchelper.s \ ) diff --git a/ports/teensy/lcd.c b/ports/teensy/lcd.c index e79b7d5ac..e5d6115d7 100644 --- a/ports/teensy/lcd.c +++ b/ports/teensy/lcd.c @@ -1,5 +1,5 @@ #include "py/obj.h" -#include "../stmhal/lcd.h" +#include "../stm32/lcd.h" void lcd_init(void) { } diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 08bd4db30..1a1ea01f7 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -1,5 +1,5 @@ -include mpconfigport.mk -include ../py/mkenv.mk +include ../../py/mkenv.mk FROZEN_DIR = scripts FROZEN_MPY_DIR = modules @@ -188,7 +188,7 @@ include $(TOP)/py/mkrules.mk .PHONY: test test: $(PROG) $(TOP)/tests/run-tests - $(eval DIRNAME=$(notdir $(CURDIR))) + $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests # install micropython in /usr/local/bin @@ -253,7 +253,7 @@ coverage: BUILD=build-coverage PROG=micropython_coverage coverage_test: coverage - $(eval DIRNAME=$(notdir $(CURDIR))) + $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -d thread cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --emit native diff --git a/ports/unix/modules/upip.py b/ports/unix/modules/upip.py index 20d52a4ab..130eb6901 120000 --- a/ports/unix/modules/upip.py +++ b/ports/unix/modules/upip.py @@ -1 +1 @@ -../../tools/upip.py \ No newline at end of file +../../../tools/upip.py \ No newline at end of file diff --git a/ports/unix/modules/upip_utarfile.py b/ports/unix/modules/upip_utarfile.py index 149886291..d9653d6a6 120000 --- a/ports/unix/modules/upip_utarfile.py +++ b/ports/unix/modules/upip_utarfile.py @@ -1 +1 @@ -../../tools/upip_utarfile.py \ No newline at end of file +../../../tools/upip_utarfile.py \ No newline at end of file diff --git a/ports/windows/.appveyor.yml b/ports/windows/.appveyor.yml index 84060a116..a82cf5adc 100644 --- a/ports/windows/.appveyor.yml +++ b/ports/windows/.appveyor.yml @@ -15,7 +15,7 @@ platform: - x64 build: - project: windows/micropython.vcxproj + project: ports/windows/micropython.vcxproj verbosity: normal test_script: diff --git a/ports/windows/Makefile b/ports/windows/Makefile index a39d34826..b6433300f 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -1,4 +1,4 @@ -include ../py/mkenv.mk +include ../../py/mkenv.mk -include mpconfigport.mk # define main target @@ -28,13 +28,13 @@ endif # source files SRC_C = \ - unix/main.c \ - unix/file.c \ - unix/input.c \ - unix/modos.c \ - unix/modmachine.c \ - unix/modtime.c \ - unix/gccollect.c \ + ports/unix/main.c \ + ports/unix/file.c \ + ports/unix/input.c \ + ports/unix/modos.c \ + ports/unix/modmachine.c \ + ports/unix/modtime.c \ + ports/unix/gccollect.c \ windows_mphal.c \ realpath.c \ init.c \ diff --git a/ports/windows/README.md b/ports/windows/README.md index 6d3249903..f1bd40551 100644 --- a/ports/windows/README.md +++ b/ports/windows/README.md @@ -50,8 +50,8 @@ __Stack usage__ The msvc compiler is quite stack-hungry which might result in a "maximum recursion depth exceeded" RuntimeError for code with lots of nested function calls. There are several ways to deal with this: -- increase the threshold used for detection by altering the argument to `mp_stack_set_limit` in `unix/main.c` -- disable detection all together by setting `MICROPY_STACK_CHECK` to "0" in `windows/mpconfigport.h` +- increase the threshold used for detection by altering the argument to `mp_stack_set_limit` in `ports/unix/main.c` +- disable detection all together by setting `MICROPY_STACK_CHECK` to "0" in `ports/windows/mpconfigport.h` - disable the /GL compiler flag by setting `WholeProgramOptimization` to "false" See [issue 2927](https://github.com/micropython/micropython/issues/2927) for more information. diff --git a/ports/windows/msvc/genhdr.targets b/ports/windows/msvc/genhdr.targets index cac3e3ddc..ee030c906 100644 --- a/ports/windows/msvc/genhdr.targets +++ b/ports/windows/msvc/genhdr.targets @@ -10,7 +10,7 @@ $(PyBuildDir)genhdr\ $(PyBaseDir)py\ - $(PyBaseDir)unix\qstrdefsport.h + $(PyBaseDir)ports\unix\qstrdefsport.h $(PySrcDir)qstrdefs.h $(DestDir)qstrdefscollected.h $(DestDir)qstrdefs.generated.h diff --git a/ports/windows/msvc/paths.props b/ports/windows/msvc/paths.props index 716698243..db3af4c0f 100644 --- a/ports/windows/msvc/paths.props +++ b/ports/windows/msvc/paths.props @@ -3,28 +3,28 @@ True - - $([System.IO.Path]::GetFullPath(`$(MSBuildThisFileDirectory)..\..`))\ - $(PyBaseDir)windows\ + $([System.IO.Path]::GetFullPath(`$(MSBuildThisFileDirectory)..\..\..`))\ + $(PyBaseDir)ports\windows\ $(PyWinDir)build\ diff --git a/ports/windows/msvc/sources.props b/ports/windows/msvc/sources.props index a97686cdc..b85295ebc 100644 --- a/ports/windows/msvc/sources.props +++ b/ports/windows/msvc/sources.props @@ -3,16 +3,16 @@ - - + + - - - - - - - + + + + + + + @@ -31,7 +31,7 @@ - - + + diff --git a/ports/windows/windows_mphal.h b/ports/windows/windows_mphal.h index 5a93d4e18..2b7aab44a 100644 --- a/ports/windows/windows_mphal.h +++ b/ports/windows/windows_mphal.h @@ -25,7 +25,7 @@ */ #include "sleep.h" -#include "unix/mphalport.h" +#include "ports/unix/mphalport.h" #define MICROPY_HAL_HAS_VT100 (0) diff --git a/ports/zephyr/Makefile b/ports/zephyr/Makefile index 5840cc47e..8b7cb76c3 100644 --- a/ports/zephyr/Makefile +++ b/ports/zephyr/Makefile @@ -26,7 +26,7 @@ ifneq ($(MAKECMDGOALS), clean) include $(Z_EXPORTS) endif -include ../py/mkenv.mk +include ../../py/mkenv.mk include $(TOP)/py/py.mk INC += -I. diff --git a/py/mkrules.mk b/py/mkrules.mk index bf6ad2941..13545eb6f 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -103,7 +103,7 @@ endif ifneq ($(FROZEN_MPY_DIR),) # to build the MicroPython cross compiler -$(TOP)/mpy-cross/mpy-cross: $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/windows/fmode.c +$(TOP)/mpy-cross/mpy-cross: $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/ports/windows/fmode.c $(Q)$(MAKE) -C $(TOP)/mpy-cross # make a list of all the .py files that need compiling and freezing diff --git a/tests/run-tests b/tests/run-tests index f9c26283d..14df1e986 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -13,10 +13,10 @@ from glob import glob # to the correct executable. if os.name == 'nt': CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') - MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../windows/micropython.exe') + MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/windows/micropython.exe') else: CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') - MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../unix/micropython') + MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython') # mpy-cross is only needed if --via-mpy command-line arg is passed MPYCROSS = os.getenv('MICROPY_MPYCROSS', '../mpy-cross/mpy-cross') diff --git a/tools/check_code_size.sh b/tools/check_code_size.sh index c5f0c6ffd..2925ff168 100755 --- a/tools/check_code_size.sh +++ b/tools/check_code_size.sh @@ -10,7 +10,7 @@ REFERENCE=$HOME/persist/firmware.bin if [ -f $REFERENCE ]; then size_old=$(stat -c%s $REFERENCE) - size_new=$(stat -c%s minimal/build/firmware.bin) + size_new=$(stat -c%s ports/minimal/build/firmware.bin) echo "Old size: $size_old new size: $size_new" if [ $size_new -gt $size_old ]; then echo "Validation failure: Core code size increased" diff --git a/tools/codestats.sh b/tools/codestats.sh index 5272f3e9c..09284a30d 100755 --- a/tools/codestats.sh +++ b/tools/codestats.sh @@ -9,7 +9,7 @@ # executing because it does not exist in old revisions of the repository. # check that we are in the root directory of the repository -if [ ! -d py -o ! -d unix -o ! -d stmhal ]; then +if [ ! -d py -o ! -d ports/unix -o ! -d ports/stm32 ]; then echo "script must be run from root of the repository" exit 1 fi @@ -23,18 +23,18 @@ AWK=awk MAKE="make -j2" # these are the binaries that are built; some have 2 or 3 depending on version -bin_unix=unix/micropython -bin_stmhal=stmhal/build-PYBV10/firmware.elf -bin_barearm_1=bare-arm/build/flash.elf -bin_barearm_2=bare-arm/build/firmware.elf -bin_minimal=minimal/build/firmware.elf -bin_cc3200_1=cc3200/build/LAUNCHXL/application.axf -bin_cc3200_2=cc3200/build/LAUNCHXL/release/application.axf -bin_cc3200_3=cc3200/build/WIPY/release/application.axf +bin_unix=ports/unix/micropython +bin_stm32=ports/stm32/build-PYBV10/firmware.elf +bin_barearm_1=ports/bare-arm/build/flash.elf +bin_barearm_2=ports/bare-arm/build/firmware.elf +bin_minimal=ports/minimal/build/firmware.elf +bin_cc3200_1=ports/cc3200/build/LAUNCHXL/application.axf +bin_cc3200_2=ports/cc3200/build/LAUNCHXL/release/application.axf +bin_cc3200_3=ports/cc3200/build/WIPY/release/application.axf # start at zero size; if build fails reuse previous valid size size_unix="0" -size_stmhal="0" +size_stm32="0" size_barearm="0" size_minimal="0" size_cc3200="0" @@ -86,7 +86,7 @@ function get_size3() { if [ -r $output ]; then last_rev=$(tail -n1 $output | $AWK '{print $1}') else - echo "# hash size_unix size_stmhal size_barearm size_minimal size_cc3200 pystones" > $output + echo "# hash size_unix size_stm32 size_barearm size_minimal size_cc3200 pystones" > $output last_rev="v1.0" fi @@ -132,37 +132,37 @@ EOF #### unix #### $RM $bin_unix - $MAKE -C unix CFLAGS_EXTRA=-DNDEBUG + $MAKE -C ports/unix CFLAGS_EXTRA=-DNDEBUG size_unix=$(get_size $size_unix $bin_unix) # undo patch if it was applied git checkout unix/modtime.c - #### stmhal #### + #### stm32 #### - $RM $bin_stmhal - $MAKE -C stmhal board=PYBV10 - size_stmhal=$(get_size $size_stmhal $bin_stmhal) + $RM $bin_stm32 + $MAKE -C ports/stm32 board=PYBV10 + size_stm32=$(get_size $size_stm32 $bin_stm32) #### bare-arm #### $RM $bin_barearm_1 $bin_barearm_2 - $MAKE -C bare-arm + $MAKE -C ports/bare-arm size_barearm=$(get_size2 $size_barearm $bin_barearm_1 $bin_barearm_2) #### minimal #### - if [ -r minimal/Makefile ]; then + if [ -r ports/minimal/Makefile ]; then $RM $bin_minimal - $MAKE -C minimal CROSS=1 + $MAKE -C ports/minimal CROSS=1 size_minimal=$(get_size $size_minimal $bin_minimal) fi #### cc3200 #### - if [ -r cc3200/Makefile ]; then + if [ -r ports/cc3200/Makefile ]; then $RM $bin_cc3200_1 $bin_cc3200_2 $bin_cc3200_3 - $MAKE -C cc3200 BTARGET=application + $MAKE -C ports/cc3200 BTARGET=application size_cc3200=$(get_size3 $size_cc3200 $bin_cc3200_1 $bin_cc3200_2 $bin_cc3200_3) fi @@ -178,7 +178,7 @@ EOF #### output data for this commit #### - echo "$hash $size_unix $size_stmhal $size_barearm $size_minimal $size_cc3200 $pystones" >> $output + echo "$hash $size_unix $size_stm32 $size_barearm $size_minimal $size_cc3200 $pystones" >> $output done -- cgit v1.2.3 From 68c28174d0e0ec3f6b1461aea3a0b6a1b84610bb Mon Sep 17 00:00:00 2001 From: tll <1040424979@qq.com> Date: Sat, 24 Jun 2017 08:38:32 +0800 Subject: py/objstr: Add check for valid UTF-8 when making a str from bytes. This patch adds a function utf8_check() to check for a valid UTF-8 encoded string, and calls it when constructing a str from raw bytes. The feature is selectable at compile time via MICROPY_PY_BUILTINS_STR_UNICODE_CHECK and is enabled if unicode is enabled. It costs about 110 bytes on Thumb-2, 150 bytes on Xtensa and 170 bytes on x86-64. --- py/mpconfig.h | 5 +++++ py/objstr.c | 10 ++++++++++ py/unicode.c | 28 ++++++++++++++++++++++++++++ py/unicode.h | 1 + tests/unicode/unicode.py | 14 ++++++++++++++ 5 files changed, 58 insertions(+) (limited to 'py') diff --git a/py/mpconfig.h b/py/mpconfig.h index dac8a903c..38cf4b560 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -691,6 +691,11 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_STR_UNICODE (0) #endif +// Whether to check for valid UTF-8 when converting bytes to str +#ifndef MICROPY_PY_BUILTINS_STR_UNICODE_CHECK +#define MICROPY_PY_BUILTINS_STR_UNICODE_CHECK (MICROPY_PY_BUILTINS_STR_UNICODE) +#endif + // Whether str.center() method provided #ifndef MICROPY_PY_BUILTINS_STR_CENTER #define MICROPY_PY_BUILTINS_STR_CENTER (0) diff --git a/py/objstr.c b/py/objstr.c index 4c287af04..f6214f80c 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -161,6 +161,11 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ if (str_hash == 0) { str_hash = qstr_compute_hash(str_data, str_len); } + #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + if (!utf8_check(str_data, str_len)) { + mp_raise_msg(&mp_type_UnicodeError, NULL); + } + #endif mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len)); o->data = str_data; o->hash = str_hash; @@ -168,6 +173,11 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK + if (!utf8_check(bufinfo.buf, bufinfo.len)) { + mp_raise_msg(&mp_type_UnicodeError, NULL); + } + #endif return mp_obj_new_str(bufinfo.buf, bufinfo.len, false); } } diff --git a/py/unicode.c b/py/unicode.c index eddb007d5..140b7ba71 100644 --- a/py/unicode.c +++ b/py/unicode.c @@ -182,3 +182,31 @@ mp_uint_t unichar_xdigit_value(unichar c) { } return n; } + +bool utf8_check(const byte *p, size_t len) { + uint8_t need = 0; + const byte *end = p + len; + for (; p < end; p++) { + byte c = *p; + if (need) { + if (c >= 0x80) { + need--; + } else { + // mismatch + return 0; + } + } else { + if (c >= 0xc0) { + if (c >= 0xf8) { + // mismatch + return 0; + } + need = (0xe5 >> ((c >> 3) & 0x6)) & 3; + } else if (c >= 0x80) { + // mismatch + return 0; + } + } + } + return need == 0; // no pending fragments allowed +} diff --git a/py/unicode.h b/py/unicode.h index 19487a65a..c1fb51789 100644 --- a/py/unicode.h +++ b/py/unicode.h @@ -30,5 +30,6 @@ #include "py/misc.h" mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr); +bool utf8_check(const byte *p, size_t len); #endif // MICROPY_INCLUDED_PY_UNICODE_H diff --git a/tests/unicode/unicode.py b/tests/unicode/unicode.py index 5f29bc1c9..3a35ce894 100644 --- a/tests/unicode/unicode.py +++ b/tests/unicode/unicode.py @@ -33,3 +33,17 @@ try: int('\u0200') except ValueError: print('ValueError') + +# test invalid UTF-8 string +try: + str(b'ab\xa1', 'utf8') +except UnicodeError: + print('UnicodeError') +try: + str(b'ab\xf8', 'utf8') +except UnicodeError: + print('UnicodeError') +try: + str(bytearray(b'ab\xc0a'), 'utf8') +except UnicodeError: + print('UnicodeError') -- cgit v1.2.3 From 5c603bd0fd53e7dbd709883f289d1e580c86e33d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 7 Sep 2017 00:10:10 +0300 Subject: py/objlist: Properly implement comparison with incompatible types. Should raise TypeError, unless it's (in)equality comparison. --- py/objlist.c | 26 ++++++++++++-------------- tests/basics/list_compare.py | 10 ++++++++++ 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'py') diff --git a/py/objlist.c b/py/objlist.c index 6ac33e80e..d70867ded 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -87,18 +87,6 @@ STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ } } -// Don't pass MP_BINARY_OP_NOT_EQUAL here -STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { - mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); - if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) { - return false; - } - mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_list_t *another = MP_OBJ_TO_PTR(another_in); - - return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); -} - STATIC mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { @@ -146,8 +134,18 @@ STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: - case MP_BINARY_OP_MORE_EQUAL: - return mp_obj_new_bool(list_cmp_helper(op, lhs, rhs)); + case MP_BINARY_OP_MORE_EQUAL: { + if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) { + if (op == MP_BINARY_OP_EQUAL) { + return mp_const_false; + } + return MP_OBJ_NULL; // op not supported + } + + mp_obj_list_t *another = MP_OBJ_TO_PTR(rhs); + bool res = mp_seq_cmp_objs(op, o->items, o->len, another->items, another->len); + return mp_obj_new_bool(res); + } default: return MP_OBJ_NULL; // op not supported diff --git a/tests/basics/list_compare.py b/tests/basics/list_compare.py index eea881424..fd656c7f1 100644 --- a/tests/basics/list_compare.py +++ b/tests/basics/list_compare.py @@ -48,3 +48,13 @@ print([1] <= [1, 0]) print([1] <= [1, -1]) print([1, 0] <= [1]) print([1, -1] <= [1]) + + +print([] == {}) +print([] != {}) +print([1] == (1,)) + +try: + print([] < {}) +except TypeError: + print("TypeError") -- cgit v1.2.3 From d4d1c45a553c6361a72053383f0fe242f05cad3d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 7 Sep 2017 10:55:43 +0300 Subject: py/runtime0.h: Move relational ops to the beginning of mp_binary_op_t. This is to allow to encode arithmetic operations more efficiently, in preparation to introduction of __rOP__ method support. --- py/objint_mpz.c | 2 +- py/runtime0.h | 31 ++++++++++++++++--------------- tests/cmdline/cmd_showbc.py.exp | 22 +++++++++++----------- 3 files changed, 28 insertions(+), 27 deletions(-) (limited to 'py') diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 148446f0f..c7a3074ba 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -221,7 +221,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_obj_new_float(flhs / frhs); #endif - } else if (op <= MP_BINARY_OP_INPLACE_POWER) { + } else if (op >= MP_BINARY_OP_OR) { mp_obj_int_t *res = mp_obj_int_new_mpz(); switch (op) { diff --git a/py/runtime0.h b/py/runtime0.h index 703c950f2..074dac1e4 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -54,6 +54,22 @@ typedef enum { } mp_unary_op_t; typedef enum { + // Relational operations, should return a bool + MP_BINARY_OP_LESS, + MP_BINARY_OP_MORE, + MP_BINARY_OP_EQUAL, + MP_BINARY_OP_LESS_EQUAL, + MP_BINARY_OP_MORE_EQUAL, + + MP_BINARY_OP_NOT_EQUAL, + MP_BINARY_OP_IN, + MP_BINARY_OP_IS, + MP_BINARY_OP_EXCEPTION_MATCH, + // these are not supported by the runtime and must be synthesised by the emitter + MP_BINARY_OP_NOT_IN, + MP_BINARY_OP_IS_NOT, + + // Arithmetic operations MP_BINARY_OP_OR, MP_BINARY_OP_XOR, MP_BINARY_OP_AND, @@ -83,21 +99,6 @@ typedef enum { MP_BINARY_OP_INPLACE_TRUE_DIVIDE, MP_BINARY_OP_INPLACE_MODULO, MP_BINARY_OP_INPLACE_POWER, - - // these should return a bool - MP_BINARY_OP_LESS, - MP_BINARY_OP_MORE, - MP_BINARY_OP_EQUAL, - MP_BINARY_OP_LESS_EQUAL, - MP_BINARY_OP_MORE_EQUAL, - - MP_BINARY_OP_NOT_EQUAL, - MP_BINARY_OP_IN, - MP_BINARY_OP_IS, - MP_BINARY_OP_EXCEPTION_MATCH, - // these are not supported by the runtime and must be synthesised by the emitter - MP_BINARY_OP_NOT_IN, - MP_BINARY_OP_IS_NOT, } mp_binary_op_t; typedef enum { diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 1e015eb03..2dd927f74 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -43,9 +43,9 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): bc=\\d\+ line=126 00 LOAD_CONST_NONE 01 LOAD_CONST_FALSE -02 BINARY_OP 5 __add__ +02 BINARY_OP 16 __add__ 03 LOAD_CONST_TRUE -04 BINARY_OP 5 __add__ +04 BINARY_OP 16 __add__ 05 STORE_FAST 0 06 LOAD_CONST_SMALL_INT 0 07 STORE_FAST 0 @@ -84,7 +84,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ STORE_FAST 7 \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 -\\d\+ BINARY_OP 5 __add__ +\\d\+ BINARY_OP 16 __add__ \\d\+ STORE_FAST 8 \\d\+ LOAD_FAST 0 \\d\+ UNARY_OP 4 @@ -96,21 +96,21 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ LOAD_DEREF 14 \\d\+ DUP_TOP \\d\+ ROT_THREE -\\d\+ BINARY_OP 27 __eq__ +\\d\+ BINARY_OP 2 __eq__ \\d\+ JUMP_IF_FALSE_OR_POP \\d\+ \\d\+ LOAD_FAST 1 -\\d\+ BINARY_OP 27 __eq__ +\\d\+ BINARY_OP 2 __eq__ \\d\+ JUMP \\d\+ \\d\+ ROT_TWO \\d\+ POP_TOP \\d\+ STORE_FAST 10 \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 -\\d\+ BINARY_OP 27 __eq__ +\\d\+ BINARY_OP 2 __eq__ \\d\+ JUMP_IF_FALSE_OR_POP \\d\+ \\d\+ LOAD_DEREF 14 \\d\+ LOAD_FAST 1 -\\d\+ BINARY_OP 27 __eq__ +\\d\+ BINARY_OP 2 __eq__ \\d\+ UNARY_OP 6 \\d\+ STORE_FAST 10 \\d\+ LOAD_DEREF 14 @@ -132,7 +132,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ DUP_TOP_TWO \\d\+ LOAD_SUBSCR \\d\+ LOAD_FAST 12 -\\d\+ BINARY_OP 18 __iadd__ +\\d\+ BINARY_OP 29 __iadd__ \\d\+ ROT_THREE \\d\+ STORE_SUBSCR \\d\+ LOAD_DEREF 14 @@ -369,7 +369,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): 42 STORE_FAST_N 19 44 LOAD_FAST 9 45 LOAD_FAST_N 19 -47 BINARY_OP 5 __add__ +47 BINARY_OP 16 __add__ 48 POP_TOP 49 LOAD_CONST_NONE 50 RETURN_VALUE @@ -521,7 +521,7 @@ arg names: * bc=\\d\+ line=113 00 LOAD_DEREF 0 02 LOAD_CONST_SMALL_INT 1 -03 BINARY_OP 5 __add__ +03 BINARY_OP 16 __add__ 04 STORE_FAST 1 05 LOAD_CONST_SMALL_INT 1 06 STORE_DEREF 0 @@ -540,7 +540,7 @@ arg names: * b bc=\\d\+ line=139 00 LOAD_FAST 1 01 LOAD_DEREF 0 -03 BINARY_OP 5 __add__ +03 BINARY_OP 16 __add__ 04 RETURN_VALUE mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ -- cgit v1.2.3 From 50b9329eba29a36b6948699aaea9473681d4f46b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 7 Sep 2017 11:26:42 +0300 Subject: py/runtime0.h: Move MP_BINARY_OP_DIVMOD to the end of mp_binary_op_t. It starts a dichotomy of mp_binary_op_t values which can't appear in the bytecode. Another reason to move it is to VALUES of OP_* and OP_INPLACE_* nicely adjacent. This also will be needed for OP_REVERSE_*, to be soon introduced. --- py/runtime0.h | 6 +++++- tests/cmdline/cmd_showbc.py.exp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'py') diff --git a/py/runtime0.h b/py/runtime0.h index 074dac1e4..fd497a6d1 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -84,7 +84,6 @@ typedef enum { MP_BINARY_OP_MODULO, MP_BINARY_OP_POWER, - MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime MP_BINARY_OP_INPLACE_OR, MP_BINARY_OP_INPLACE_XOR, @@ -99,6 +98,11 @@ typedef enum { MP_BINARY_OP_INPLACE_TRUE_DIVIDE, MP_BINARY_OP_INPLACE_MODULO, MP_BINARY_OP_INPLACE_POWER, + + // Operations below this line don't appear in bytecode, they + // just identify special methods. + + MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime } mp_binary_op_t; typedef enum { diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 2dd927f74..0919aac53 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -132,7 +132,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ DUP_TOP_TWO \\d\+ LOAD_SUBSCR \\d\+ LOAD_FAST 12 -\\d\+ BINARY_OP 29 __iadd__ +\\d\+ BINARY_OP 28 __iadd__ \\d\+ ROT_THREE \\d\+ STORE_SUBSCR \\d\+ LOAD_DEREF 14 -- cgit v1.2.3 From 6d4cac088eb29c7909f81121608546ca1b5e292e Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 7 Sep 2017 12:54:58 +0300 Subject: py/objtype: Make sure mp_binary_op_method_name has full size again. After recent refactorings to mp_binary_op_t, and make it future refactoring proof for now, at the cost of extra element in the array. --- py/objtype.c | 2 +- py/runtime0.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'py') diff --git a/py/objtype.c b/py/objtype.c index 83a9836c3..8ce593dba 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -453,7 +453,7 @@ const qstr mp_binary_op_method_name[] = { /* MP_BINARY_OP_IS, */ - [MP_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size + [MP_BINARY_OP_LAST] = 0, // used to make sure array has full size, TODO: FIXME }; STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { diff --git a/py/runtime0.h b/py/runtime0.h index fd497a6d1..723ab582d 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -103,6 +103,8 @@ typedef enum { // just identify special methods. MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime + + MP_BINARY_OP_LAST, } mp_binary_op_t; typedef enum { -- cgit v1.2.3 From c460f6f15af681860f7606761da7579c9945761b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 7 Sep 2017 13:37:33 +0300 Subject: py/runtime0.h: Regroup operations a bit. Originally, there were grouped in blocks of 5, to make it easier e.g. to assess and numeric code of each. But now it makes more sense to group it by semantics/properties, and then split in chunks still, which usually leads to chunks of ~6 ops. --- py/runtime0.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'py') diff --git a/py/runtime0.h b/py/runtime0.h index 723ab582d..b34211d57 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -60,8 +60,8 @@ typedef enum { MP_BINARY_OP_EQUAL, MP_BINARY_OP_LESS_EQUAL, MP_BINARY_OP_MORE_EQUAL, - MP_BINARY_OP_NOT_EQUAL, + MP_BINARY_OP_IN, MP_BINARY_OP_IS, MP_BINARY_OP_EXCEPTION_MATCH, @@ -75,24 +75,23 @@ typedef enum { MP_BINARY_OP_AND, MP_BINARY_OP_LSHIFT, MP_BINARY_OP_RSHIFT, - MP_BINARY_OP_ADD, + MP_BINARY_OP_SUBTRACT, MP_BINARY_OP_MULTIPLY, MP_BINARY_OP_FLOOR_DIVIDE, MP_BINARY_OP_TRUE_DIVIDE, - MP_BINARY_OP_MODULO, MP_BINARY_OP_POWER, + MP_BINARY_OP_INPLACE_OR, MP_BINARY_OP_INPLACE_XOR, - MP_BINARY_OP_INPLACE_AND, MP_BINARY_OP_INPLACE_LSHIFT, MP_BINARY_OP_INPLACE_RSHIFT, MP_BINARY_OP_INPLACE_ADD, - MP_BINARY_OP_INPLACE_SUBTRACT, + MP_BINARY_OP_INPLACE_SUBTRACT, MP_BINARY_OP_INPLACE_MULTIPLY, MP_BINARY_OP_INPLACE_FLOOR_DIVIDE, MP_BINARY_OP_INPLACE_TRUE_DIVIDE, -- cgit v1.2.3 From b8ee7ab5b988f424e34e778fe3a679710d675efa Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 8 Sep 2017 00:10:10 +0300 Subject: py/runtime0.h: Put inplace arith ops in front of normal operations. This is to allow to place reverse ops immediately after normal ops, so they can be tested as one range (which is optimization for reverse ops introduction in the next patch). --- py/objint_mpz.c | 2 +- py/runtime0.h | 28 ++++++++++++++-------------- tests/cmdline/cmd_showbc.py.exp | 14 +++++++------- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'py') diff --git a/py/objint_mpz.c b/py/objint_mpz.c index c7a3074ba..0e318b492 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -221,7 +221,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_obj_new_float(flhs / frhs); #endif - } else if (op >= MP_BINARY_OP_OR) { + } else if (op >= MP_BINARY_OP_INPLACE_OR) { mp_obj_int_t *res = mp_obj_int_new_mpz(); switch (op) { diff --git a/py/runtime0.h b/py/runtime0.h index b34211d57..3cf5e530d 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -70,20 +70,6 @@ typedef enum { MP_BINARY_OP_IS_NOT, // Arithmetic operations - MP_BINARY_OP_OR, - MP_BINARY_OP_XOR, - MP_BINARY_OP_AND, - MP_BINARY_OP_LSHIFT, - MP_BINARY_OP_RSHIFT, - MP_BINARY_OP_ADD, - - MP_BINARY_OP_SUBTRACT, - MP_BINARY_OP_MULTIPLY, - MP_BINARY_OP_FLOOR_DIVIDE, - MP_BINARY_OP_TRUE_DIVIDE, - MP_BINARY_OP_MODULO, - MP_BINARY_OP_POWER, - MP_BINARY_OP_INPLACE_OR, MP_BINARY_OP_INPLACE_XOR, MP_BINARY_OP_INPLACE_AND, @@ -98,6 +84,20 @@ typedef enum { MP_BINARY_OP_INPLACE_MODULO, MP_BINARY_OP_INPLACE_POWER, + MP_BINARY_OP_OR, + MP_BINARY_OP_XOR, + MP_BINARY_OP_AND, + MP_BINARY_OP_LSHIFT, + MP_BINARY_OP_RSHIFT, + MP_BINARY_OP_ADD, + + MP_BINARY_OP_SUBTRACT, + MP_BINARY_OP_MULTIPLY, + MP_BINARY_OP_FLOOR_DIVIDE, + MP_BINARY_OP_TRUE_DIVIDE, + MP_BINARY_OP_MODULO, + MP_BINARY_OP_POWER, + // Operations below this line don't appear in bytecode, they // just identify special methods. diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 0919aac53..0e66a013d 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -43,9 +43,9 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): bc=\\d\+ line=126 00 LOAD_CONST_NONE 01 LOAD_CONST_FALSE -02 BINARY_OP 16 __add__ +02 BINARY_OP 28 __add__ 03 LOAD_CONST_TRUE -04 BINARY_OP 16 __add__ +04 BINARY_OP 28 __add__ 05 STORE_FAST 0 06 LOAD_CONST_SMALL_INT 0 07 STORE_FAST 0 @@ -84,7 +84,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ STORE_FAST 7 \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 -\\d\+ BINARY_OP 16 __add__ +\\d\+ BINARY_OP 28 __add__ \\d\+ STORE_FAST 8 \\d\+ LOAD_FAST 0 \\d\+ UNARY_OP 4 @@ -132,7 +132,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ DUP_TOP_TWO \\d\+ LOAD_SUBSCR \\d\+ LOAD_FAST 12 -\\d\+ BINARY_OP 28 __iadd__ +\\d\+ BINARY_OP 16 __iadd__ \\d\+ ROT_THREE \\d\+ STORE_SUBSCR \\d\+ LOAD_DEREF 14 @@ -369,7 +369,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): 42 STORE_FAST_N 19 44 LOAD_FAST 9 45 LOAD_FAST_N 19 -47 BINARY_OP 16 __add__ +47 BINARY_OP 28 __add__ 48 POP_TOP 49 LOAD_CONST_NONE 50 RETURN_VALUE @@ -521,7 +521,7 @@ arg names: * bc=\\d\+ line=113 00 LOAD_DEREF 0 02 LOAD_CONST_SMALL_INT 1 -03 BINARY_OP 16 __add__ +03 BINARY_OP 28 __add__ 04 STORE_FAST 1 05 LOAD_CONST_SMALL_INT 1 06 STORE_DEREF 0 @@ -540,7 +540,7 @@ arg names: * b bc=\\d\+ line=139 00 LOAD_FAST 1 01 LOAD_DEREF 0 -03 BINARY_OP 16 __add__ +03 BINARY_OP 28 __add__ 04 RETURN_VALUE mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ -- cgit v1.2.3 From e6fbee0981611bed51a628dde77ee75c82609111 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 10 Sep 2017 15:15:41 +1000 Subject: py/builtinhelp: Simplify code slightly by extracting object type. Reduces code size by about 10 bytes. --- py/builtinhelp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'py') diff --git a/py/builtinhelp.c b/py/builtinhelp.c index dbcd6e00f..e10e48b7d 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -136,20 +136,19 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { } #endif + mp_obj_type_t *type = mp_obj_get_type(obj); + // try to print something sensible about the given object mp_print_str(MP_PYTHON_PRINTER, "object "); mp_obj_print(obj, PRINT_STR); - mp_printf(MP_PYTHON_PRINTER, " is of type %s\n", mp_obj_get_type_str(obj)); + mp_printf(MP_PYTHON_PRINTER, " is of type %q\n", type->name); mp_map_t *map = NULL; - if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) { + if (type == &mp_type_module) { map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj)); } else { - mp_obj_type_t *type; - if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) { - type = obj; - } else { - type = mp_obj_get_type(obj); + if (type == &mp_type_type) { + type = MP_OBJ_TO_PTR(obj); } if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) { map = mp_obj_dict_get_map(type->locals_dict); -- cgit v1.2.3 From 9355cca610e2e7f16a5847271fefe47db97b8cc4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 10 Sep 2017 13:54:00 +0300 Subject: esp8266: Set DEFPSIZE=1024, MINCACHE=3 for "btree" module. Defaults of 4096 and 5 respectively are too high to esp8266, causing out of memory with a database beyond couple of pages. --- ports/esp8266/Makefile | 1 + py/py.mk | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'py') diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 177a32353..95236a8d9 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -7,6 +7,7 @@ MICROPY_PY_USSL = 1 MICROPY_SSL_AXTLS = 1 MICROPY_FATFS = 1 MICROPY_PY_BTREE = 1 +BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3 FROZEN_DIR ?= scripts FROZEN_MPY_DIR ?= modules diff --git a/py/py.mk b/py/py.mk index 663237603..f5faad182 100644 --- a/py/py.mk +++ b/py/py.mk @@ -74,7 +74,7 @@ endif ifeq ($(MICROPY_PY_BTREE),1) BTREE_DIR = lib/berkeley-db-1.xx -BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ -Dvirt_fd_t=mp_obj_t "-DVIRT_FD_T_HEADER=" +BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ -Dvirt_fd_t=mp_obj_t "-DVIRT_FD_T_HEADER=" $(BTREE_DEFS_EXTRA) INC += -I$(TOP)/$(BTREE_DIR)/PORT/include SRC_MOD += extmod/modbtree.c SRC_MOD += $(addprefix $(BTREE_DIR)/,\ -- cgit v1.2.3 From eb84a830df62813f5af7f0144fc77444bf18f3a8 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 10 Sep 2017 17:05:20 +0300 Subject: py/runtime: Implement dispatch for "reverse op" special methods. If, for class X, X.__add__(Y) doesn't exist (or returns NotImplemented), try Y.__radd__(X) instead. This patch could be simpler, but requires undoing operand swap and operation switch to get non-confusing error message in case __radd__ doesn't exist. --- ports/unix/mpconfigport_coverage.h | 1 + py/mpconfig.h | 10 +++++++++- py/objtype.c | 7 +++++++ py/runtime.c | 15 ++++++++++++++- py/runtime0.h | 17 +++++++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) (limited to 'py') diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index a9e0a38fa..367b4853a 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -35,6 +35,7 @@ #define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_PY_DELATTR_SETATTR (1) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_SYS_GETSIZEOF (1) diff --git a/py/mpconfig.h b/py/mpconfig.h index 38cf4b560..63438a846 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -759,11 +759,19 @@ typedef double mp_float_t; #endif // Whether to support complete set of special methods -// for user classes, otherwise only the most used +// for user classes, or only the most used ones. "Reverse" +// methods are controlled by MICROPY_PY_REVERSE_SPECIAL_METHODS +// below. #ifndef MICROPY_PY_ALL_SPECIAL_METHODS #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #endif +// Whether to support reverse arithmetic operarions methods +// (__radd__, etc.) +#ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) +#endif + // Whether to support compile function #ifndef MICROPY_PY_BUILTINS_COMPILE #define MICROPY_PY_BUILTINS_COMPILE (0) diff --git a/py/objtype.c b/py/objtype.c index 8ce593dba..cf9311d5c 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -441,6 +441,13 @@ const qstr mp_binary_op_method_name[] = { MP_BINARY_OP_INPLACE_TRUE_DIVIDE, MP_BINARY_OP_INPLACE_MODULO, MP_BINARY_OP_INPLACE_POWER,*/ + + #if MICROPY_PY_REVERSE_SPECIAL_METHODS + [MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__, + [MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__, + [MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__, + #endif + [MP_BINARY_OP_LESS] = MP_QSTR___lt__, [MP_BINARY_OP_MORE] = MP_QSTR___gt__, [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__, diff --git a/py/runtime.c b/py/runtime.c index 21ef42577..c533558da 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -555,7 +555,20 @@ generic_binary_op: } } - // TODO implement dispatch for reverse binary ops +#if MICROPY_PY_REVERSE_SPECIAL_METHODS + if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_REVERSE_POWER) { + mp_obj_t t = rhs; + rhs = lhs; + lhs = t; + if (op <= MP_BINARY_OP_POWER) { + op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; + goto generic_binary_op; + } + + // Convert __rop__ back to __op__ for error message + op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; + } +#endif unsupported_op: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { diff --git a/py/runtime0.h b/py/runtime0.h index 3cf5e530d..a3e9d46b9 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -101,6 +101,23 @@ typedef enum { // Operations below this line don't appear in bytecode, they // just identify special methods. + // MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_* +#if MICROPY_PY_REVERSE_SPECIAL_METHODS + MP_BINARY_OP_REVERSE_OR, + MP_BINARY_OP_REVERSE_XOR, + MP_BINARY_OP_REVERSE_AND, + MP_BINARY_OP_REVERSE_LSHIFT, + MP_BINARY_OP_REVERSE_RSHIFT, + MP_BINARY_OP_REVERSE_ADD, + + MP_BINARY_OP_REVERSE_SUBTRACT, + MP_BINARY_OP_REVERSE_MULTIPLY, + MP_BINARY_OP_REVERSE_FLOOR_DIVIDE, + MP_BINARY_OP_REVERSE_TRUE_DIVIDE, + MP_BINARY_OP_REVERSE_MODULO, + MP_BINARY_OP_REVERSE_POWER, +#endif + MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime MP_BINARY_OP_LAST, -- cgit v1.2.3 From 52620c6b0e8a601e49866d0db37abbe217b16a0d Mon Sep 17 00:00:00 2001 From: ASM Date: Fri, 8 Sep 2017 15:01:14 +0300 Subject: py/nlrx86: Fix building for Android/x86. Tested using Clang on self-hosted Termux environment https://termux.com/. --- py/nlrx86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/nlrx86.c b/py/nlrx86.c index 8d15d7bab..a5a20f373 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -55,7 +55,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { // by default. // TODE: Better support for various x86 calling conventions // (unfortunately, __attribute__((naked)) is not supported on x86). - #ifndef __ZEPHYR__ + #if !(defined(__ZEPHYR__) || defined(__ANDROID__)) "pop %ebp \n" // undo function's prelude #endif "mov 4(%esp), %edx \n" // load nlr_buf -- cgit v1.2.3 From da8c4c2653b5121070f8c2872aead79d67d28441 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 12 Sep 2017 16:03:52 +1000 Subject: py/builtinhelp: Change signature of help text var from pointer to array. As a pointer (const char *) it takes up an extra word of storage which is in RAM. --- ports/cc3200/misc/help.c | 2 +- ports/esp8266/help.c | 2 +- ports/stm32/help.c | 2 +- ports/teensy/help.c | 2 +- ports/zephyr/help.c | 2 +- py/builtin.h | 2 +- py/builtinhelp.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'py') diff --git a/ports/cc3200/misc/help.c b/ports/cc3200/misc/help.c index 739303e19..ea0c9501d 100644 --- a/ports/cc3200/misc/help.c +++ b/ports/cc3200/misc/help.c @@ -27,6 +27,6 @@ #include "py/builtin.h" -const char *cc3200_help_text = "Welcome to MicroPython!\n" +const char cc3200_help_text[] = "Welcome to MicroPython!\n" "For online help please visit http://micropython.org/help/.\n" "For further help on a specific object, type help(obj)\n"; diff --git a/ports/esp8266/help.c b/ports/esp8266/help.c index 2035cdd6c..0a851f4c4 100644 --- a/ports/esp8266/help.c +++ b/ports/esp8266/help.c @@ -26,7 +26,7 @@ #include "py/builtin.h" -const char *esp_help_text = +const char esp_help_text[] = "Welcome to MicroPython!\n" "\n" "For online docs please visit http://docs.micropython.org/en/latest/esp8266/ .\n" diff --git a/ports/stm32/help.c b/ports/stm32/help.c index ea0b6921b..f9d97b70d 100644 --- a/ports/stm32/help.c +++ b/ports/stm32/help.c @@ -26,7 +26,7 @@ #include "py/builtin.h" -const char *stm32_help_text = +const char stm32_help_text[] = "Welcome to MicroPython!\n" "\n" "For online help please visit http://micropython.org/help/.\n" diff --git a/ports/teensy/help.c b/ports/teensy/help.c index ebe4bed6b..a2370c04d 100644 --- a/ports/teensy/help.c +++ b/ports/teensy/help.c @@ -26,7 +26,7 @@ #include "py/builtin.h" -const char *teensy_help_text = +const char teensy_help_text[] = "Welcome to MicroPython!\n" "\n" "For online help please visit http://micropython.org/help/.\n" diff --git a/ports/zephyr/help.c b/ports/zephyr/help.c index 0c7f27940..becc203f6 100644 --- a/ports/zephyr/help.c +++ b/ports/zephyr/help.c @@ -26,7 +26,7 @@ #include "py/builtin.h" -const char *zephyr_help_text = +const char zephyr_help_text[] = "Welcome to MicroPython!\n" "\n" "Control commands:\n" diff --git a/py/builtin.h b/py/builtin.h index a637b6e22..84b99a8a4 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -118,6 +118,6 @@ extern const mp_obj_module_t mp_module_webrepl; extern const mp_obj_module_t mp_module_framebuf; extern const mp_obj_module_t mp_module_btree; -extern const char *MICROPY_PY_BUILTINS_HELP_TEXT; +extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; #endif // MICROPY_INCLUDED_PY_BUILTIN_H diff --git a/py/builtinhelp.c b/py/builtinhelp.c index e10e48b7d..c9992906d 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -32,7 +32,7 @@ #if MICROPY_PY_BUILTINS_HELP -const char *mp_help_default_text = +const char mp_help_default_text[] = "Welcome to MicroPython!\n" "\n" "For online docs please visit http://docs.micropython.org/\n" -- cgit v1.2.3 From 89f657f073d212161a04082419faeca30fc3a410 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Sep 2017 20:33:55 +1000 Subject: py/runtime.h: Change empty mp_warning macro so var-args are non empty. Variable arguments in a macro should take at least 1 argument. --- py/runtime.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/runtime.h b/py/runtime.h index 4abdea584..bbdd7647e 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -175,7 +175,7 @@ void mp_native_raise(mp_obj_t o); #if MICROPY_WARNINGS void mp_warning(const char *msg, ...); #else -#define mp_warning(msg, ...) +#define mp_warning(...) #endif #endif // MICROPY_INCLUDED_PY_RUNTIME_H -- cgit v1.2.3 From 280fb4d92830bedb1f4ef90554300e444661ef8c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Sep 2017 20:36:06 +1000 Subject: py/emitbc: Remove stray semicolon in outer scope. --- py/emitbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/emitbc.c b/py/emitbc.c index 677020925..3f4dfc178 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -550,7 +550,7 @@ void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) { void mp_emit_bc_load_null(emit_t *emit) { emit_bc_pre(emit, 1); emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL); -}; +} void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { (void)qst; -- cgit v1.2.3 From 9dce823cfd0a9991350184f08a1373f3887134f4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 18 Sep 2017 00:06:43 +0300 Subject: py/modbuiltins: Implement abs() by dispatching to MP_UNARY_OP_ABS. This allows user classes to implement __abs__ special method, and saves code size (104 bytes for x86_64), even though during refactor, an issue was fixed and few optimizations were made: * abs() of minimum (negative) small int value is calculated properly. * objint_longlong and objint_mpz avoid allocating new object is the argument is already non-negative. --- py/modbuiltins.c | 21 +-------------------- py/objcomplex.c | 5 +++++ py/objfloat.c | 9 +++++++++ py/objint.c | 10 ---------- py/objint.h | 1 - py/objint_longlong.c | 34 ++++++++++------------------------ py/objint_mpz.c | 30 +++++++++--------------------- py/runtime.c | 9 +++++++++ py/runtime0.h | 1 + tests/unix/extra_coverage.py.exp | 2 +- 10 files changed, 45 insertions(+), 77 deletions(-) (limited to 'py') diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 1c76b8073..0486251b6 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -91,26 +91,7 @@ STATIC mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__); STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) { - #if MICROPY_PY_BUILTINS_FLOAT - if (mp_obj_is_float(o_in)) { - mp_float_t value = mp_obj_float_get(o_in); - // TODO check for NaN etc - if (value < 0) { - return mp_obj_new_float(-value); - } else { - return o_in; - } - #if MICROPY_PY_BUILTINS_COMPLEX - } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) { - mp_float_t real, imag; - mp_obj_complex_get(o_in, &real, &imag); - return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)); - #endif - } - #endif - - // this will raise a TypeError if the argument is not integral - return mp_obj_int_abs(o_in); + return mp_unary_op(MP_UNARY_OP_ABS, o_in); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs); diff --git a/py/objcomplex.c b/py/objcomplex.c index 07b9d5d41..e7a3c244a 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -124,6 +124,11 @@ STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag)); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag); + case MP_UNARY_OP_ABS: { + mp_float_t real, imag; + mp_obj_complex_get(o_in, &real, &imag); + return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)); + } default: return MP_OBJ_NULL; // op not supported } } diff --git a/py/objfloat.c b/py/objfloat.c index fadbbcb79..fefd78314 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -162,6 +162,15 @@ STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val)); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val); + case MP_UNARY_OP_ABS: { + mp_float_t value = mp_obj_float_get(o_in); + // TODO check for NaN etc + if (value < 0) { + return mp_obj_new_float(-value); + } else { + return o_in; + } + } default: return MP_OBJ_NULL; // op not supported } } diff --git a/py/objint.c b/py/objint.c index 6a73b4382..000a0404c 100644 --- a/py/objint.c +++ b/py/objint.c @@ -314,16 +314,6 @@ int mp_obj_int_sign(mp_obj_t self_in) { } } -// This must handle int and bool types, and must raise a -// TypeError if the argument is not integral -mp_obj_t mp_obj_int_abs(mp_obj_t self_in) { - mp_int_t val = mp_obj_get_int(self_in); - if (val < 0) { - val = -val; - } - return MP_OBJ_NEW_SMALL_INT(val); -} - // This is called for operations on SMALL_INT that are not handled by mp_unary_op mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { return MP_OBJ_NULL; // op not supported diff --git a/py/objint.h b/py/objint.h index a4d4ff32d..4b95acde9 100644 --- a/py/objint.h +++ b/py/objint.h @@ -57,7 +57,6 @@ mp_int_t mp_obj_int_hash(mp_obj_t self_in); mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf); void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); int mp_obj_int_sign(mp_obj_t self_in); -mp_obj_t mp_obj_int_abs(mp_obj_t self_in); mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in); mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index ddfdae744..8d8ca1b2c 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -94,30 +94,6 @@ int mp_obj_int_sign(mp_obj_t self_in) { } } -// This must handle int and bool types, and must raise a -// TypeError if the argument is not integral -mp_obj_t mp_obj_int_abs(mp_obj_t self_in) { - if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) { - mp_obj_int_t *self = self_in; - self = mp_obj_new_int_from_ll(self->val); - if (self->val < 0) { - // TODO could overflow long long - self->val = -self->val; - } - return self; - } else { - mp_int_t val = mp_obj_get_int(self_in); - if (val == MP_SMALL_INT_MIN) { - return mp_obj_new_int_from_ll(-val); - } else { - if (val < 0) { - val = -val; - } - return MP_OBJ_NEW_SMALL_INT(val); - } - } -} - mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_int_t *o = o_in; switch (op) { @@ -130,6 +106,16 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_int_from_ll(-o->val); case MP_UNARY_OP_INVERT: return mp_obj_new_int_from_ll(~o->val); + case MP_UNARY_OP_ABS: { + mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in); + if (self->val >= 0) { + return o_in; + } + self = mp_obj_new_int_from_ll(self->val); + // TODO could overflow long long + self->val = -self->val; + return MP_OBJ_FROM_PTR(self); + } default: return MP_OBJ_NULL; // op not supported } } diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 0e318b492..15aad1d4d 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -141,27 +141,6 @@ int mp_obj_int_sign(mp_obj_t self_in) { } } -// This must handle int and bool types, and must raise a -// TypeError if the argument is not integral -mp_obj_t mp_obj_int_abs(mp_obj_t self_in) { - if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) { - mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_int_t *self2 = mp_obj_int_new_mpz(); - mpz_abs_inpl(&self2->mpz, &self->mpz); - return MP_OBJ_FROM_PTR(self2); - } else { - mp_int_t val = mp_obj_get_int(self_in); - if (val == MP_SMALL_INT_MIN) { - return mp_obj_new_int_from_ll(-val); - } else { - if (val < 0) { - val = -val; - } - return MP_OBJ_NEW_SMALL_INT(val); - } - } -} - mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { @@ -170,6 +149,15 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); } case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); } + case MP_UNARY_OP_ABS: { + mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in); + if (self->mpz.neg == 0) { + return o_in; + } + mp_obj_int_t *self2 = mp_obj_int_new_mpz(); + mpz_abs_inpl(&self2->mpz, &self->mpz); + return MP_OBJ_FROM_PTR(self2); + } default: return MP_OBJ_NULL; // op not supported } } diff --git a/py/runtime.c b/py/runtime.c index c533558da..f21eed204 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -231,6 +231,15 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { } else { return MP_OBJ_NEW_SMALL_INT(-val); } + case MP_UNARY_OP_ABS: + if (val >= 0) { + return arg; + } else if (val == MP_SMALL_INT_MIN) { + // check for overflow + return mp_obj_new_int(-val); + } else { + return MP_OBJ_NEW_SMALL_INT(-val); + } default: assert(op == MP_UNARY_OP_INVERT); return MP_OBJ_NEW_SMALL_INT(~val); diff --git a/py/runtime0.h b/py/runtime0.h index a3e9d46b9..54bf192d3 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -50,6 +50,7 @@ typedef enum { MP_UNARY_OP_NEGATIVE, MP_UNARY_OP_INVERT, MP_UNARY_OP_NOT, + MP_UNARY_OP_ABS, // __abs__ MP_UNARY_OP_SIZEOF, // for sys.getsizeof() } mp_unary_op_t; diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index ab638a632..4dc421dab 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -38,7 +38,7 @@ ementation 0 0 # runtime utils -TypeError: can't convert str to int +TypeError: unsupported type for : 'str' TypeError: unsupported types for : 'str', 'str' Warning: test # format float -- cgit v1.2.3 From fdb2aa81b7c7588d94ec59932781e14759045df0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 18 Sep 2017 14:31:03 +1000 Subject: py/{objfloat,objcomplex}: Optimise MP_UNARY_OP_ABS by reusing variables. --- py/objcomplex.c | 7 ++----- py/objfloat.c | 5 ++--- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'py') diff --git a/py/objcomplex.c b/py/objcomplex.c index e7a3c244a..088ad5211 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -124,11 +124,8 @@ STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag)); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag); - case MP_UNARY_OP_ABS: { - mp_float_t real, imag; - mp_obj_complex_get(o_in, &real, &imag); - return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)); - } + case MP_UNARY_OP_ABS: + return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(o->real*o->real + o->imag*o->imag)); default: return MP_OBJ_NULL; // op not supported } } diff --git a/py/objfloat.c b/py/objfloat.c index fefd78314..55a9379ff 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -163,10 +163,9 @@ STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val); case MP_UNARY_OP_ABS: { - mp_float_t value = mp_obj_float_get(o_in); // TODO check for NaN etc - if (value < 0) { - return mp_obj_new_float(-value); + if (val < 0) { + return mp_obj_new_float(-val); } else { return o_in; } -- cgit v1.2.3 From 44f0a4d1e7a315c8d2b21fc4b0471d88e382a91e Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 18 Sep 2017 23:53:33 +1000 Subject: py/mpconfig.h: Add note that using computed gotos in VM is not C99. --- py/mpconfig.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'py') diff --git a/py/mpconfig.h b/py/mpconfig.h index 63438a846..b93f851d6 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -383,6 +383,8 @@ // Whether to use computed gotos in the VM, or a switch // Computed gotos are roughly 10% faster, and increase VM code size by a little +// Note: enabling this will use the gcc-specific extensions of ranged designated +// initialisers and addresses of labels, which are not part of the C99 standard. #ifndef MICROPY_OPT_COMPUTED_GOTO #define MICROPY_OPT_COMPUTED_GOTO (0) #endif -- cgit v1.2.3 From fc9a6dd09e77c34ef04bab57e73bfcb08bc78bb4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 19 Sep 2017 21:19:23 +0300 Subject: py/objstr: strip: Don't strip "\0" by default. An issue was due to incorrectly taking size of default strip characters set. --- py/objstr.c | 2 +- tests/basics/string_strip.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'py') diff --git a/py/objstr.c b/py/objstr.c index f6214f80c..11bfb41fc 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -777,7 +777,7 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { if (n_args == 1) { chars_to_del = whitespace; - chars_to_del_len = sizeof(whitespace); + chars_to_del_len = sizeof(whitespace) - 1; } else { if (mp_obj_get_type(args[1]) != self_type) { bad_implicit_conversion(args[1]); diff --git a/tests/basics/string_strip.py b/tests/basics/string_strip.py index 5d99a78e5..971a4aae5 100644 --- a/tests/basics/string_strip.py +++ b/tests/basics/string_strip.py @@ -32,6 +32,13 @@ print("a ".strip()) print("a ".lstrip()) print("a ".rstrip()) +# \0 used to give a problem + +print("\0abc\0".strip()) +print("\0abc\0".lstrip()) +print("\0abc\0".rstrip()) +print("\0abc\0".strip("\0")) + # Test that stripping unstrippable string returns original object s = "abc" print(id(s.strip()) == id(s)) -- cgit v1.2.3 From 96fd80db1306ed67ee967b888c1c03c136bff4fb Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 21 Sep 2017 15:24:57 +1000 Subject: py/objexcept: Prevent infinite recursion when allocating exceptions. The aim of this patch is to rewrite the functions that create exception instances (mp_obj_exception_make_new and mp_obj_new_exception_msg_varg) so that they do not call any functions that may raise an exception. Otherwise it's possible to create infinite recursion with an exception being raised while trying to create an exception object. The two main things that are done to accomplish this are: 1. Change mp_obj_new_exception_msg_varg to just format the string, then call mp_obj_exception_make_new to actually create the exception object. 2. In mp_obj_exception_make_new and mp_obj_new_exception_msg_varg try to allocate all memory first using functions that don't raise exceptions If any of the memory allocations fail (return NULL) then degrade gracefully by trying other options for memory allocation, eg using the emergency exception buffer. 3. Use a custom printer backend to conservatively format strings: if it can't allocate memory then it just truncates the string. As part of this rewrite, raising an exception without a message, like KeyError(123), will now use the emergency buffer to store the arg and traceback data if there is no heap memory available. Memory use with this patch is unchanged. Code size is increased by: bare-arm: +136 minimal x86: +124 unix x64: +72 unix nanbox: +96 stm32: +88 esp8266: +92 cc3200: +80 --- py/objexcept.c | 243 +++++++++++++++++++++++++-------------- tests/micropython/emg_exc.py | 16 ++- tests/micropython/emg_exc.py.exp | 5 +- tests/run-tests | 1 + 4 files changed, 176 insertions(+), 89 deletions(-) (limited to 'py') diff --git a/py/objexcept.c b/py/objexcept.c index a9fe04094..0a03df9d0 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -38,6 +38,12 @@ #include "py/gc.h" #include "py/mperrno.h" +// Number of items per traceback entry (file, line, block) +#define TRACEBACK_ENTRY_LEN (3) + +// Number of traceback entries to reserve in the emergency exception buffer +#define EMG_TRACEBACK_ALLOC (2 * TRACEBACK_ENTRY_LEN) + // Instance of MemoryError exception - needed by mp_malloc_fail const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; @@ -127,18 +133,51 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false); - mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); - if (o == NULL) { - // Couldn't allocate heap memory; use local data instead. - o = &MP_STATE_VM(mp_emergency_exception_obj); - // We can't store any args. - o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; + + // Try to allocate memory for the exception, with fallback to emergency exception object + mp_obj_exception_t *o_exc = m_new_obj_maybe(mp_obj_exception_t); + if (o_exc == NULL) { + o_exc = &MP_STATE_VM(mp_emergency_exception_obj); + } + + // Populate the exception object + o_exc->base.type = type; + o_exc->traceback_data = NULL; + + mp_obj_tuple_t *o_tuple; + if (n_args == 0) { + // No args, can use the empty tuple straightaway + o_tuple = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; } else { - o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_args, args)); + // Try to allocate memory for the tuple containing the args + o_tuple = m_new_obj_var_maybe(mp_obj_tuple_t, mp_obj_t, n_args); + + #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF + // If we are called by mp_obj_new_exception_msg_varg then it will have + // reserved room (after the traceback data) for a tuple with 1 element. + // Otherwise we are free to use the whole buffer after the traceback data. + if (o_tuple == NULL && mp_emergency_exception_buf_size >= + EMG_TRACEBACK_ALLOC * sizeof(size_t) + sizeof(mp_obj_tuple_t) + n_args * sizeof(mp_obj_t)) { + o_tuple = (mp_obj_tuple_t*) + ((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + EMG_TRACEBACK_ALLOC * sizeof(size_t)); + } + #endif + + if (o_tuple == NULL) { + // No memory for a tuple, fallback to an empty tuple + o_tuple = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; + } else { + // Have memory for a tuple so populate it + o_tuple->base.type = &mp_type_tuple; + o_tuple->len = n_args; + memcpy(o_tuple->items, args, n_args * sizeof(mp_obj_t)); + } } - o->base.type = type; - o->traceback_data = NULL; - return MP_OBJ_FROM_PTR(o); + + // Store the tuple of args in the exception object + o_exc->args = o_tuple; + + return MP_OBJ_FROM_PTR(o_exc); } // Get exception "value" - that is, first argument, or None @@ -306,87 +345,95 @@ mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg return mp_obj_new_exception_msg_varg(exc_type, msg); } -mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { - // check that the given type is an exception type - assert(exc_type->make_new == mp_obj_exception_make_new); - - // make exception object - mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); - if (o == NULL) { - // Couldn't allocate heap memory; use local data instead. - // Unfortunately, we won't be able to format the string... - o = &MP_STATE_VM(mp_emergency_exception_obj); - o->base.type = exc_type; - o->traceback_data = NULL; - o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; - -#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF - // If the user has provided a buffer, then we try to create a tuple - // of length 1, which has a string object and the string data. +// The following struct and function implement a simple printer that conservatively +// allocates memory and truncates the output data if no more memory can be obtained. +// It leaves room for a null byte at the end of the buffer. - if (mp_emergency_exception_buf_size > (sizeof(mp_obj_tuple_t) + sizeof(mp_obj_str_t) + sizeof(mp_obj_t))) { - mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)MP_STATE_VM(mp_emergency_exception_buf); - mp_obj_str_t *str = (mp_obj_str_t *)&tuple->items[1]; - - tuple->base.type = &mp_type_tuple; - tuple->len = 1; - tuple->items[0] = MP_OBJ_FROM_PTR(str); - - byte *str_data = (byte *)&str[1]; - size_t max_len = (byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - - str_data; +struct _exc_printer_t { + bool allow_realloc; + size_t alloc; + size_t len; + byte *buf; +}; - vstr_t vstr; - vstr_init_fixed_buf(&vstr, max_len, (char *)str_data); +STATIC void exc_add_strn(void *data, const char *str, size_t len) { + struct _exc_printer_t *pr = data; + if (pr->len + len >= pr->alloc) { + // Not enough room for data plus a null byte so try to grow the buffer + if (pr->allow_realloc) { + size_t new_alloc = pr->alloc + len + 16; + byte *new_buf = m_renew_maybe(byte, pr->buf, pr->alloc, new_alloc, true); + if (new_buf == NULL) { + pr->allow_realloc = false; + len = pr->alloc - pr->len - 1; + } else { + pr->alloc = new_alloc; + pr->buf = new_buf; + } + } else { + len = pr->alloc - pr->len - 1; + } + } + memcpy(pr->buf + pr->len, str, len); + pr->len += len; +} - va_list ap; - va_start(ap, fmt); - vstr_vprintf(&vstr, fmt, ap); - va_end(ap); +mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { + assert(fmt != NULL); - str->base.type = &mp_type_str; - str->hash = qstr_compute_hash(str_data, str->len); - str->len = vstr.len; - str->data = str_data; + // Check that the given type is an exception type + assert(exc_type->make_new == mp_obj_exception_make_new); - o->args = tuple; + // Try to allocate memory for the message + mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); + size_t o_str_alloc = strlen(fmt) + 1; + byte *o_str_buf = m_new_maybe(byte, o_str_alloc); + + bool used_emg_buf = false; + #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF + // If memory allocation failed and there is an emergency buffer then try to use + // that buffer to store the string object and its data (at least 16 bytes for + // the string data), reserving room at the start for the traceback and 1-tuple. + if ((o_str == NULL || o_str_buf == NULL) + && mp_emergency_exception_buf_size >= EMG_TRACEBACK_ALLOC * sizeof(size_t) + + sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t) + sizeof(mp_obj_str_t) + 16) { + used_emg_buf = true; + o_str = (mp_obj_str_t*)((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + + EMG_TRACEBACK_ALLOC * sizeof(size_t) + sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t)); + o_str_buf = (byte*)&o_str[1]; + o_str_alloc = (uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + + mp_emergency_exception_buf_size - o_str_buf; + } + #endif - size_t offset = &str_data[str->len] - (byte*)MP_STATE_VM(mp_emergency_exception_buf); - offset += sizeof(void *) - 1; - offset &= ~(sizeof(void *) - 1); + if (o_str == NULL) { + // No memory for the string object so create the exception with no args + return mp_obj_exception_make_new(exc_type, 0, 0, NULL); + } - if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) { - // We have room to store some traceback. - o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset); - o->traceback_alloc = ((byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]); - o->traceback_len = 0; - } - } -#endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF + if (o_str_buf == NULL) { + // No memory for the string buffer: assume that the fmt string is in ROM + // and use that data as the data of the string + o_str->len = o_str_alloc - 1; // will be equal to strlen(fmt) + o_str->data = (const byte*)fmt; } else { - o->base.type = exc_type; - o->traceback_data = NULL; - o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(1, NULL)); - - assert(fmt != NULL); - { - if (strchr(fmt, '%') == NULL) { - // no formatting substitutions, avoid allocating vstr. - o->args->items[0] = mp_obj_new_str(fmt, strlen(fmt), false); - } else { - // render exception message and store as .args[0] - va_list ap; - vstr_t vstr; - vstr_init(&vstr, 16); - va_start(ap, fmt); - vstr_vprintf(&vstr, fmt, ap); - va_end(ap); - o->args->items[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); - } - } + // We have some memory to format the string + struct _exc_printer_t exc_pr = {!used_emg_buf, o_str_alloc, 0, o_str_buf}; + mp_print_t print = {&exc_pr, exc_add_strn}; + va_list ap; + va_start(ap, fmt); + mp_vprintf(&print, fmt, ap); + va_end(ap); + exc_pr.buf[exc_pr.len] = '\0'; + o_str->len = exc_pr.len; + o_str->data = exc_pr.buf; } - return MP_OBJ_FROM_PTR(o); + // Create the string object and call mp_obj_exception_make_new to create the exception + o_str->base.type = &mp_type_str; + o_str->hash = qstr_compute_hash(o_str->data, o_str->len); + mp_obj_t arg = MP_OBJ_FROM_PTR(o_str); + return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } // return true if the given object is an exception type @@ -443,24 +490,46 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qs // if memory allocation fails (eg because gc is locked), just return if (self->traceback_data == NULL) { - self->traceback_data = m_new_maybe(size_t, 3); + self->traceback_data = m_new_maybe(size_t, TRACEBACK_ENTRY_LEN); if (self->traceback_data == NULL) { + #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF + if (mp_emergency_exception_buf_size >= EMG_TRACEBACK_ALLOC * sizeof(size_t)) { + // There is room in the emergency buffer for traceback data + size_t *tb = (size_t*)MP_STATE_VM(mp_emergency_exception_buf); + self->traceback_data = tb; + self->traceback_alloc = EMG_TRACEBACK_ALLOC; + } else { + // Can't allocate and no room in emergency buffer + return; + } + #else + // Can't allocate return; + #endif + } else { + // Allocated the traceback data on the heap + self->traceback_alloc = TRACEBACK_ENTRY_LEN; } - self->traceback_alloc = 3; self->traceback_len = 0; - } else if (self->traceback_len + 3 > self->traceback_alloc) { + } else if (self->traceback_len + TRACEBACK_ENTRY_LEN > self->traceback_alloc) { + #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF + if (self->traceback_data == (size_t*)MP_STATE_VM(mp_emergency_exception_buf)) { + // Can't resize the emergency buffer + return; + } + #endif // be conservative with growing traceback data - size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc, self->traceback_alloc + 3, true); + size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc, + self->traceback_alloc + TRACEBACK_ENTRY_LEN, true); if (tb_data == NULL) { return; } self->traceback_data = tb_data; - self->traceback_alloc += 3; + self->traceback_alloc += TRACEBACK_ENTRY_LEN; } size_t *tb_data = &self->traceback_data[self->traceback_len]; - self->traceback_len += 3; + self->traceback_len += TRACEBACK_ENTRY_LEN; tb_data[0] = file; tb_data[1] = line; tb_data[2] = block; diff --git a/tests/micropython/emg_exc.py b/tests/micropython/emg_exc.py index d228e6faa..4a9fa18bc 100644 --- a/tests/micropython/emg_exc.py +++ b/tests/micropython/emg_exc.py @@ -2,6 +2,11 @@ import micropython import sys +try: + import uio +except ImportError: + print("SKIP") + raise SystemExit # some ports need to allocate heap for the emg exc try: @@ -14,7 +19,16 @@ def f(): try: raise ValueError(1) except ValueError as er: - sys.print_exception(er) + exc = er micropython.heap_unlock() + # print the exception + buf = uio.StringIO() + sys.print_exception(exc, buf) + for l in buf.getvalue().split("\n"): + if l.startswith(" File "): + print(l.split('"')[2]) + else: + print(l) + f() diff --git a/tests/micropython/emg_exc.py.exp b/tests/micropython/emg_exc.py.exp index 82b10b5f5..fd2cfb272 100644 --- a/tests/micropython/emg_exc.py.exp +++ b/tests/micropython/emg_exc.py.exp @@ -1 +1,4 @@ -ValueError: +Traceback (most recent call last): +, line 20, in f +ValueError: 1 + diff --git a/tests/run-tests b/tests/run-tests index 866a9b7c3..568d99f8e 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -345,6 +345,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_tests.add('misc/rge_sm.py') # requires yield skip_tests.add('misc/print_exception.py') # because native doesn't have proper traceback info skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native + skip_tests.add('micropython/emg_exc.py') # because native doesn't have proper traceback info skip_tests.add('micropython/heapalloc_traceback.py') # because native doesn't have proper traceback info skip_tests.add('micropython/heapalloc_iter.py') # requires generators skip_tests.add('micropython/schedule.py') # native code doesn't check pending events -- cgit v1.2.3 From 7885a425d78a5a2fa7da5099cdd547a35f5e69dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Aug 2017 21:42:39 +1000 Subject: py/stream: Remove unnecessary checks for NULL return from vstr_add_len. The vstr argument to the calls to vstr_add_len are dynamically allocated (ie fixed_buf=false) and so vstr_add_len will never return NULL. So there's no need to check for it. Any out-of-memory errors are raised by the call to m_renew in vstr_ensure_extra. --- py/stream.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'py') diff --git a/py/stream.c b/py/stream.c index 0029a59a7..0adf0af06 100644 --- a/py/stream.c +++ b/py/stream.c @@ -141,9 +141,6 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl mp_uint_t last_buf_offset = 0; while (more_bytes > 0) { char *p = vstr_add_len(&vstr, more_bytes); - if (p == NULL) { - mp_raise_msg(&mp_type_MemoryError, "out of memory"); - } int error; mp_uint_t out_sz = mp_stream_read_exactly(args[0], p, more_bytes, &error); if (error != 0) { @@ -380,10 +377,6 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) while (max_size == -1 || max_size-- != 0) { char *p = vstr_add_len(&vstr, 1); - if (p == NULL) { - mp_raise_msg(&mp_type_MemoryError, "out of memory"); - } - int error; mp_uint_t out_sz = stream_p->read(args[0], p, 1, &error); if (out_sz == MP_STREAM_ERROR) { -- cgit v1.2.3 From ede8a0235b47333aaaa8d03a3b9e20b014be3808 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Sep 2017 08:05:24 +1000 Subject: py/vstr: Raise a RuntimeError if fixed vstr buffer overflows. Current users of fixed vstr buffers (building file paths) assume that there is no overflow and do not check for overflow after building the vstr. This has the potential to lead to NULL pointer dereferences (when vstr_null_terminated_str returns NULL because it can't allocate RAM for the terminating byte) and stat'ing and loading invalid path names (due to the path being truncated). The safest and simplest thing to do in these cases is just raise an exception if a write goes beyond the end of a fixed vstr buffer, which is what this patch does. It also simplifies the vstr code. --- ports/unix/coverage.c | 17 ++++++++++-- py/vstr.c | 59 ++++++++++------------------------------ tests/unix/extra_coverage.py.exp | 3 +- 3 files changed, 31 insertions(+), 48 deletions(-) (limited to 'py') diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 4a9ab194b..651db0a94 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -181,8 +181,21 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); VSTR_FIXED(fix, 4); - vstr_add_str(&fix, "large"); - mp_printf(&mp_plat_print, "%.*s\n", (int)fix.len, fix.buf); + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + vstr_add_str(&fix, "large"); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + + fix.len = fix.alloc; + if (nlr_push(&nlr) == 0) { + vstr_null_terminated_str(&fix); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } } // repl autocomplete diff --git a/py/vstr.c b/py/vstr.c index 8a00f6c6f..869b27805 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -30,7 +30,7 @@ #include #include "py/mpconfig.h" -#include "py/misc.h" +#include "py/runtime.h" #include "py/mpprint.h" // returned value is always at least 1 greater than argument @@ -92,7 +92,9 @@ void vstr_free(vstr_t *vstr) { // Extend vstr strictly by requested size, return pointer to newly added chunk. char *vstr_extend(vstr_t *vstr, size_t size) { if (vstr->fixed_buf) { - return NULL; + // We can't reallocate, and the caller is expecting the space to + // be there, so the only safe option is to raise an exception. + mp_raise_msg(&mp_type_RuntimeError, NULL); } char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size); char *p = new_buf + vstr->alloc; @@ -101,17 +103,18 @@ char *vstr_extend(vstr_t *vstr, size_t size) { return p; } -STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { +STATIC void vstr_ensure_extra(vstr_t *vstr, size_t size) { if (vstr->len + size > vstr->alloc) { if (vstr->fixed_buf) { - return false; + // We can't reallocate, and the caller is expecting the space to + // be there, so the only safe option is to raise an exception. + mp_raise_msg(&mp_type_RuntimeError, NULL); } size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16); char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc); vstr->alloc = new_alloc; vstr->buf = new_buf; } - return true; } void vstr_hint_size(vstr_t *vstr, size_t size) { @@ -119,9 +122,7 @@ void vstr_hint_size(vstr_t *vstr, size_t size) { } char *vstr_add_len(vstr_t *vstr, size_t len) { - if (!vstr_ensure_extra(vstr, len)) { - return NULL; - } + vstr_ensure_extra(vstr, len); char *buf = vstr->buf + vstr->len; vstr->len += len; return buf; @@ -131,9 +132,7 @@ char *vstr_add_len(vstr_t *vstr, size_t len) { char *vstr_null_terminated_str(vstr_t *vstr) { // If there's no more room, add single byte if (vstr->alloc == vstr->len) { - if (vstr_extend(vstr, 1) == NULL) { - return NULL; - } + vstr_extend(vstr, 1); } vstr->buf[vstr->len] = '\0'; return vstr->buf; @@ -141,9 +140,6 @@ char *vstr_null_terminated_str(vstr_t *vstr) { void vstr_add_byte(vstr_t *vstr, byte b) { byte *buf = (byte*)vstr_add_len(vstr, 1); - if (buf == NULL) { - return; - } buf[0] = b; } @@ -153,31 +149,19 @@ void vstr_add_char(vstr_t *vstr, unichar c) { // Is it worth just calling vstr_add_len(vstr, 4)? if (c < 0x80) { byte *buf = (byte*)vstr_add_len(vstr, 1); - if (buf == NULL) { - return; - } *buf = (byte)c; } else if (c < 0x800) { byte *buf = (byte*)vstr_add_len(vstr, 2); - if (buf == NULL) { - return; - } buf[0] = (c >> 6) | 0xC0; buf[1] = (c & 0x3F) | 0x80; } else if (c < 0x10000) { byte *buf = (byte*)vstr_add_len(vstr, 3); - if (buf == NULL) { - return; - } buf[0] = (c >> 12) | 0xE0; buf[1] = ((c >> 6) & 0x3F) | 0x80; buf[2] = (c & 0x3F) | 0x80; } else { assert(c < 0x110000); byte *buf = (byte*)vstr_add_len(vstr, 4); - if (buf == NULL) { - return; - } buf[0] = (c >> 18) | 0xF0; buf[1] = ((c >> 12) & 0x3F) | 0x80; buf[2] = ((c >> 6) & 0x3F) | 0x80; @@ -193,16 +177,7 @@ void vstr_add_str(vstr_t *vstr, const char *str) { } void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) { - if (!vstr_ensure_extra(vstr, len)) { - // if buf is fixed, we got here because there isn't enough room left - // so just try to copy as much as we can, with room for a possible null byte - if (vstr->fixed_buf && vstr->len < vstr->alloc) { - len = vstr->alloc - vstr->len; - goto copy; - } - return; - } -copy: + vstr_ensure_extra(vstr, len); memmove(vstr->buf + vstr->len, str, len); vstr->len += len; } @@ -214,9 +189,7 @@ STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len } if (byte_len > 0) { // ensure room for the new bytes - if (!vstr_ensure_extra(vstr, byte_len)) { - return NULL; - } + vstr_ensure_extra(vstr, byte_len); // copy up the string to make room for the new bytes memmove(vstr->buf + byte_pos + byte_len, vstr->buf + byte_pos, l - byte_pos); // increase the length @@ -227,17 +200,13 @@ STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b) { char *s = vstr_ins_blank_bytes(vstr, byte_pos, 1); - if (s != NULL) { - *s = b; - } + *s = b; } void vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr) { // TODO UNICODE char *s = vstr_ins_blank_bytes(vstr, char_pos, 1); - if (s != NULL) { - *s = chr; - } + *s = chr; } void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) { diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 4dc421dab..4c4f66663 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -18,7 +18,8 @@ sts test tes -larg +RuntimeError: +RuntimeError: # repl ame__ -- cgit v1.2.3 From e2ba45c35fa9f5e84f79e8e220a9a7d43a94ff7f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Sep 2017 11:28:45 +1000 Subject: py/vm: Use lowercase letter at start of exception message. For consistency with all the other exception messages. --- py/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/vm.c b/py/vm.c index c7fc83d04..9a27b2b22 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1124,7 +1124,7 @@ unwind_return: } } if (obj == MP_OBJ_NULL) { - obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise"); + obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "no active exception to reraise"); RAISE(obj); } } else { -- cgit v1.2.3 From 8edc2e4b141ffad74754686fbdc66e033ff24f34 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Sep 2017 11:54:08 +1000 Subject: py/runtime0: Add comments about unary/binary-op enums used in bytecode. --- py/runtime0.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'py') diff --git a/py/runtime0.h b/py/runtime0.h index 54bf192d3..6d77cce68 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -42,6 +42,8 @@ #define MP_NATIVE_TYPE_PTR16 (0x06) #define MP_NATIVE_TYPE_PTR32 (0x07) +// Note: the first 7 of these are used in bytecode and changing +// them requires changing the bytecode version. typedef enum { MP_UNARY_OP_BOOL, // __bool__ MP_UNARY_OP_LEN, // __len__ @@ -54,6 +56,8 @@ typedef enum { MP_UNARY_OP_SIZEOF, // for sys.getsizeof() } mp_unary_op_t; +// Note: the first 35 of these are used in bytecode and changing +// them requires changing the bytecode version. typedef enum { // Relational operations, should return a bool MP_BINARY_OP_LESS, -- cgit v1.2.3 From f008263022f794c056d8d102deaa62760822761a Mon Sep 17 00:00:00 2001 From: Anton Patrushev Date: Fri, 22 Sep 2017 22:44:09 +0500 Subject: py/persistentcode: Define mp_raw_code_save_file() for any unix target. A unix target should provide POSIX open/write/close functions regardless of its machine architecture. Fixes issue #3325. --- py/persistentcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/persistentcode.c b/py/persistentcode.c index 2fa8c1df0..f954038ae 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -374,7 +374,7 @@ void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) { // here we define mp_raw_code_save_file depending on the port // TODO abstract this away properly -#if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__))) +#if defined(__i386__) || defined(__x86_64__) || defined(__unix__) #include #include -- cgit v1.2.3 From 9d836fedbdb1d28bdfc4ba475bbdfc1adb3f007a Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 25 Sep 2017 16:35:19 -0700 Subject: py: Clarify which mp_unary_op_t's may appear in the bytecode. Not all can, so we don't need to reserve bytecodes for them, and can use free slots for something else later. --- py/bc0.h | 2 +- py/runtime0.h | 14 +++++++++----- py/showbc.c | 2 +- py/vmentrytable.h | 2 +- tests/cmdline/cmd_showbc.py.exp | 6 +++--- 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'py') diff --git a/py/bc0.h b/py/bc0.h index f671c5b5a..38e23c0fd 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -113,7 +113,7 @@ #define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64) #define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16) #define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16) -#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(7) +#define MP_BC_UNARY_OP_MULTI (0xd0) // + op( Date: Sun, 24 Sep 2017 20:15:48 -0500 Subject: py: Add config option to print warnings/errors to stderr. This adds a new configuration option to print runtime warnings and errors to stderr. On Unix, CPython prints warnings and unhandled exceptions to stderr, so the unix port here is configured to use this option. The unix port already printed unhandled exceptions on the main thread to stderr. This patch fixes unhandled exceptions on other threads and warnings (issue #2838) not printing on stderr. Additionally, a couple tests needed to be fixed to handle this new behavior. This is done by also capturing stderr when running tests. --- ports/unix/mpconfigport.h | 3 +++ py/modthread.c | 8 ++++---- py/mpconfig.h | 5 +++++ py/warning.c | 6 +++--- tests/run-tests | 4 ++-- 5 files changed, 17 insertions(+), 9 deletions(-) (limited to 'py') diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index b557f3d44..50b979279 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -145,8 +145,11 @@ // names in exception messages (may require more RAM). #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) #define MICROPY_WARNINGS (1) +#define MICROPY_ERROR_PRINTER (&mp_stderr_print) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) +extern const struct _mp_print_t mp_stderr_print; + // Define to 1 to use undertested inefficient GC helper implementation // (if more efficient arch-specific one is not available). #ifndef MICROPY_GCREGS_SETJMP diff --git a/py/modthread.c b/py/modthread.c index bf74128e8..cb071d0f8 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -192,10 +192,10 @@ STATIC void *thread_entry(void *args_in) { // swallow exception silently } else { // print exception out - mp_printf(&mp_plat_print, "Unhandled exception in thread started by "); - mp_obj_print_helper(&mp_plat_print, args->fun, PRINT_REPR); - mp_printf(&mp_plat_print, "\n"); - mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(exc)); + mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in thread started by "); + mp_obj_print_helper(MICROPY_ERROR_PRINTER, args->fun, PRINT_REPR); + mp_printf(MICROPY_ERROR_PRINTER, "\n"); + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(exc)); } } diff --git a/py/mpconfig.h b/py/mpconfig.h index b93f851d6..44de3beeb 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -533,6 +533,11 @@ typedef long long mp_longint_impl_t; #define MICROPY_WARNINGS (0) #endif +// This macro is used when printing runtime warnings and errors +#ifndef MICROPY_ERROR_PRINTER +#define MICROPY_ERROR_PRINTER (&mp_plat_print) +#endif + // Float and complex implementation #define MICROPY_FLOAT_IMPL_NONE (0) #define MICROPY_FLOAT_IMPL_FLOAT (1) diff --git a/py/warning.c b/py/warning.c index 46b31ecca..12d0f9c99 100644 --- a/py/warning.c +++ b/py/warning.c @@ -35,9 +35,9 @@ void mp_warning(const char *msg, ...) { va_list args; va_start(args, msg); - mp_print_str(&mp_plat_print, "Warning: "); - mp_vprintf(&mp_plat_print, msg, args); - mp_print_str(&mp_plat_print, "\n"); + mp_print_str(MICROPY_ERROR_PRINTER, "Warning: "); + mp_vprintf(MICROPY_ERROR_PRINTER, msg, args); + mp_print_str(MICROPY_ERROR_PRINTER, "\n"); va_end(args); } diff --git a/tests/run-tests b/tests/run-tests index 568d99f8e..23fc3d910 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -103,7 +103,7 @@ def run_micropython(pyb, args, test_file, is_special=False): os.close(master) os.close(slave) else: - output_mupy = subprocess.check_output(args + [test_file]) + output_mupy = subprocess.check_output(args + [test_file], stderr=subprocess.STDOUT) except subprocess.CalledProcessError: return b'CRASH' @@ -124,7 +124,7 @@ def run_micropython(pyb, args, test_file, is_special=False): # run the actual test try: - output_mupy = subprocess.check_output(cmdlist) + output_mupy = subprocess.check_output(cmdlist, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: output_mupy = b'CRASH' -- cgit v1.2.3 From bdc6e86e079dd8a82e9ead1d4041c2e17c882437 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 26 Sep 2017 12:57:51 +1000 Subject: py/objfloat: Support raising a negative number to a fractional power. This returns a complex number, following CPython behaviour. For ports that don't have complex numbers enabled this will raise a ValueError which gives a fail-safe for scripts that were written assuming complex numbers exist. --- py/objfloat.c | 7 +++++++ tests/float/complex1.py | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'py') diff --git a/py/objfloat.c b/py/objfloat.c index 55a9379ff..0831be3fd 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -298,6 +298,13 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t if (lhs_val == 0 && rhs_val < 0) { goto zero_division_error; } + if (lhs_val < 0 && rhs_val != MICROPY_FLOAT_C_FUN(floor)(rhs_val)) { + #if MICROPY_PY_BUILTINS_COMPLEX + return mp_obj_complex_binary_op(MP_BINARY_OP_POWER, lhs_val, 0, rhs_in); + #else + mp_raise_ValueError("complex values not supported"); + #endif + } lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val); break; case MP_BINARY_OP_DIVMOD: { diff --git a/tests/float/complex1.py b/tests/float/complex1.py index 7f0b317b3..854410545 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -53,6 +53,10 @@ print(type(hash(1j))) # float on lhs should delegate to complex print(1.2 + 3j) +# negative base and fractional power should create a complex +ans = (-1) ** 2.3; print("%.5g %.5g" % (ans.real, ans.imag)) +ans = (-1.2) ** -3.4; print("%.5g %.5g" % (ans.real, ans.imag)) + # check printing of inf/nan print(float('nan') * 1j) print(float('inf') * (1 + 1j)) -- cgit v1.2.3 From 01978648fdc317c13b17ba186c82df4fb8a5cbac Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 3 Oct 2017 17:26:45 +1100 Subject: py/objset: Simplify set and frozenset by separating their locals dicts. A lot of set's methods (the mutable ones) are not allowed to operate on a frozenset, and giving frozenset a separate locals dict with only the methods that it supports allows to simplify the logic that verifies if args are a set or a frozenset. Even though the new frozenset locals dict is relatively large (88 bytes on 32-bit archs) there is a much bigger saving coming from the removal of a const string for an error message, along with the removal of some checks for set or frozenset type. Changes in code size due to this patch are (for ports that changed at all): unix x64: -56 unix nanbox: -304 stm32: -64 esp8266: -124 cc3200: -40 Apart from the reduced code, frozenset now has better tab-completion because it only lists the valid methods. And the error message for accessing an invalid method is now more detailed (it includes the method name that wasn't found). --- py/objset.c | 71 ++++++++++++++++++++++++++----------------------------------- 1 file changed, 30 insertions(+), 41 deletions(-) (limited to 'py') diff --git a/py/objset.c b/py/objset.c index d4a8a1a39..6dede887c 100644 --- a/py/objset.c +++ b/py/objset.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -57,23 +57,13 @@ STATIC bool is_set_or_frozenset(mp_obj_t o) { ; } +// This macro is shorthand for mp_check_self to verify the argument is a set. +#define check_set(o) mp_check_self(MP_OBJ_IS_TYPE(o, &mp_type_set)) + // This macro is shorthand for mp_check_self to verify the argument is a // set or frozenset for methods that operate on both of these types. #define check_set_or_frozenset(o) mp_check_self(is_set_or_frozenset(o)) -// This function is used to verify the argument for methods that modify -// the set object, and raises an exception if the arg is a frozenset. -STATIC void check_set(mp_obj_t o) { - #if MICROPY_PY_BUILTINS_FROZENSET - if (MP_OBJ_IS_TYPE(o, &mp_type_frozenset)) { - // Mutable method called on frozenset; emulate CPython behavior, eg: - // AttributeError: 'frozenset' object has no attribute 'add' - mp_raise_msg(&mp_type_AttributeError, "'frozenset' has no such attribute"); - } - #endif - mp_check_self(MP_OBJ_IS_TYPE(o, &mp_type_set)); -} - STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); @@ -188,26 +178,16 @@ STATIC mp_obj_t set_clear(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear); -STATIC mp_obj_t set_copy_as_mutable(mp_obj_t self_in) { +STATIC mp_obj_t set_copy(mp_obj_t self_in) { + check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_set_t *other = m_new_obj(mp_obj_set_t); - other->base.type = &mp_type_set; + other->base.type = self->base.type; mp_set_init(&other->set, self->set.alloc); other->set.used = self->set.used; memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t)); - return MP_OBJ_FROM_PTR(other); } - -STATIC mp_obj_t set_copy(mp_obj_t self_in) { - check_set_or_frozenset(self_in); - - mp_obj_t other = set_copy_as_mutable(self_in); - ((mp_obj_base_t*)MP_OBJ_TO_PTR(other))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type; - - return other; -} STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy); STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) { @@ -224,25 +204,23 @@ STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { check_set(args[0]); self = args[0]; } else { - check_set_or_frozenset(args[0]); - self = set_copy_as_mutable(args[0]); + self = set_copy(args[0]); } - for (size_t i = 1; i < n_args; i++) { mp_obj_t other = args[i]; if (self == other) { set_clear(self); } else { + mp_set_t *self_set = &((mp_obj_set_t*)MP_OBJ_TO_PTR(self))->set; mp_obj_t iter = mp_getiter(other, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { - set_discard(self, next); + mp_set_lookup(self_set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND); } } } - ((mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]))->type; return self; } @@ -333,16 +311,16 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool other = MP_OBJ_TO_PTR(set_make_new(&mp_type_set, 1, 0, &other_in)); cleanup_other = true; } - bool out = true; + mp_obj_t out = mp_const_true; if (proper && self->set.used == other->set.used) { - out = false; + out = mp_const_false; } else { mp_obj_iter_buf_t iter_buf; mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self), &iter_buf); mp_obj_t next; while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) { - out = false; + out = mp_const_false; break; } } @@ -354,7 +332,7 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool if (cleanup_other) { set_clear(MP_OBJ_FROM_PTR(other)); } - return mp_obj_new_bool(out); + return out; } STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(self_in, other_in, false); @@ -409,7 +387,7 @@ STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove); STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { - check_set(self_in); + check_set_or_frozenset(self_in); // can be frozenset due to call from set_symmetric_difference mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t iter = mp_getiter(other_in, NULL); mp_obj_t next; @@ -421,10 +399,8 @@ STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update); STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) { - check_set_or_frozenset(self_in); - mp_obj_t self_out = set_copy_as_mutable(self_in); + mp_obj_t self_out = set_copy(self_in); set_symmetric_difference_update(self_out, other_in); - ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_out))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type; return self_out; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference); @@ -578,6 +554,19 @@ const mp_obj_type_t mp_type_set = { }; #if MICROPY_PY_BUILTINS_FROZENSET +STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) }, + { MP_ROM_QSTR(MP_QSTR_difference), MP_ROM_PTR(&set_diff_obj) }, + { MP_ROM_QSTR(MP_QSTR_intersection), MP_ROM_PTR(&set_intersect_obj) }, + { MP_ROM_QSTR(MP_QSTR_isdisjoint), MP_ROM_PTR(&set_isdisjoint_obj) }, + { MP_ROM_QSTR(MP_QSTR_issubset), MP_ROM_PTR(&set_issubset_obj) }, + { MP_ROM_QSTR(MP_QSTR_issuperset), MP_ROM_PTR(&set_issuperset_obj) }, + { MP_ROM_QSTR(MP_QSTR_symmetric_difference), MP_ROM_PTR(&set_symmetric_difference_obj) }, + { MP_ROM_QSTR(MP_QSTR_union), MP_ROM_PTR(&set_union_obj) }, + { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); + const mp_obj_type_t mp_type_frozenset = { { &mp_type_type }, .name = MP_QSTR_frozenset, @@ -586,7 +575,7 @@ const mp_obj_type_t mp_type_frozenset = { .unary_op = set_unary_op, .binary_op = set_binary_op, .getiter = set_getiter, - .locals_dict = (mp_obj_dict_t*)&set_locals_dict, + .locals_dict = (mp_obj_dict_t*)&frozenset_locals_dict, }; #endif -- cgit v1.2.3 From 2ac1364688cd3ee313661e82a336663551986fc8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 3 Oct 2017 17:56:27 +1100 Subject: py/objset: Check that RHS of a binary op is a set/frozenset. CPython docs explicitly state that the RHS of a set/frozenset binary op must be a set to prevent user errors. It also preserves commutativity of the ops, eg: "abc" & set() is a TypeError, and so should be set() & "abc". This change actually decreases unix (x64) code by 160 bytes; it increases stm32 by 4 bytes and esp8266 by 28 bytes (but previous patch already introduced a much large saving). --- py/objset.c | 4 ++++ tests/basics/set_binop.py | 12 ++++++++++++ tests/misc/non_compliant.py | 12 ------------ tests/misc/non_compliant.py.exp | 2 -- 4 files changed, 16 insertions(+), 14 deletions(-) (limited to 'py') diff --git a/py/objset.c b/py/objset.c index 6dede887c..80ed26334 100644 --- a/py/objset.c +++ b/py/objset.c @@ -463,6 +463,10 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { #else bool update = true; #endif + if (op != MP_BINARY_OP_IN && !is_set_or_frozenset(rhs)) { + // For all ops except containment the RHS must be a set/frozenset + return MP_OBJ_NULL; + } switch (op) { case MP_BINARY_OP_OR: return set_union(lhs, rhs); diff --git a/tests/basics/set_binop.py b/tests/basics/set_binop.py index 7848920b6..bc76533b1 100644 --- a/tests/basics/set_binop.py +++ b/tests/basics/set_binop.py @@ -47,6 +47,18 @@ s1 = s2 = set('abc') s1 -= set('ad') print(s1 is s2, len(s1)) +# RHS must be a set +try: + print(set('12') >= '1') +except TypeError: + print('TypeError') + +# RHS must be a set +try: + print(set('12') <= '123') +except TypeError: + print('TypeError') + # unsupported operator try: set('abc') * 2 diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index b4c90e9fc..152633c3b 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -39,18 +39,6 @@ try: except NotImplementedError: print('NotImplementedError') -# should raise type error -try: - print(set('12') >= '1') -except TypeError: - print('TypeError') - -# should raise type error -try: - print(set('12') <= '123') -except TypeError: - print('TypeError') - # uPy raises TypeError, shold be ValueError try: '%c' % b'\x01\x02' diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index ba5590acc..9c157fd5b 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -3,8 +3,6 @@ AttributeError TypeError NotImplementedError NotImplementedError -True -True TypeError, ValueError NotImplementedError NotImplementedError -- cgit v1.2.3 From 1394258f378e50966daa1d83053067eeee8ef07d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 3 Oct 2017 18:03:06 +1100 Subject: py/objset: Include the failed key in a KeyError raised from set.remove. --- py/objset.c | 2 +- tests/basics/set_remove.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'py') diff --git a/py/objset.c b/py/objset.c index 80ed26334..aefc26aac 100644 --- a/py/objset.c +++ b/py/objset.c @@ -380,7 +380,7 @@ STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) { - nlr_raise(mp_obj_new_exception(&mp_type_KeyError)); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, item)); } return mp_const_none; } diff --git a/tests/basics/set_remove.py b/tests/basics/set_remove.py index 5627516c4..072723911 100644 --- a/tests/basics/set_remove.py +++ b/tests/basics/set_remove.py @@ -4,8 +4,8 @@ print(s.remove(1)) print(list(s)) try: print(s.remove(1), "!!!") -except KeyError: - pass +except KeyError as er: + print('KeyError', er.args[0]) else: print("failed to raise KeyError") -- cgit v1.2.3 From 3289b9b7a76a1230b6bb631e191a47bfc6c7a8ee Mon Sep 17 00:00:00 2001 From: chrismas9 Date: Sun, 10 Sep 2017 00:51:44 +1000 Subject: py/{mkenv.mk,mkrules.mk}: Append .exe for Windows executable files. Building mpy-cross: this patch adds .exe to the PROG name when building executables for host (eg mpy-cross) on Windows. make clean now removes mpy-cross.exe under Windows. Building MicroPython: this patch sets MPY_CROSS to mpy-cross.exe or mpy-cross so they can coexist and use cygwin or WSL without rebuilding mpy-cross. The dependency in the mpy rule now uses mpy-cross.exe for Windows and mpy-cross for Linux. --- py/mkenv.mk | 6 ++++++ py/mkrules.mk | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'py') diff --git a/py/mkenv.mk b/py/mkenv.mk index b167b2533..8b637e9ac 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -59,7 +59,13 @@ LD += -m32 endif MAKE_FROZEN = $(TOP)/tools/make-frozen.py +# allow mpy-cross (for WSL) and mpy-cross.exe (for cygwin) to coexist +ifeq ($(OS),Windows_NT) +MPY_CROSS = $(TOP)/mpy-cross/mpy-cross.exe +PROG_EXT = .exe +else MPY_CROSS = $(TOP)/mpy-cross/mpy-cross +endif MPY_TOOL = $(TOP)/tools/mpy-tool.py all: diff --git a/py/mkrules.mk b/py/mkrules.mk index 13545eb6f..fd579557f 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -111,7 +111,7 @@ FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' | FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) # to build .mpy files from .py files -$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py $(TOP)/mpy-cross/mpy-cross +$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py $(MPY_CROSS) @$(ECHO) "MPY $<" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $< @@ -133,13 +133,13 @@ $(PROG): $(OBJ) # we may want to compile using Thumb, but link with non-Thumb libc. $(Q)$(CC) -o $@ $^ $(LIB) $(LDFLAGS) ifndef DEBUG - $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG) + $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)$(PROG_EXT) endif - $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG) + $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG)$(PROG_EXT) clean: clean-prog clean-prog: - $(RM) -f $(PROG) + $(RM) -f $(PROG)$(PROG_EXT) $(RM) -f $(PROG).map .PHONY: clean-prog -- cgit v1.2.3 From 6c82cfc089466f0b3f4b61c81baee1cabece1eaa Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Oct 2017 11:31:05 +1100 Subject: py/objtype: Change type of enum-to-qstr table to uint16_t to save space. Qstr values fit in 16-bits (and this fact is used elsewhere in the code) so no need to use more than that for the large lookup tables. The compiler will anyway give a warning if the qstr values don't fit in 16 bits. Saves around 80 bytes of code space for Thumb2 archs. --- py/objtype.c | 4 ++-- py/runtime.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'py') diff --git a/py/objtype.c b/py/objtype.c index cf9311d5c..033765a47 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -334,7 +334,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size return MP_OBJ_FROM_PTR(o); } -const qstr mp_unary_op_method_name[] = { +const uint16_t mp_unary_op_method_name[] = { [MP_UNARY_OP_BOOL] = MP_QSTR___bool__, [MP_UNARY_OP_LEN] = MP_QSTR___len__, [MP_UNARY_OP_HASH] = MP_QSTR___hash__, @@ -408,7 +408,7 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -const qstr mp_binary_op_method_name[] = { +const uint16_t mp_binary_op_method_name[] = { /* MP_BINARY_OP_OR, MP_BINARY_OP_XOR, diff --git a/py/runtime.h b/py/runtime.h index bbdd7647e..da12f8f04 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -57,9 +57,9 @@ typedef struct _mp_arg_t { mp_arg_val_t defval; } mp_arg_t; -// defined in objtype.c -extern const qstr mp_unary_op_method_name[]; -extern const qstr mp_binary_op_method_name[]; +// Tables mapping operator enums to qstrs, defined in objtype.c +extern const uint16_t mp_unary_op_method_name[]; +extern const uint16_t mp_binary_op_method_name[]; void mp_init(void); void mp_deinit(void); -- cgit v1.2.3 From a3dc1b1957d2c96d7c60c2c629c95077b03488a1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Oct 2017 12:37:50 +1100 Subject: all: Remove inclusion of internal py header files. Header files that are considered internal to the py core and should not normally be included directly are: py/nlr.h - internal nlr configuration and declarations py/bc0.h - contains bytecode macro definitions py/runtime0.h - contains basic runtime enums Instead, the top-level header files to include are one of: py/obj.h - includes runtime0.h and defines everything to use the mp_obj_t type py/runtime.h - includes mpstate.h and hence nlr.h, obj.h, runtime0.h, and defines everything to use the general runtime support functions Additional, specific headers (eg py/objlist.h) can be included if needed. --- drivers/cc3000/src/ccspi.c | 2 -- extmod/machine_mem.c | 2 +- extmod/modbtree.c | 2 -- extmod/modframebuf.c | 2 -- extmod/modlwip.c | 1 - extmod/modubinascii.c | 1 - extmod/moductypes.c | 1 - extmod/moduhashlib.c | 1 - extmod/moduheapq.c | 2 -- extmod/modujson.c | 1 - extmod/modurandom.c | 1 - extmod/modure.c | 1 - extmod/modussl_axtls.c | 1 - extmod/modussl_mbedtls.c | 2 -- extmod/modutimeq.c | 2 -- extmod/moduzlib.c | 1 - extmod/modwebrepl.c | 2 -- extmod/modwebsocket.c | 2 -- extmod/uos_dupterm.c | 1 - extmod/vfs.c | 1 - extmod/vfs_fat.c | 1 - extmod/vfs_fat_file.c | 1 - extmod/vfs_fat_misc.c | 1 - lib/netutils/netutils.c | 2 -- lib/utils/pyexec.c | 1 - mpy-cross/main.c | 1 - ports/bare-arm/main.c | 1 - ports/cc3200/ftp/ftp.c | 3 +-- ports/cc3200/hal/cc3200_hal.c | 1 - ports/cc3200/misc/mpexception.c | 1 - ports/cc3200/mods/modmachine.c | 1 - ports/cc3200/mods/modnetwork.c | 3 --- ports/cc3200/mods/modubinascii.c | 2 -- ports/cc3200/mods/moduhashlib.c | 1 - ports/cc3200/mods/moduos.c | 2 -- ports/cc3200/mods/pybadc.c | 2 -- ports/cc3200/mods/pybi2c.c | 1 - ports/cc3200/mods/pybpin.c | 3 --- ports/cc3200/mods/pybsleep.c | 1 - ports/cc3200/mods/pybspi.c | 1 - ports/cc3200/mods/pybtimer.c | 3 --- ports/cc3200/mods/pybuart.c | 3 --- ports/cc3200/mpthreadport.c | 2 -- ports/cc3200/util/gccollect.c | 2 -- ports/esp8266/esp_mphal.c | 2 -- ports/esp8266/machine_adc.c | 2 -- ports/esp8266/machine_pin.c | 1 - ports/esp8266/machine_pwm.c | 1 - ports/esp8266/machine_rtc.c | 2 -- ports/esp8266/machine_wdt.c | 2 -- ports/esp8266/main.c | 2 -- ports/esp8266/modnetwork.c | 1 - ports/esp8266/modutime.c | 2 -- ports/minimal/main.c | 1 - ports/qemu-arm/main.c | 2 -- ports/qemu-arm/test_main.c | 2 -- ports/stm32/accel.c | 1 - ports/stm32/adc.c | 1 - ports/stm32/can.c | 1 - ports/stm32/gccollect.c | 1 - ports/stm32/i2c.c | 1 - ports/stm32/irq.c | 1 - ports/stm32/lcd.c | 1 - ports/stm32/led.c | 1 - ports/stm32/modmachine.h | 2 -- ports/stm32/modnetwork.c | 1 - ports/stm32/modnwcc3k.c | 1 - ports/stm32/modnwwiznet5k.c | 1 - ports/stm32/modpyb.c | 2 -- ports/stm32/moduos.c | 1 - ports/stm32/modusocket.c | 1 - ports/stm32/mphalport.c | 1 - ports/stm32/mpthreadport.c | 2 -- ports/stm32/pendsv.c | 1 - ports/stm32/pin.c | 1 - ports/stm32/sdcard.c | 1 - ports/stm32/spi.c | 1 - ports/stm32/stm32_it.c | 1 - ports/stm32/uart.c | 1 - ports/teensy/led.c | 1 - ports/teensy/teensy_hal.c | 1 - ports/teensy/timer.c | 1 - ports/teensy/uart.c | 1 - ports/unix/file.c | 1 - ports/unix/main.c | 2 -- ports/unix/modffi.c | 1 - ports/unix/modjni.c | 2 -- ports/unix/modos.c | 1 - ports/unix/modsocket.c | 1 - ports/unix/mpthreadport.c | 1 - ports/unix/unix_mphal.c | 1 - ports/zephyr/machine_pin.c | 1 - ports/zephyr/main.c | 1 - py/argcheck.c | 1 - py/bc.c | 4 +--- py/bc.h | 1 - py/builtinevex.c | 1 - py/builtinimport.c | 1 - py/emit.h | 1 - py/emitnative.c | 1 - py/gc.c | 2 -- py/lexer.c | 1 - py/map.c | 1 - py/modbuiltins.c | 2 -- py/modmicropython.c | 1 - py/modsys.c | 3 --- py/nativeglue.c | 2 -- py/nlrthumb.c | 1 - py/nlrx64.c | 1 - py/nlrx86.c | 2 -- py/nlrxtensa.c | 1 - py/obj.c | 2 -- py/objarray.c | 2 -- py/objbool.c | 2 -- py/objcomplex.c | 3 --- py/objdict.c | 3 --- py/objexcept.c | 1 - py/objfloat.c | 2 -- py/objfun.c | 2 -- py/objgenerator.c | 2 -- py/objgetitemiter.c | 1 - py/objint.c | 2 -- py/objint_longlong.c | 2 -- py/objint_mpz.c | 2 -- py/objlist.c | 2 -- py/objmodule.c | 2 -- py/objnamedtuple.c | 1 - py/objnone.c | 2 -- py/objpolyiter.c | 1 - py/objproperty.c | 1 - py/objrange.c | 2 -- py/objreversed.c | 1 - py/objset.c | 2 -- py/objsingleton.c | 2 -- py/objslice.c | 2 -- py/objstr.c | 2 -- py/objstringio.c | 1 - py/objstrunicode.c | 2 -- py/objtuple.c | 2 -- py/objtype.c | 2 -- py/parse.c | 2 -- py/persistentcode.c | 1 - py/runtime.c | 3 --- py/runtime.h | 1 - py/runtime_utils.c | 2 -- py/sequence.c | 3 --- py/stackctrl.c | 3 --- py/stream.c | 1 - py/vm.c | 2 -- 149 files changed, 3 insertions(+), 226 deletions(-) (limited to 'py') diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c index 64900efe4..820be809b 100644 --- a/drivers/cc3000/src/ccspi.c +++ b/drivers/cc3000/src/ccspi.c @@ -34,8 +34,6 @@ #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "pin.h" #include "led.h" diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c index af987cb7f..b9f16507c 100644 --- a/extmod/machine_mem.c +++ b/extmod/machine_mem.c @@ -24,8 +24,8 @@ * THE SOFTWARE. */ +#include "py/runtime.h" #include "extmod/machine_mem.h" -#include "py/nlr.h" #if MICROPY_PY_MACHINE diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 5017079da..5c1311532 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -29,9 +29,7 @@ #include // for declaration of global errno variable #include -#include "py/nlr.h" #include "py/runtime.h" -#include "py/runtime0.h" #include "py/stream.h" #if MICROPY_PY_BTREE diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 239302295..20e40d579 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -27,8 +27,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #if MICROPY_PY_FRAMEBUF diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 6b8caa42b..f7e776af9 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -29,7 +29,6 @@ #include #include -#include "py/nlr.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/stream.h" diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c index f15efea0f..8256a50cf 100644 --- a/extmod/modubinascii.c +++ b/extmod/modubinascii.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/binary.h" #include "extmod/modubinascii.h" diff --git a/extmod/moductypes.c b/extmod/moductypes.c index dc03f6de5..c3da083cf 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/binary.h" diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index f3beb3939..3fad69247 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #if MICROPY_PY_UHASHLIB diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c index 4a620bad8..71c15368b 100644 --- a/extmod/moduheapq.c +++ b/extmod/moduheapq.c @@ -24,9 +24,7 @@ * THE SOFTWARE. */ -#include "py/nlr.h" #include "py/objlist.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_UHEAPQ diff --git a/extmod/modujson.c b/extmod/modujson.c index 6c4aa1611..f14682d26 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -26,7 +26,6 @@ #include -#include "py/nlr.h" #include "py/objlist.h" #include "py/objstringio.h" #include "py/parsenum.h" diff --git a/extmod/modurandom.c b/extmod/modurandom.c index 4b63dace4..1512a3fd4 100644 --- a/extmod/modurandom.c +++ b/extmod/modurandom.c @@ -27,7 +27,6 @@ #include #include -//#include "py/nlr.h" #include "py/runtime.h" #if MICROPY_PY_URANDOM diff --git a/extmod/modure.c b/extmod/modure.c index 7e1c24325..78de4706d 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/binary.h" #include "py/objstr.h" diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index b5d2412d2..88a89a23d 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index a65470e16..d7316cb4a 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -31,10 +31,8 @@ #include #include // needed because mp_is_nonblocking_error uses system error codes -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" -#include "py/obj.h" // mbedtls_time_t #include "mbedtls/platform.h" diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index faa589583..94cbd20d2 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -27,9 +27,7 @@ #include -#include "py/nlr.h" #include "py/objlist.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/smallint.h" diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index b446dba73..e9af07370 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index d618f5370..4ff282aac 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -28,8 +28,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/stream.h" #include "py/builtin.h" diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c index 6c6e32c1a..a651164b2 100644 --- a/extmod/modwebsocket.c +++ b/extmod/modwebsocket.c @@ -28,8 +28,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/stream.h" #include "extmod/modwebsocket.h" diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c index 233d145aa..1d6f02dce 100644 --- a/extmod/uos_dupterm.c +++ b/extmod/uos_dupterm.c @@ -27,7 +27,6 @@ #include #include "py/mpconfig.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/objarray.h" diff --git a/extmod/vfs.c b/extmod/vfs.c index 3bdce80db..a1cd8d5f6 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -27,7 +27,6 @@ #include #include -#include "py/runtime0.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/mperrno.h" diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index b27054111..22346bdf1 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -33,7 +33,6 @@ #endif #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 8fb48f01a..1fcbb253d 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -29,7 +29,6 @@ #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" diff --git a/extmod/vfs_fat_misc.c b/extmod/vfs_fat_misc.c index 7c16db7e5..9a26b4a2f 100644 --- a/extmod/vfs_fat_misc.c +++ b/extmod/vfs_fat_misc.c @@ -28,7 +28,6 @@ #if MICROPY_VFS_FAT #include -#include "py/nlr.h" #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" diff --git a/lib/netutils/netutils.c b/lib/netutils/netutils.c index 15e70397c..06c3ff9b0 100644 --- a/lib/netutils/netutils.c +++ b/lib/netutils/netutils.c @@ -29,8 +29,6 @@ #include #include -#include "py/obj.h" -#include "py/nlr.h" #include "py/runtime.h" #include "lib/netutils/netutils.h" diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index d3500b42b..1e99aa649 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -29,7 +29,6 @@ #include #include -#include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 225bc4309..d819f74f1 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -29,7 +29,6 @@ #include #include -#include "py/mpstate.h" #include "py/compile.h" #include "py/persistentcode.h" #include "py/runtime.h" diff --git a/ports/bare-arm/main.c b/ports/bare-arm/main.c index 938414dfe..b96fb47ac 100644 --- a/ports/bare-arm/main.c +++ b/ports/bare-arm/main.c @@ -2,7 +2,6 @@ #include #include -#include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" diff --git a/ports/cc3200/ftp/ftp.c b/ports/cc3200/ftp/ftp.c index 5461f9180..ee80e51f5 100644 --- a/ports/cc3200/ftp/ftp.c +++ b/ports/cc3200/ftp/ftp.c @@ -27,8 +27,7 @@ #include #include -#include "py/mpstate.h" -#include "py/obj.h" +#include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" diff --git a/ports/cc3200/hal/cc3200_hal.c b/ports/cc3200/hal/cc3200_hal.c index 9718980e7..0285d0585 100644 --- a/ports/cc3200/hal/cc3200_hal.c +++ b/ports/cc3200/hal/cc3200_hal.c @@ -33,7 +33,6 @@ #include -#include "py/mpstate.h" #include "py/mphal.h" #include "py/runtime.h" #include "py/objstr.h" diff --git a/ports/cc3200/misc/mpexception.c b/ports/cc3200/misc/mpexception.c index 2dfcbfdef..72d4a155f 100644 --- a/ports/cc3200/misc/mpexception.c +++ b/ports/cc3200/misc/mpexception.c @@ -28,7 +28,6 @@ #include #include -#include "py/mpstate.h" #include "mpexception.h" diff --git a/ports/cc3200/mods/modmachine.c b/ports/cc3200/mods/modmachine.c index fb0fe7f2c..6051497e3 100644 --- a/ports/cc3200/mods/modmachine.c +++ b/ports/cc3200/mods/modmachine.c @@ -27,7 +27,6 @@ #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c index 0234a0ccb..37dffe731 100644 --- a/ports/cc3200/mods/modnetwork.c +++ b/ports/cc3200/mods/modnetwork.c @@ -25,9 +25,6 @@ * THE SOFTWARE. */ -#include "py/mpstate.h" -#include "py/obj.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" diff --git a/ports/cc3200/mods/modubinascii.c b/ports/cc3200/mods/modubinascii.c index 7f51a8f3d..6b020ab39 100644 --- a/ports/cc3200/mods/modubinascii.c +++ b/ports/cc3200/mods/modubinascii.c @@ -25,8 +25,6 @@ * THE SOFTWARE. */ -#include "py/mpconfig.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/binary.h" #include "extmod/modubinascii.h" diff --git a/ports/cc3200/mods/moduhashlib.c b/ports/cc3200/mods/moduhashlib.c index bec88d7ca..96f514927 100644 --- a/ports/cc3200/mods/moduhashlib.c +++ b/ports/cc3200/mods/moduhashlib.c @@ -30,7 +30,6 @@ #include "py/mpconfig.h" #include MICROPY_HAL_H -#include "py/nlr.h" #include "py/runtime.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" diff --git a/ports/cc3200/mods/moduos.c b/ports/cc3200/mods/moduos.c index ba8fd86a6..7d99c8e80 100644 --- a/ports/cc3200/mods/moduos.c +++ b/ports/cc3200/mods/moduos.c @@ -28,8 +28,6 @@ #include #include -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/objtuple.h" #include "py/objstr.h" #include "py/runtime.h" diff --git a/ports/cc3200/mods/pybadc.c b/ports/cc3200/mods/pybadc.c index 850664cab..c73b8c149 100644 --- a/ports/cc3200/mods/pybadc.c +++ b/ports/cc3200/mods/pybadc.c @@ -28,8 +28,6 @@ #include #include -#include "py/mpconfig.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/binary.h" #include "py/gc.h" diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c index efb78a44d..d08627fa4 100644 --- a/ports/cc3200/mods/pybi2c.c +++ b/ports/cc3200/mods/pybi2c.c @@ -28,7 +28,6 @@ #include #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" diff --git a/ports/cc3200/mods/pybpin.c b/ports/cc3200/mods/pybpin.c index 2402332d5..c877433e9 100644 --- a/ports/cc3200/mods/pybpin.c +++ b/ports/cc3200/mods/pybpin.c @@ -29,11 +29,8 @@ #include #include -#include "py/mpconfig.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/gc.h" -#include "py/mpstate.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c index a7488c5f1..798c6538b 100644 --- a/ports/cc3200/mods/pybsleep.c +++ b/ports/cc3200/mods/pybsleep.c @@ -27,7 +27,6 @@ #include #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mphal.h" #include "inc/hw_types.h" diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c index 8537f649f..27591e4f4 100644 --- a/ports/cc3200/mods/pybspi.c +++ b/ports/cc3200/mods/pybspi.c @@ -28,7 +28,6 @@ #include #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mperrno.h" #include "bufhelper.h" diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c index f3a12c5e7..ea795b848 100644 --- a/ports/cc3200/mods/pybtimer.c +++ b/ports/cc3200/mods/pybtimer.c @@ -29,9 +29,6 @@ #include #include -#include "py/mpconfig.h" -#include "py/obj.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mperrno.h" diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c index 135e0f2a3..35c0de9f9 100644 --- a/ports/cc3200/mods/pybuart.c +++ b/ports/cc3200/mods/pybuart.c @@ -29,8 +29,6 @@ #include #include -#include "py/mpconfig.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/objlist.h" #include "py/stream.h" @@ -48,7 +46,6 @@ #include "mpirq.h" #include "pybsleep.h" #include "mpexception.h" -#include "py/mpstate.h" #include "osi.h" #include "utils.h" #include "pin.h" diff --git a/ports/cc3200/mpthreadport.c b/ports/cc3200/mpthreadport.c index e77ac4ae5..9dbc518e0 100644 --- a/ports/cc3200/mpthreadport.c +++ b/ports/cc3200/mpthreadport.c @@ -26,8 +26,6 @@ #include -#include "py/mpconfig.h" -#include "py/mpstate.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" diff --git a/ports/cc3200/util/gccollect.c b/ports/cc3200/util/gccollect.c index baee2eeef..6e2a9081c 100644 --- a/ports/cc3200/util/gccollect.c +++ b/ports/cc3200/util/gccollect.c @@ -28,8 +28,6 @@ #include #include -#include "py/mpconfig.h" -#include "py/mpstate.h" #include "py/gc.h" #include "py/mpthread.h" #include "gccollect.h" diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c index ec4751e16..71d4c5062 100644 --- a/ports/esp8266/esp_mphal.c +++ b/ports/esp8266/esp_mphal.c @@ -31,8 +31,6 @@ #include "esp_mphal.h" #include "user_interface.h" #include "ets_alt_task.h" -#include "py/obj.h" -#include "py/mpstate.h" #include "py/runtime.h" #include "extmod/misc.h" #include "lib/utils/pyexec.h" diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c index c8c08695b..b422f0f9e 100644 --- a/ports/esp8266/machine_adc.c +++ b/ports/esp8266/machine_adc.c @@ -27,8 +27,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "user_interface.h" diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index 3ead3f4c2..14505c8f0 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -33,7 +33,6 @@ #include "user_interface.h" #include "gpio.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" diff --git a/ports/esp8266/machine_pwm.c b/ports/esp8266/machine_pwm.c index 8d73e6bb1..4c5cb8727 100644 --- a/ports/esp8266/machine_pwm.c +++ b/ports/esp8266/machine_pwm.c @@ -29,7 +29,6 @@ #include "esppwm.h" -#include "py/nlr.h" #include "py/runtime.h" #include "modmachine.h" diff --git a/ports/esp8266/machine_rtc.c b/ports/esp8266/machine_rtc.c index f6a13c095..bbfc172cd 100644 --- a/ports/esp8266/machine_rtc.c +++ b/ports/esp8266/machine_rtc.c @@ -27,8 +27,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "user_interface.h" diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c index 5e23ff782..04b42782e 100644 --- a/ports/esp8266/machine_wdt.c +++ b/ports/esp8266/machine_wdt.c @@ -27,8 +27,6 @@ //#include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "user_interface.h" #include "etshal.h" diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index 957198aa0..7f5dca84e 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -27,9 +27,7 @@ #include #include -#include "py/nlr.h" #include "py/compile.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/mperrno.h" diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index 3acd244b8..2c61e5dcd 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" diff --git a/ports/esp8266/modutime.c b/ports/esp8266/modutime.c index 77dbcfa1f..ab9cb7dc2 100644 --- a/ports/esp8266/modutime.c +++ b/ports/esp8266/modutime.c @@ -28,8 +28,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/gc.h" #include "py/runtime.h" #include "py/mphal.h" diff --git a/ports/minimal/main.c b/ports/minimal/main.c index e28cfe45e..9d43a9cf9 100644 --- a/ports/minimal/main.c +++ b/ports/minimal/main.c @@ -2,7 +2,6 @@ #include #include -#include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" diff --git a/ports/qemu-arm/main.c b/ports/qemu-arm/main.c index d5fbcd84b..d23ef576f 100644 --- a/ports/qemu-arm/main.c +++ b/ports/qemu-arm/main.c @@ -4,10 +4,8 @@ #include #include -#include "py/nlr.h" #include "py/obj.h" #include "py/compile.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" diff --git a/ports/qemu-arm/test_main.c b/ports/qemu-arm/test_main.c index 5c07d1607..c018ae428 100644 --- a/ports/qemu-arm/test_main.c +++ b/ports/qemu-arm/test_main.c @@ -4,10 +4,8 @@ #include #include -#include "py/nlr.h" #include "py/obj.h" #include "py/compile.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index 512a6e313..7b36e2082 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -28,7 +28,6 @@ #include #include "py/mphal.h" -#include "py/nlr.h" #include "py/runtime.h" #include "pin.h" #include "genhdr/pins.h" diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 4192e7fed..9a0dc56a3 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/binary.h" #include "py/mphal.h" diff --git a/ports/stm32/can.c b/ports/stm32/can.c index 2fd593d58..25a608ce9 100644 --- a/ports/stm32/can.c +++ b/ports/stm32/can.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/objtuple.h" #include "py/runtime.h" #include "py/gc.h" diff --git a/ports/stm32/gccollect.c b/ports/stm32/gccollect.c index 937fb6f36..cdec2a136 100644 --- a/ports/stm32/gccollect.c +++ b/ports/stm32/gccollect.c @@ -27,7 +27,6 @@ #include #include -#include "py/mpstate.h" #include "py/obj.h" #include "py/gc.h" #include "py/mpthread.h" diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c index fcf3cd9c3..b22787cab 100644 --- a/ports/stm32/i2c.c +++ b/ports/stm32/i2c.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" diff --git a/ports/stm32/irq.c b/ports/stm32/irq.c index d6db8e83d..7298a4b50 100644 --- a/ports/stm32/irq.c +++ b/ports/stm32/irq.c @@ -24,7 +24,6 @@ * THE SOFTWARE. */ -#include "py/nlr.h" #include "py/obj.h" #include "py/mphal.h" #include "irq.h" diff --git a/ports/stm32/lcd.c b/ports/stm32/lcd.c index 559616b96..488df1699 100644 --- a/ports/stm32/lcd.c +++ b/ports/stm32/lcd.c @@ -28,7 +28,6 @@ #include #include "py/mphal.h" -#include "py/nlr.h" #include "py/runtime.h" #if MICROPY_HW_HAS_LCD diff --git a/ports/stm32/led.c b/ports/stm32/led.c index e03781bcf..9bbcaa6b3 100644 --- a/ports/stm32/led.c +++ b/ports/stm32/led.c @@ -26,7 +26,6 @@ #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "timer.h" diff --git a/ports/stm32/modmachine.h b/ports/stm32/modmachine.h index ac39f854e..77668695f 100644 --- a/ports/stm32/modmachine.h +++ b/ports/stm32/modmachine.h @@ -26,8 +26,6 @@ #ifndef MICROPY_INCLUDED_STMHAL_MODMACHINE_H #define MICROPY_INCLUDED_STMHAL_MODMACHINE_H -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/obj.h" void machine_init(void); diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 6b4949a0d..642174532 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/objlist.h" #include "py/runtime.h" #include "modnetwork.h" diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c index 2be5d6c22..551206da8 100644 --- a/ports/stm32/modnwcc3k.c +++ b/ports/stm32/modnwcc3k.c @@ -30,7 +30,6 @@ // CC3000 defines its own ENOBUFS (different to standard one!) #undef ENOBUFS -#include "py/nlr.h" #include "py/objtuple.h" #include "py/objlist.h" #include "py/stream.h" diff --git a/ports/stm32/modnwwiznet5k.c b/ports/stm32/modnwwiznet5k.c index 2d5a8d51a..21e4dbbbf 100644 --- a/ports/stm32/modnwwiznet5k.c +++ b/ports/stm32/modnwwiznet5k.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/mperrno.h" diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index 5dc28e132..176fc8466 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -27,8 +27,6 @@ #include #include -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/obj.h" #include "py/gc.h" #include "py/builtin.h" diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c index 82ee61726..f661b3b5e 100644 --- a/ports/stm32/moduos.c +++ b/ports/stm32/moduos.c @@ -27,7 +27,6 @@ #include #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/objstr.h" diff --git a/ports/stm32/modusocket.c b/ports/stm32/modusocket.c index 32dad5ced..c5ab3b6d7 100644 --- a/ports/stm32/modusocket.c +++ b/ports/stm32/modusocket.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/objtuple.h" #include "py/objlist.h" #include "py/runtime.h" diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index dff781ff2..ab3dc227a 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -1,6 +1,5 @@ #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" diff --git a/ports/stm32/mpthreadport.c b/ports/stm32/mpthreadport.c index d7c5b569b..11653b24c 100644 --- a/ports/stm32/mpthreadport.c +++ b/ports/stm32/mpthreadport.c @@ -26,8 +26,6 @@ #include -#include "py/mpconfig.h" -#include "py/mpstate.h" #include "py/gc.h" #include "py/mpthread.h" #include "gccollect.h" diff --git a/ports/stm32/pendsv.c b/ports/stm32/pendsv.c index 00ea12f46..0aeb1a6dc 100644 --- a/ports/stm32/pendsv.c +++ b/ports/stm32/pendsv.c @@ -26,7 +26,6 @@ #include -#include "py/mpstate.h" #include "py/runtime.h" #include "lib/utils/interrupt_char.h" #include "pendsv.h" diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index b7a2302b0..ee2d84646 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "extmod/virtpin.h" diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 27276332a..484426b84 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -26,7 +26,6 @@ #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "lib/oofatfs/ff.h" diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 654a1327d..cfd9c2667 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "extmod/machine_spi.h" diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 2111da1ae..f1ac9b6b8 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -67,7 +67,6 @@ #include -#include "py/mpstate.h" #include "py/obj.h" #include "py/mphal.h" #include "stm32_it.h" diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 1238b4e31..2b2f782f9 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" diff --git a/ports/teensy/led.c b/ports/teensy/led.c index 9159c75ce..add052fad 100644 --- a/ports/teensy/led.c +++ b/ports/teensy/led.c @@ -2,7 +2,6 @@ #include "Arduino.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "led.h" diff --git a/ports/teensy/teensy_hal.c b/ports/teensy/teensy_hal.c index 439e3380d..84d68cff8 100644 --- a/ports/teensy/teensy_hal.c +++ b/ports/teensy/teensy_hal.c @@ -1,7 +1,6 @@ #include #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mphal.h" #include "usb.h" diff --git a/ports/teensy/timer.c b/ports/teensy/timer.c index cdc7a3c54..b823e6c3b 100644 --- a/ports/teensy/timer.c +++ b/ports/teensy/timer.c @@ -29,7 +29,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" diff --git a/ports/teensy/uart.c b/ports/teensy/uart.c index 768572aff..3d5111217 100644 --- a/ports/teensy/uart.c +++ b/ports/teensy/uart.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "bufhelper.h" #include "uart.h" diff --git a/ports/unix/file.c b/ports/unix/file.c index 0d65f9ca0..84e918082 100644 --- a/ports/unix/file.c +++ b/ports/unix/file.c @@ -31,7 +31,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/builtin.h" diff --git a/ports/unix/main.c b/ports/unix/main.c index e861d7f11..e1cd33fc1 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -37,8 +37,6 @@ #include #include -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" #include "py/builtin.h" diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 9b514371b..78adccac1 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -32,7 +32,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/binary.h" #include "py/mperrno.h" diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index b7ac49dc8..15b6d9cd7 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -30,8 +30,6 @@ #include #include -#include "py/nlr.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/binary.h" diff --git a/ports/unix/modos.c b/ports/unix/modos.c index 5030fbb65..327116a0a 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -34,7 +34,6 @@ #include #include "py/mpconfig.h" -#include "py/nlr.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/mphal.h" diff --git a/ports/unix/modsocket.c b/ports/unix/modsocket.c index c612f870d..7e82554c7 100644 --- a/ports/unix/modsocket.c +++ b/ports/unix/modsocket.c @@ -38,7 +38,6 @@ #include #include -#include "py/nlr.h" #include "py/objtuple.h" #include "py/objstr.h" #include "py/runtime.h" diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index 09f5702e3..8c636a445 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -28,7 +28,6 @@ #include #include -#include "py/mpstate.h" #include "py/runtime.h" #include "py/mpthread.h" #include "py/gc.h" diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 02cdbea11..2b273d834 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -29,7 +29,6 @@ #include #include -#include "py/mpstate.h" #include "py/mphal.h" #include "py/runtime.h" #include "extmod/misc.h" diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index c23ac08f0..4dcd956cf 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -32,7 +32,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" diff --git a/ports/zephyr/main.c b/ports/zephyr/main.c index a4301629f..7255d981f 100644 --- a/ports/zephyr/main.c +++ b/ports/zephyr/main.c @@ -33,7 +33,6 @@ #include #endif -#include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" diff --git a/py/argcheck.c b/py/argcheck.c index 0c5c5ca95..add6f8de8 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) { diff --git a/py/bc.c b/py/bc.c index 917eba57d..991b0cf26 100644 --- a/py/bc.c +++ b/py/bc.c @@ -29,9 +29,7 @@ #include #include -#include "py/nlr.h" -#include "py/objfun.h" -#include "py/runtime0.h" +#include "py/runtime.h" #include "py/bc0.h" #include "py/bc.h" diff --git a/py/bc.h b/py/bc.h index 69e213e42..ebfdeaac1 100644 --- a/py/bc.h +++ b/py/bc.h @@ -27,7 +27,6 @@ #define MICROPY_INCLUDED_PY_BC_H #include "py/runtime.h" -#include "py/obj.h" #include "py/objfun.h" // bytecode layout: diff --git a/py/builtinevex.c b/py/builtinevex.c index ba8048f70..846603f46 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -26,7 +26,6 @@ #include -#include "py/nlr.h" #include "py/objfun.h" #include "py/compile.h" #include "py/runtime.h" diff --git a/py/builtinimport.c b/py/builtinimport.c index f5bfb0d98..04ce66723 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -29,7 +29,6 @@ #include #include -#include "py/nlr.h" #include "py/compile.h" #include "py/objmodule.h" #include "py/persistentcode.h" diff --git a/py/emit.h b/py/emit.h index 2b2c904f6..270a40633 100644 --- a/py/emit.h +++ b/py/emit.h @@ -28,7 +28,6 @@ #include "py/lexer.h" #include "py/scope.h" -#include "py/runtime0.h" /* Notes on passes: * We don't know exactly the opcodes in pass 1 because they depend on the diff --git a/py/emitnative.c b/py/emitnative.c index 4608cd1e0..b2c9a7366 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -46,7 +46,6 @@ #include #include -#include "py/nlr.h" #include "py/emit.h" #include "py/bc.h" diff --git a/py/gc.c b/py/gc.c index 3a505e9c7..9752b3532 100644 --- a/py/gc.c +++ b/py/gc.c @@ -28,9 +28,7 @@ #include #include -#include "py/mpstate.h" #include "py/gc.h" -#include "py/obj.h" #include "py/runtime.h" #if MICROPY_ENABLE_GC diff --git a/py/lexer.c b/py/lexer.c index 074d6f356..6017d69d6 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -28,7 +28,6 @@ #include #include -#include "py/mpstate.h" #include "py/reader.h" #include "py/lexer.h" #include "py/runtime.h" diff --git a/py/map.c b/py/map.c index f07b8fbd2..4f76b9b16 100644 --- a/py/map.c +++ b/py/map.c @@ -31,7 +31,6 @@ #include "py/mpconfig.h" #include "py/misc.h" -#include "py/runtime0.h" #include "py/runtime.h" // Fixed empty map. Useful when need to call kw-receiving functions diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 0486251b6..82b08cdc9 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -27,12 +27,10 @@ #include #include -#include "py/nlr.h" #include "py/smallint.h" #include "py/objint.h" #include "py/objstr.h" #include "py/objtype.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/stream.h" diff --git a/py/modmicropython.c b/py/modmicropython.c index 6fa3f9ad2..2aac53adc 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -26,7 +26,6 @@ #include -#include "py/mpstate.h" #include "py/builtin.h" #include "py/stackctrl.h" #include "py/runtime.h" diff --git a/py/modsys.c b/py/modsys.c index ecc0b6065..84a4eb0f4 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -25,8 +25,6 @@ * THE SOFTWARE. */ -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/builtin.h" #include "py/objlist.h" #include "py/objtuple.h" @@ -35,7 +33,6 @@ #include "py/objtype.h" #include "py/stream.h" #include "py/smallint.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_SYS diff --git a/py/nativeglue.c b/py/nativeglue.c index e954234c2..61b624ec7 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -28,8 +28,6 @@ #include #include -#include "py/nlr.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/emitglue.h" #include "py/bc.h" diff --git a/py/nlrthumb.c b/py/nlrthumb.c index 8ff1bb2d2..6e7d71766 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -25,7 +25,6 @@ */ #include "py/mpstate.h" -#include "py/nlr.h" #if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) diff --git a/py/nlrx64.c b/py/nlrx64.c index aeaacd50c..847d10398 100644 --- a/py/nlrx64.c +++ b/py/nlrx64.c @@ -25,7 +25,6 @@ */ #include "py/mpstate.h" -#include "py/nlr.h" #if !MICROPY_NLR_SETJMP && defined(__x86_64__) diff --git a/py/nlrx86.c b/py/nlrx86.c index a5a20f373..094dea3cc 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -24,9 +24,7 @@ * THE SOFTWARE. */ -#include "py/mpconfig.h" #include "py/mpstate.h" -#include "py/nlr.h" #if !MICROPY_NLR_SETJMP && defined(__i386__) diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c index ccac3597b..4520e7e7a 100644 --- a/py/nlrxtensa.c +++ b/py/nlrxtensa.c @@ -25,7 +25,6 @@ */ #include "py/mpstate.h" -#include "py/nlr.h" #if !MICROPY_NLR_SETJMP && defined(__xtensa__) diff --git a/py/obj.c b/py/obj.c index 857fe373f..a1de89a03 100644 --- a/py/obj.c +++ b/py/obj.c @@ -29,12 +29,10 @@ #include #include -#include "py/nlr.h" #include "py/obj.h" #include "py/objtype.h" #include "py/objint.h" #include "py/objstr.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/stream.h" // for mp_obj_print diff --git a/py/objarray.c b/py/objarray.c index d51cc650b..8a3e7faad 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -29,8 +29,6 @@ #include #include -#include "py/nlr.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/binary.h" #include "py/objstr.h" diff --git a/py/objbool.c b/py/objbool.c index b94c57f87..5755b188e 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -26,8 +26,6 @@ #include -#include "py/obj.h" -#include "py/runtime0.h" #include "py/runtime.h" typedef struct _mp_obj_bool_t { diff --git a/py/objcomplex.c b/py/objcomplex.c index 088ad5211..409d65666 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -28,10 +28,7 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/parsenum.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_COMPLEX diff --git a/py/objdict.c b/py/objdict.c index 6bb243562..1553a83b4 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -27,9 +27,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/objtype.h" diff --git a/py/objexcept.c b/py/objexcept.c index 0a03df9d0..b87609a6b 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -29,7 +29,6 @@ #include #include -#include "py/mpstate.h" #include "py/objlist.h" #include "py/objstr.h" #include "py/objtuple.h" diff --git a/py/objfloat.c b/py/objfloat.c index 0831be3fd..743287be6 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -29,9 +29,7 @@ #include #include -#include "py/nlr.h" #include "py/parsenum.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objfun.c b/py/objfun.c index 5606511d8..030b3f7cb 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -28,10 +28,8 @@ #include #include -#include "py/nlr.h" #include "py/objtuple.h" #include "py/objfun.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/bc.h" #include "py/stackctrl.h" diff --git a/py/objgenerator.c b/py/objgenerator.c index 2f39f3a52..bf0bbb0e6 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -28,8 +28,6 @@ #include #include -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/bc.h" #include "py/objgenerator.h" diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index afd6fb22b..ec41c2c5b 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -26,7 +26,6 @@ #include -#include "py/nlr.h" #include "py/runtime.h" // this is a wrapper object that turns something that has a __getitem__ method into an iterator diff --git a/py/objint.c b/py/objint.c index 000a0404c..4f2e610a5 100644 --- a/py/objint.c +++ b/py/objint.c @@ -28,12 +28,10 @@ #include #include -#include "py/nlr.h" #include "py/parsenum.h" #include "py/smallint.h" #include "py/objint.h" #include "py/objstr.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/binary.h" diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 8d8ca1b2c..2e567c572 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -28,10 +28,8 @@ #include #include -#include "py/nlr.h" #include "py/smallint.h" #include "py/objint.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 15aad1d4d..7b5cb0b9d 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -28,11 +28,9 @@ #include #include -#include "py/nlr.h" #include "py/parsenumbase.h" #include "py/smallint.h" #include "py/objint.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objlist.c b/py/objlist.c index d70867ded..bc22d9fc3 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -27,9 +27,7 @@ #include #include -#include "py/nlr.h" #include "py/objlist.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" diff --git a/py/objmodule.c b/py/objmodule.c index fc8507c27..f9363e379 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -27,8 +27,6 @@ #include #include -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/objmodule.h" #include "py/runtime.h" #include "py/builtin.h" diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index fb9d9f02c..38daccdf2 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -27,7 +27,6 @@ #include -#include "py/nlr.h" #include "py/objtuple.h" #include "py/runtime.h" #include "py/objstr.h" diff --git a/py/objnone.c b/py/objnone.c index cd7319bec..da1031835 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -26,9 +26,7 @@ #include -#include "py/nlr.h" #include "py/obj.h" -#include "py/runtime0.h" typedef struct _mp_obj_none_t { mp_obj_base_t base; diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 61bd1e0ac..01880bff9 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -26,7 +26,6 @@ #include -#include "py/nlr.h" #include "py/runtime.h" // This is universal iterator type which calls "iternext" method stored in diff --git a/py/objproperty.c b/py/objproperty.c index 0934fad05..b66d24a11 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_PROPERTY diff --git a/py/objrange.c b/py/objrange.c index fa99c4c2d..3874adb11 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -26,8 +26,6 @@ #include -#include "py/nlr.h" -#include "py/runtime0.h" #include "py/runtime.h" /******************************************************************************/ diff --git a/py/objreversed.c b/py/objreversed.c index a596a2fde..e498b553d 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -27,7 +27,6 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_REVERSED diff --git a/py/objset.c b/py/objset.c index aefc26aac..6ed15c791 100644 --- a/py/objset.c +++ b/py/objset.c @@ -28,9 +28,7 @@ #include #include -#include "py/nlr.h" #include "py/runtime.h" -#include "py/runtime0.h" #include "py/builtin.h" #if MICROPY_PY_BUILTINS_SET diff --git a/py/objsingleton.c b/py/objsingleton.c index ea72ae38c..67535391e 100644 --- a/py/objsingleton.c +++ b/py/objsingleton.c @@ -27,9 +27,7 @@ #include #include -#include "py/nlr.h" #include "py/obj.h" -#include "py/runtime0.h" /******************************************************************************/ /* singleton objects defined by Python */ diff --git a/py/objslice.c b/py/objslice.c index 358c44d06..de996d831 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -27,9 +27,7 @@ #include #include -#include "py/nlr.h" #include "py/obj.h" -#include "py/runtime0.h" /******************************************************************************/ /* slice object */ diff --git a/py/objstr.c b/py/objstr.c index 11bfb41fc..d17b0a68c 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -28,11 +28,9 @@ #include #include -#include "py/nlr.h" #include "py/unicode.h" #include "py/objstr.h" #include "py/objlist.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" diff --git a/py/objstringio.c b/py/objstringio.c index 61da0203e..5c50aa317 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/objstr.h" #include "py/objstringio.h" #include "py/runtime.h" diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 785317406..29f7695b7 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -28,10 +28,8 @@ #include #include -#include "py/nlr.h" #include "py/objstr.h" #include "py/objlist.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_STR_UNICODE diff --git a/py/objtuple.c b/py/objtuple.c index b8916a1a7..34b7664eb 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -27,9 +27,7 @@ #include #include -#include "py/nlr.h" #include "py/objtuple.h" -#include "py/runtime0.h" #include "py/runtime.h" /******************************************************************************/ diff --git a/py/objtype.c b/py/objtype.c index 033765a47..d7f409e30 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -30,9 +30,7 @@ #include #include -#include "py/nlr.h" #include "py/objtype.h" -#include "py/runtime0.h" #include "py/runtime.h" #if MICROPY_DEBUG_VERBOSE // print debugging info diff --git a/py/parse.c b/py/parse.c index e399aac53..8c51b0349 100644 --- a/py/parse.c +++ b/py/parse.c @@ -31,11 +31,9 @@ #include #include -#include "py/nlr.h" #include "py/lexer.h" #include "py/parse.h" #include "py/parsenum.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/objint.h" #include "py/objstr.h" diff --git a/py/persistentcode.c b/py/persistentcode.c index f954038ae..d8b17c7e6 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -99,7 +99,6 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_ #if MICROPY_PERSISTENT_CODE_LOAD #include "py/parsenum.h" -#include "py/bc0.h" STATIC int read_byte(mp_reader_t *reader) { return reader->readbyte(reader->data); diff --git a/py/runtime.c b/py/runtime.c index f21eed204..069548deb 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -28,8 +28,6 @@ #include #include -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/parsenum.h" #include "py/compile.h" #include "py/objstr.h" @@ -38,7 +36,6 @@ #include "py/objmodule.h" #include "py/objgenerator.h" #include "py/smallint.h" -#include "py/runtime0.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/stackctrl.h" diff --git a/py/runtime.h b/py/runtime.h index da12f8f04..d410b5614 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -27,7 +27,6 @@ #define MICROPY_INCLUDED_PY_RUNTIME_H #include "py/mpstate.h" -#include "py/obj.h" typedef enum { MP_VM_RETURN_NORMAL, diff --git a/py/runtime_utils.c b/py/runtime_utils.c index 56a918064..a5c5403ba 100644 --- a/py/runtime_utils.c +++ b/py/runtime_utils.c @@ -26,8 +26,6 @@ */ #include "py/runtime.h" -#include "py/obj.h" -#include "py/nlr.h" void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) { nlr_buf_t nlr; diff --git a/py/sequence.c b/py/sequence.c index 0752ee109..c66fde98f 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -27,9 +27,6 @@ #include -#include "py/nlr.h" -#include "py/obj.h" -#include "py/runtime0.h" #include "py/runtime.h" // Helpers for sequence types diff --git a/py/stackctrl.c b/py/stackctrl.c index 0bcd82f4f..7cd35fee2 100644 --- a/py/stackctrl.c +++ b/py/stackctrl.c @@ -24,9 +24,6 @@ * THE SOFTWARE. */ -#include "py/mpstate.h" -#include "py/nlr.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/stackctrl.h" diff --git a/py/stream.c b/py/stream.c index 0adf0af06..453dee769 100644 --- a/py/stream.c +++ b/py/stream.c @@ -28,7 +28,6 @@ #include #include -#include "py/nlr.h" #include "py/objstr.h" #include "py/stream.h" #include "py/runtime.h" diff --git a/py/vm.c b/py/vm.c index 9a27b2b22..564200037 100644 --- a/py/vm.c +++ b/py/vm.c @@ -29,8 +29,6 @@ #include #include -#include "py/mpstate.h" -#include "py/nlr.h" #include "py/emitglue.h" #include "py/objtype.h" #include "py/runtime.h" -- cgit v1.2.3 From dfa563c71fead671931e91b786cd649eed517f92 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Oct 2017 17:59:22 +1100 Subject: py/objstr: Make empty bytes object have a null-terminating byte. Because a lot of string processing functions assume there is a null terminating byte, so they can work in an efficient way. Fixes issue #3334. --- py/objstr.c | 4 ++-- tests/basics/bytes.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'py') diff --git a/py/objstr.c b/py/objstr.c index d17b0a68c..51da7a418 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1973,8 +1973,8 @@ const mp_obj_type_t mp_type_bytes = { .locals_dict = (mp_obj_dict_t*)&str8_locals_dict, }; -// the zero-length bytes -const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, NULL}; +// The zero-length bytes object, with data that includes a null-terminating byte +const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte*)""}; // Create a str/bytes object using the given data. New memory is allocated and // the data is copied across. diff --git a/tests/basics/bytes.py b/tests/basics/bytes.py index d3da15c8e..1d97e6b16 100644 --- a/tests/basics/bytes.py +++ b/tests/basics/bytes.py @@ -8,6 +8,9 @@ print(b'\u1234') print(bytes()) print(bytes(b'abc')) +# make sure empty bytes is converted correctly +print(str(bytes(), 'utf-8')) + a = b"123" print(a) print(str(a)) -- cgit v1.2.3 From 23faf88cab10a216eb24a30b4f33edd17183522c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Oct 2017 18:07:32 +1100 Subject: py/mpprint: Only check for null string printing when NDEBUG not defined. Printing "(null)" when a NULL string pointer is passed to %s is a debugging feature and not a feature that's relied upon by the code. So it only needs to be compiled in when debugging (such as assert) is enabled, and saves roughy 30 bytes of code when disabled. This patch also fixes this NULL check to not do the check if the precision is specified as zero. --- py/mpprint.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'py') diff --git a/py/mpprint.c b/py/mpprint.c index 6c02d7cef..a569ef793 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -485,14 +485,17 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { case 's': { const char *str = va_arg(args, const char*); - if (str) { - if (prec < 0) { - prec = strlen(str); - } - chrs += mp_print_strn(print, str, prec, flags, fill, width); - } else { + #ifndef NDEBUG + // With debugging enabled, catch printing of null string pointers + if (prec != 0 && str == NULL) { chrs += mp_print_strn(print, "(null)", 6, flags, fill, width); + break; } + #endif + if (prec < 0) { + prec = strlen(str); + } + chrs += mp_print_strn(print, str, prec, flags, fill, width); break; } case 'u': -- cgit v1.2.3