diff options
51 files changed, 304 insertions, 231 deletions
diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h index 3a3c8615d0..73b66802fe 100644 --- a/bare-arm/mpconfigport.h +++ b/bare-arm/mpconfigport.h @@ -12,13 +12,16 @@ #define MICROPY_HELPER_REPL (0) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (0) +#define MICROPY_PY_BUILTINS_FROZENSET (0) +#define MICROPY_PY_BUILTINS_SET (0) +#define MICROPY_PY_BUILTINS_SLICE (0) +#define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (0) -#define MICROPY_PY_PROPERTY (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) @@ -36,8 +36,21 @@ typedef struct _mp_exc_stack { byte opcode; } mp_exc_stack_t; +typedef struct _mp_code_state { + const byte *code_info; + const byte *ip; + mp_obj_t *sp; + // bit 0 is saved currently_in_except_block value + mp_exc_stack_t *exc_sp; + uint n_state; + // Variable-length + mp_obj_t state[0]; + // Variable-length, never accessed by name, only as (void*)(state + n_state) + //mp_exc_stack_t exc_state[0]; +} mp_code_state; + mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, mp_obj_t *ret); -mp_vm_return_kind_t mp_execute_bytecode2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out, mp_exc_stack_t *exc_stack, mp_exc_stack_t **exc_sp_in_out, volatile mp_obj_t inject_exc); +mp_vm_return_kind_t mp_execute_bytecode2(mp_code_state *code_state, volatile mp_obj_t inject_exc); void mp_bytecode_print(const byte *code, int len); void mp_bytecode_print2(const byte *code, int len); diff --git a/py/binary.c b/py/binary.c index 7640b7590d..cec2374460 100644 --- a/py/binary.c +++ b/py/binary.c @@ -114,7 +114,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) { // TODO: Explode API more to cover signedness return mp_obj_new_int_from_ll(((long long*)p)[index]); #endif -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT case 'f': return mp_obj_new_float(((float*)p)[index]); case 'd': @@ -217,7 +217,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte ** void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) { switch (typecode) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT case 'f': ((float*)p)[index] = mp_obj_float_get(val_in); break; @@ -260,7 +260,7 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine ((long long*)p)[index] = val; break; #endif -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT case 'f': ((float*)p)[index] = val; break; diff --git a/py/builtin.c b/py/builtin.c index 178a6835aa..c336378109 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -37,7 +37,7 @@ #include "runtime.h" #include "builtin.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #include <math.h> #endif @@ -104,7 +104,7 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) { val = -val; } return MP_OBJ_NEW_SMALL_INT(val); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) { mp_float_t value = mp_obj_float_get(o_in); // TODO check for NaN etc diff --git a/py/builtintables.c b/py/builtintables.c index 1d22683d97..628514da1c 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -44,27 +44,29 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool }, { MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes }, { MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray }, -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT { MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict }, { MP_OBJ_NEW_QSTR(MP_QSTR_enumerate), (mp_obj_t)&mp_type_enumerate }, { MP_OBJ_NEW_QSTR(MP_QSTR_filter), (mp_obj_t)&mp_type_filter }, -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT { MP_OBJ_NEW_QSTR(MP_QSTR_float), (mp_obj_t)&mp_type_float }, #endif -#if MICROPY_PY_FROZENSET +#if MICROPY_PY_BUILTINS_FROZENSET { MP_OBJ_NEW_QSTR(MP_QSTR_frozenset), (mp_obj_t)&mp_type_frozenset }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_int), (mp_obj_t)&mp_type_int }, { MP_OBJ_NEW_QSTR(MP_QSTR_list), (mp_obj_t)&mp_type_list }, { MP_OBJ_NEW_QSTR(MP_QSTR_map), (mp_obj_t)&mp_type_map }, { MP_OBJ_NEW_QSTR(MP_QSTR_object), (mp_obj_t)&mp_type_object }, -#if MICROPY_PY_PROPERTY +#if MICROPY_PY_BUILTINS_PROPERTY { MP_OBJ_NEW_QSTR(MP_QSTR_property), (mp_obj_t)&mp_type_property }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_range), (mp_obj_t)&mp_type_range }, +#if MICROPY_PY_BUILTINS_SET { MP_OBJ_NEW_QSTR(MP_QSTR_set), (mp_obj_t)&mp_type_set }, +#endif { MP_OBJ_NEW_QSTR(MP_QSTR_str), (mp_obj_t)&mp_type_str }, { MP_OBJ_NEW_QSTR(MP_QSTR_super), (mp_obj_t)&mp_type_super }, { MP_OBJ_NEW_QSTR(MP_QSTR_tuple), (mp_obj_t)&mp_type_tuple }, @@ -169,7 +171,7 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_struct }, #endif -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&mp_module_math }, #if MICROPY_PY_CMATH { MP_OBJ_NEW_QSTR(MP_QSTR_cmath), (mp_obj_t)&mp_module_cmath }, diff --git a/py/compile.c b/py/compile.c index c90772a7e3..1f0d90570e 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1745,7 +1745,7 @@ void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // And, if the loop never runs, the loop variable should never be assigned void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) { START_BREAK_CONTINUE_BLOCK - comp->break_label |= MP_EMIT_BREAK_FROM_FOR; + // note that we don't need to pop anything when breaking from an optimise for loop uint top_label = comp_next_label(comp); uint entry_label = comp_next_label(comp); diff --git a/py/modcmath.c b/py/modcmath.c index 9e4de2585f..3bc3055dc8 100644 --- a/py/modcmath.c +++ b/py/modcmath.c @@ -32,7 +32,7 @@ #include "obj.h" #include "builtin.h" -#if MICROPY_ENABLE_FLOAT && MICROPY_PY_CMATH +#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_CMATH // These are defined in modmath.c extern const mp_obj_float_t mp_math_e_obj; @@ -154,4 +154,4 @@ const mp_obj_module_t mp_module_cmath = { .globals = (mp_obj_dict_t*)&mp_module_cmath_globals, }; -#endif // MICROPY_ENABLE_FLOAT && MICROPY_PY_CMATH +#endif // MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_CMATH diff --git a/py/modmath.c b/py/modmath.c index e0ff163436..0fd583c2ff 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -32,7 +32,7 @@ #include "obj.h" #include "builtin.h" -#if MICROPY_ENABLE_FLOAT && MICROPY_PY_MATH +#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH //TODO: Change macros to check for overflow and raise OverflowError or RangeError #define MATH_FUN_1(py_name, c_name) \ @@ -184,4 +184,4 @@ const mp_obj_module_t mp_module_math = { .globals = (mp_obj_dict_t*)&mp_module_math_globals, }; -#endif // MICROPY_ENABLE_FLOAT && MICROPY_PY_MATH +#endif // MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH diff --git a/py/mpconfig.h b/py/mpconfig.h index 1af27f7679..77b76bf13d 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -212,15 +212,15 @@ typedef long long mp_longint_impl_t; #endif #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_PY_BUILTINS_FLOAT (1) #define MICROPY_FLOAT_C_FUN(fun) fun##f typedef float mp_float_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_PY_BUILTINS_FLOAT (1) #define MICROPY_FLOAT_C_FUN(fun) fun typedef double mp_float_t; #else -#define MICROPY_ENABLE_FLOAT (0) +#define MICROPY_PY_BUILTINS_FLOAT (0) #endif // Enable features which improve CPython compatibility @@ -239,20 +239,24 @@ typedef double mp_float_t; /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ -// Whether to support slice object and correspondingly -// slice subscript operators -#ifndef MICROPY_PY_SLICE -#define MICROPY_PY_SLICE (1) +// Whether to support set object +#ifndef MICROPY_PY_BUILTINS_SET +#define MICROPY_PY_BUILTINS_SET (1) +#endif + +// Whether to support slice subscript operators and slice object +#ifndef MICROPY_PY_BUILTINS_SLICE +#define MICROPY_PY_BUILTINS_SLICE (1) #endif // Whether to support frozenset object -#ifndef MICROPY_PY_FROZENSET -#define MICROPY_PY_FROZENSET (0) +#ifndef MICROPY_PY_BUILTINS_FROZENSET +#define MICROPY_PY_BUILTINS_FROZENSET (0) #endif -// Whether to support the property object -#ifndef MICROPY_PY_PROPERTY -#define MICROPY_PY_PROPERTY (1) +// Whether to support property object +#ifndef MICROPY_PY_BUILTINS_PROPERTY +#define MICROPY_PY_BUILTINS_PROPERTY (1) #endif // Whether to provide "collections" module @@ -1262,7 +1262,7 @@ bool mpz_as_int_checked(const mpz_t *i, machine_int_t *value) { return true; } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mpz_as_float(const mpz_t *i) { mp_float_t val = 0; mpz_dig_t *d = i->dig + i->len; @@ -98,7 +98,7 @@ mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs); machine_int_t mpz_as_int(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, machine_int_t *value); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mpz_as_float(const mpz_t *z); #endif uint mpz_as_str_size(const mpz_t *z, uint base); @@ -257,7 +257,7 @@ bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value) { return true; } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_get_float(mp_obj_t arg) { if (arg == mp_const_false) { return 0; @@ -371,7 +371,7 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_str(const char* data, uint len, bool make_qstr_if_not_already); mp_obj_t mp_obj_new_bytes(const byte* data, uint len); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_obj_t mp_obj_new_float(mp_float_t val); mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); #endif @@ -420,7 +420,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); machine_int_t mp_obj_get_int(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_get_float(mp_obj_t self_in); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); #endif @@ -442,7 +442,7 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); // int // For long int, returns value truncated to machine_int_t machine_int_t mp_obj_int_get(mp_const_obj_t self_in); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float(mp_obj_t self_in); #endif // Will raise exception if value doesn't fit into machine_int_t @@ -470,7 +470,7 @@ const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need t const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len); void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT // float typedef struct _mp_obj_float_t { mp_obj_base_t base; @@ -568,7 +568,9 @@ typedef struct { } mp_bound_slice_t; void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest); +#if MICROPY_PY_BUILTINS_SLICE bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes); +#endif #define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t)) #define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); } bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2); diff --git a/py/objarray.c b/py/objarray.c index 91fcec624a..44fbf2f998 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -169,7 +169,9 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value return MP_OBJ_NULL; // op not supported } else { mp_obj_array_t *o = self_in; - if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { + if (0) { +#if MICROPY_PY_BUILTINS_SLICE + } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { if (value != MP_OBJ_SENTINEL) { // Only getting a slice is suported so far, not assignment // TODO: confirmed that both bytearray and array.array support @@ -187,6 +189,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value byte *p = o->items; memcpy(res->items, p + slice.start * sz, (slice.stop - slice.start) * sz); return res; +#endif } else { uint index = mp_get_index(o->base.type, o->len, index_in, false); if (value == MP_OBJ_SENTINEL) { diff --git a/py/objcomplex.c b/py/objcomplex.c index 80a13c6d8f..d58b53463c 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -36,7 +36,7 @@ #include "runtime0.h" #include "runtime.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #include <math.h> diff --git a/py/objfloat.c b/py/objfloat.c index 6732f31215..b608b1a3d7 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -39,7 +39,7 @@ #include "runtime0.h" #include "runtime.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #include "formatfloat.h" @@ -170,4 +170,4 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) { return mp_obj_new_float(lhs_val); } -#endif // MICROPY_ENABLE_FLOAT +#endif // MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objfun.c b/py/objfun.c index 8ee5365d5d..77d57821b9 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -469,7 +469,7 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { } else { mp_obj_type_t *type = mp_obj_get_type(obj); if (0) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else if (type == &mp_type_float) { // convert float to int (could also pass in float registers) return (machine_int_t)mp_obj_float_get(obj); diff --git a/py/objgenerator.c b/py/objgenerator.c index d9825f814f..7326bced30 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -82,42 +82,31 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) { typedef struct _mp_obj_gen_instance_t { mp_obj_base_t base; mp_obj_dict_t *globals; - const byte *code_info; - const byte *ip; - mp_obj_t *sp; - // bit 0 is saved currently_in_except_block value - mp_exc_stack_t *exc_sp; - uint n_state; - // Variable-length - mp_obj_t state[0]; - // Variable-length, never accessed by name, only as (void*)(state + n_state) - //mp_exc_stack_t exc_state[0]; + mp_code_state code_state; } mp_obj_gen_instance_t; void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_gen_instance_t *self = self_in; - print(env, "<generator object '%s' at %p>", mp_obj_code_get_name(self->code_info), self_in); + print(env, "<generator object '%s' at %p>", mp_obj_code_get_name(self->code_state.code_info), self_in); } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance)); mp_obj_gen_instance_t *self = self_in; - if (self->ip == 0) { + if (self->code_state.ip == 0) { *ret_val = MP_OBJ_STOP_ITERATION; return MP_VM_RETURN_NORMAL; } - if (self->sp == self->state - 1) { + if (self->code_state.sp == self->code_state.state - 1) { if (send_value != mp_const_none) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator")); } } else { - *self->sp = send_value; + *self->code_state.sp = send_value; } mp_obj_dict_t *old_globals = mp_globals_get(); mp_globals_set(self->globals); - mp_vm_return_kind_t ret_kind = mp_execute_bytecode2(self->code_info, &self->ip, - &self->state[self->n_state - 1], &self->sp, (mp_exc_stack_t*)(self->state + self->n_state), - &self->exc_sp, throw_value); + mp_vm_return_kind_t ret_kind = mp_execute_bytecode2(&self->code_state, throw_value); mp_globals_set(old_globals); switch (ret_kind) { @@ -127,17 +116,17 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ // again and again, leading to side effects. // TODO: check how return with value behaves under such conditions // in CPython. - self->ip = 0; - *ret_val = *self->sp; + self->code_state.ip = 0; + *ret_val = *self->code_state.sp; break; case MP_VM_RETURN_YIELD: - *ret_val = *self->sp; + *ret_val = *self->code_state.sp; break; case MP_VM_RETURN_EXCEPTION: - self->ip = 0; - *ret_val = self->state[self->n_state - 1]; + self->code_state.ip = 0; + *ret_val = self->code_state.state[self->code_state.n_state - 1]; break; default: @@ -269,32 +258,32 @@ mp_obj_t mp_obj_new_gen_instance(mp_obj_dict_t *globals, const byte *bytecode, mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t)); o->base.type = &mp_type_gen_instance; o->globals = globals; - o->code_info = code_info; - o->sp = &o->state[0] - 1; // sp points to top of stack, which starts off 1 below the state - o->exc_sp = (mp_exc_stack_t*)(o->state + n_state) - 1; - o->n_state = n_state; + o->code_state.code_info = code_info; + o->code_state.sp = &o->code_state.state[0] - 1; // sp points to top of stack, which starts off 1 below the state + o->code_state.exc_sp = (mp_exc_stack_t*)(o->code_state.state + n_state) - 1; + o->code_state.n_state = n_state; // copy args to end of state array, in reverse (that's how mp_execute_bytecode2 needs it) for (uint i = 0; i < n_args; i++) { - o->state[n_state - 1 - i] = args[i]; + o->code_state.state[n_state - 1 - i] = args[i]; } for (uint i = 0; i < n_args2; i++) { - o->state[n_state - 1 - n_args - i] = args2[i]; + o->code_state.state[n_state - 1 - n_args - i] = args2[i]; } // set rest of state to MP_OBJ_NULL for (uint i = 0; i < n_state - n_args - n_args2; i++) { - o->state[i] = MP_OBJ_NULL; + o->code_state.state[i] = MP_OBJ_NULL; } // bytecode prelude: initialise closed over variables for (uint n_local = *bytecode++; n_local > 0; n_local--) { uint local_num = *bytecode++; - o->state[n_state - 1 - local_num] = mp_obj_new_cell(o->state[n_state - 1 - local_num]); + o->code_state.state[n_state - 1 - local_num] = mp_obj_new_cell(o->code_state.state[n_state - 1 - local_num]); } // set ip to start of actual byte code - o->ip = bytecode; + o->code_state.ip = bytecode; return o; } diff --git a/py/objint.c b/py/objint.c index f631d698f3..74b7564550 100644 --- a/py/objint.c +++ b/py/objint.c @@ -41,7 +41,7 @@ #include "runtime0.h" #include "runtime.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #include <math.h> #endif @@ -62,7 +62,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, 0); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0])))); #endif @@ -267,7 +267,7 @@ machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float(mp_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 82db9e6608..dfe069c087 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -188,7 +188,7 @@ machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return mp_obj_int_get(self_in); } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float(mp_obj_t self_in) { if (MP_OBJ_IS_SMALL_INT(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 9cdbb71688..516fb52746 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -118,7 +118,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { zrhs = &z_int; } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) { zrhs = &((mp_obj_int_t*)rhs_in)->mpz; -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_float)) { return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in); } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) { @@ -130,7 +130,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } if (0) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) { mp_float_t flhs = mpz_as_float(zlhs); mp_float_t frhs = mpz_as_float(zrhs); @@ -292,7 +292,7 @@ machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { } } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float(mp_obj_t self_in) { if (MP_OBJ_IS_SMALL_INT(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); diff --git a/py/objlist.c b/py/objlist.c index 647096f0dd..6e22169fd9 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -150,7 +150,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = self_in; mp_bound_slice_t slice; @@ -174,7 +174,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } else if (value == MP_OBJ_SENTINEL) { // load mp_obj_list_t *self = self_in; -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { @@ -188,7 +188,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { uint index_val = mp_get_index(self->base.type, self->len, index, false); return self->items[index_val]; } else { -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = self_in; assert(MP_OBJ_IS_TYPE(value, &mp_type_list)); diff --git a/py/objproperty.c b/py/objproperty.c index 147a755a42..5a9311ac96 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -34,7 +34,7 @@ #include "obj.h" #include "runtime.h" -#if MICROPY_PY_PROPERTY +#if MICROPY_PY_BUILTINS_PROPERTY typedef struct _mp_obj_property_t { mp_obj_base_t base; @@ -115,4 +115,4 @@ const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) { return self->proxy; } -#endif // MICROPY_PY_PROPERTY +#endif // MICROPY_PY_BUILTINS_PROPERTY diff --git a/py/objset.c b/py/objset.c index 6a6a375faa..ab76b57642 100644 --- a/py/objset.c +++ b/py/objset.c @@ -37,6 +37,8 @@ #include "runtime0.h" #include "builtin.h" +#if MICROPY_PY_BUILTINS_SET + typedef struct _mp_obj_set_t { mp_obj_base_t base; mp_set_t set; @@ -52,13 +54,13 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in); STATIC bool is_set_or_frozenset(mp_obj_t o) { return MP_OBJ_IS_TYPE(o, &mp_type_set) -#if MICROPY_PY_FROZENSET +#if MICROPY_PY_BUILTINS_FROZENSET || MP_OBJ_IS_TYPE(o, &mp_type_frozenset) #endif ; } -#if MICROPY_PY_FROZENSET +#if MICROPY_PY_BUILTINS_FROZENSET STATIC void check_set_or_frozenset(mp_obj_t o) { if (!is_set_or_frozenset(o)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'set' object required")); @@ -72,7 +74,7 @@ STATIC void check_set(mp_obj_t o) { if (!MP_OBJ_IS_TYPE(o, &mp_type_set)) { // Emulate CPython behavior // AttributeError: 'frozenset' object has no attribute 'add' - #if MICROPY_PY_FROZENSET + #if MICROPY_PY_BUILTINS_FROZENSET if (MP_OBJ_IS_TYPE(o, &mp_type_frozenset)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "'frozenset' has no such attribute")); } @@ -83,11 +85,11 @@ STATIC void check_set(mp_obj_t o) { STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_set_t *self = self_in; - #if MICROPY_PY_FROZENSET + #if MICROPY_PY_BUILTINS_FROZENSET bool is_frozen = MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset); #endif if (self->set.used == 0) { - #if MICROPY_PY_FROZENSET + #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { print(env, "frozen"); } @@ -96,7 +98,7 @@ STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, return; } bool first = true; - #if MICROPY_PY_FROZENSET + #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { print(env, "frozenset("); } @@ -112,7 +114,7 @@ STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, } } print(env, "}"); - #if MICROPY_PY_FROZENSET + #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { print(env, ")"); } @@ -556,7 +558,7 @@ const mp_obj_type_t mp_type_set = { .locals_dict = (mp_obj_t)&set_locals_dict, }; -#if MICROPY_PY_FROZENSET +#if MICROPY_PY_BUILTINS_FROZENSET const mp_obj_type_t mp_type_frozenset = { { &mp_type_type }, .name = MP_QSTR_frozenset, @@ -584,3 +586,5 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) { mp_obj_set_t *self = self_in; mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } + +#endif // MICROPY_PY_BUILTINS_SET diff --git a/py/objslice.c b/py/objslice.c index dfd070f8d0..6324c0e49b 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -56,7 +56,7 @@ const mp_obj_ellipsis_t mp_const_ellipsis_obj = {{&mp_type_ellipsis}}; /******************************************************************************/ /* slice object */ -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE // TODO: This implements only variant of slice with 2 integer args only. // CPython supports 3rd arg (step), plus args can be arbitrary Python objects. diff --git a/py/objstr.c b/py/objstr.c index 27f6d9cd6f..9ff9106375 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -348,7 +348,7 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) { @@ -741,14 +741,14 @@ static bool arg_looks_integer(mp_obj_t arg) { static bool arg_looks_numeric(mp_obj_t arg) { return arg_looks_integer(arg) -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT || MP_OBJ_IS_TYPE(arg, &mp_type_float) #endif ; } static mp_obj_t arg_as_int(mp_obj_t arg) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) { // TODO: Needs a way to construct an mpz integer from a float @@ -1066,7 +1066,7 @@ mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args) { flags |= PF_FLAG_PAD_NAN_INF; // '{:06e}'.format(float('-inf')) should give '-00inf' switch (type) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': case 'f': @@ -1214,7 +1214,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, ' ', width); break; } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT // This is what CPython reports, so we report the same. if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "integer argument expected, got float")); @@ -1230,7 +1230,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t pfenv_print_mp_int(&pfenv_vstr, arg_as_int(arg), 1, 10, 'a', flags, fill, width); break; -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': case 'f': @@ -1476,73 +1476,47 @@ STATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) { return str_partitioner(self_in, arg, -1); } -enum { CASE_UPPER, CASE_LOWER }; - // Supposedly not too critical operations, so optimize for code size -STATIC mp_obj_t str_caseconv(int op, mp_obj_t self_in) { +STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, self_data, self_len); byte *data; mp_obj_t s = mp_obj_str_builder_start(mp_obj_get_type(self_in), self_len, &data); for (int i = 0; i < self_len; i++) { - if (op == CASE_UPPER) { - *data++ = unichar_toupper(*self_data++); - } else { - *data++ = unichar_tolower(*self_data++); - } + *data++ = op(*self_data++); } *data = 0; return mp_obj_str_builder_end(s); } STATIC mp_obj_t str_lower(mp_obj_t self_in) { - return str_caseconv(CASE_LOWER, self_in); + return str_caseconv(unichar_tolower, self_in); } STATIC mp_obj_t str_upper(mp_obj_t self_in) { - return str_caseconv(CASE_UPPER, self_in); + return str_caseconv(unichar_toupper, self_in); } -enum { IS_SPACE, IS_ALPHA, IS_DIGIT, IS_UPPER, IS_LOWER }; - -STATIC mp_obj_t str_uni_istype(int type, mp_obj_t self_in) { +STATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, self_data, self_len); if (self_len == 0) { return mp_const_false; // default to False for empty str } - typedef bool (*check_function)(unichar); - check_function f; - - if (type != IS_UPPER && type != IS_LOWER) { - switch (type) { - case IS_SPACE: f = &unichar_isspace; break; - case IS_ALPHA: f = &unichar_isalpha; break; - case IS_DIGIT: f = &unichar_isdigit; break; - default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unknown type provided for str_uni_istype")); - } - + if (f != unichar_isupper && f != unichar_islower) { for (int i = 0; i < self_len; i++) { if (!f(*self_data++)) { return mp_const_false; } } } else { - switch (type) { - case IS_UPPER: f = &unichar_isupper; break; - case IS_LOWER: f = &unichar_islower; break; - default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unknown type provided for str_uni_istype")); - } - bool contains_alpha = false; for (int i = 0; i < self_len; i++) { // only check alphanumeric characters if (unichar_isalpha(*self_data++)) { contains_alpha = true; - if (!f(*(self_data-1))) { - return mp_const_false; // we already incremented + if (!f(*(self_data - 1))) { // -1 because we already incremented above + return mp_const_false; } } } @@ -1556,23 +1530,23 @@ STATIC mp_obj_t str_uni_istype(int type, mp_obj_t self_in) { } STATIC mp_obj_t str_isspace(mp_obj_t self_in) { - return str_uni_istype(IS_SPACE, self_in); + return str_uni_istype(unichar_isspace, self_in); } STATIC mp_obj_t str_isalpha(mp_obj_t self_in) { - return str_uni_istype(IS_ALPHA, self_in); + return str_uni_istype(unichar_isalpha, self_in); } STATIC mp_obj_t str_isdigit(mp_obj_t self_in) { - return str_uni_istype(IS_DIGIT, self_in); + return str_uni_istype(unichar_isdigit, self_in); } STATIC mp_obj_t str_isupper(mp_obj_t self_in) { - return str_uni_istype(IS_UPPER, self_in); + return str_uni_istype(unichar_isupper, self_in); } STATIC mp_obj_t str_islower(mp_obj_t self_in) { - return str_uni_istype(IS_LOWER, self_in); + return str_uni_istype(unichar_islower, self_in); } #if MICROPY_CPYTHON_COMPAT diff --git a/py/objtuple.c b/py/objtuple.c index c0a33dad7e..fc97f53cf2 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -161,7 +161,7 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load mp_obj_tuple_t *self = self_in; -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { diff --git a/py/objtype.c b/py/objtype.c index 0561282b8a..ebbb6097dd 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -413,7 +413,7 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_class_lookup(self, self->base.type, attr, 0, dest); mp_obj_t member = dest[0]; if (member != MP_OBJ_NULL) { -#if MICROPY_PY_PROPERTY +#if MICROPY_PY_BUILTINS_PROPERTY if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { // object member is a property // delegate the store to the property @@ -447,7 +447,7 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { STATIC bool instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { mp_obj_instance_t *self = self_in; -#if MICROPY_PY_PROPERTY +#if MICROPY_PY_BUILTINS_PROPERTY // for property, we need to do a lookup first in the class dict // this makes all stores slow... how to fix? mp_obj_t member[2] = {MP_OBJ_NULL}; diff --git a/py/parsenum.c b/py/parsenum.c index 9729ffe64a..2e513e5159 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -36,7 +36,7 @@ #include "parsenum.h" #include "smallint.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #include <math.h> #endif @@ -144,7 +144,7 @@ value_error: #define PARSE_DEC_IN_EXP (3) mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; diff --git a/py/pfenv.c b/py/pfenv.c index c1a2eee0df..e4db4da046 100644 --- a/py/pfenv.c +++ b/py/pfenv.c @@ -39,7 +39,7 @@ #include <stdio.h> #endif -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #include "formatfloat.h" #endif @@ -266,7 +266,7 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int return len; } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec) { char buf[32]; char sign = '\0'; diff --git a/py/pfenv.h b/py/pfenv.h index 4c902c6bc2..2a3de6c32d 100644 --- a/py/pfenv.h +++ b/py/pfenv.h @@ -46,6 +46,6 @@ void pfenv_vstr_add_strn(void *data, const char *str, unsigned int len); int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, char fill, int width); int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width); int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int base_char, int flags, char fill, int width); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec); #endif diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 4ee56db909..69182f2809 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -263,7 +263,7 @@ Q(iterator) Q(module) Q(slice) -#if MICROPY_PY_FROZENSET +#if MICROPY_PY_BUILTINS_FROZENSET Q(frozenset) #endif @@ -375,7 +375,7 @@ Q(disable) Q(enable) #endif -#if MICROPY_PY_PROPERTY +#if MICROPY_PY_BUILTINS_PROPERTY Q(property) Q(getter) Q(setter) diff --git a/py/runtime.c b/py/runtime.c index a9d57460ac..ecaf40deb4 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -353,7 +353,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { lhs_val = mp_small_int_floor_divide(lhs_val, rhs_val); break; - #if MICROPY_ENABLE_FLOAT + #if MICROPY_PY_BUILTINS_FLOAT case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_val == 0) { @@ -371,7 +371,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: if (rhs_val < 0) { - #if MICROPY_ENABLE_FLOAT + #if MICROPY_PY_BUILTINS_FLOAT lhs = mp_obj_new_float(lhs_val); goto generic_binary_op; #else @@ -418,7 +418,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } else { return mp_obj_new_int(lhs_val); } -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_float)) { mp_obj_t res = mp_obj_float_binary_op(op, lhs_val, rhs); if (res == MP_OBJ_NULL) { @@ -1173,8 +1173,10 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_obj_list_append, mp_obj_new_dict, mp_obj_dict_store, +#if MICROPY_PY_BUILTINS_SET mp_obj_new_set, mp_obj_set_store, +#endif mp_make_function_from_raw_code, mp_call_function_n_kw_for_native, mp_call_method_n_kw, @@ -1183,7 +1185,9 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_import_name, mp_import_from, mp_import_all, +#if MICROPY_PY_BUILTINS_SLICE mp_obj_new_slice, +#endif mp_unpack_sequence, mp_unpack_ex, }; diff --git a/py/runtime0.h b/py/runtime0.h index 542edf4a62..eea578237a 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -115,8 +115,10 @@ typedef enum { MP_F_LIST_APPEND, MP_F_BUILD_MAP, MP_F_STORE_MAP, +#if MICROPY_PY_BUILTINS_SET MP_F_BUILD_SET, MP_F_STORE_SET, +#endif MP_F_MAKE_FUNCTION_FROM_RAW_CODE, MP_F_CALL_FUNCTION_N_KW_FOR_NATIVE, MP_F_CALL_METHOD_N_KW, @@ -125,7 +127,9 @@ typedef enum { MP_F_IMPORT_NAME, MP_F_IMPORT_FROM, MP_F_IMPORT_ALL, +#if MICROPY_PY_BUILTINS_SLICE MP_F_NEW_SLICE, +#endif MP_F_UNPACK_SEQUENCE, MP_F_UNPACK_EX, MP_F_NUMBER_OF, diff --git a/py/sequence.c b/py/sequence.c index c940d9f69f..c73f3baba1 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -51,6 +51,8 @@ void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void } } +#if MICROPY_PY_BUILTINS_SLICE + bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) { mp_obj_t ostart, ostop, ostep; machine_int_t start, stop; @@ -102,6 +104,8 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_ return true; } +#endif + mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes) { machine_int_t start = indexes->start, stop = indexes->stop; machine_int_t step = indexes->step; diff --git a/py/showbc.c b/py/showbc.c index 33c59dcba9..fc02f4c580 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -419,7 +419,7 @@ void mp_bytecode_print2(const byte *ip, int len) { printf("SET_ADD " UINT_FMT, unum); break; -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE case MP_BC_BUILD_SLICE: DECODE_UINT; printf("BUILD_SLICE " UINT_FMT, unum); @@ -28,6 +28,7 @@ #include <stdio.h> #include <string.h> #include <assert.h> +#include <alloca.h> #include "mpconfig.h" #include "nlr.h" @@ -40,11 +41,10 @@ #include "bc.h" #include "objgenerator.h" -// With these macros you can tune the maximum number of state slots +// With these macros you can tune the maximum number of function state bytes // that will be allocated on the stack. Any function that needs more // than this will use the heap. -#define VM_MAX_STATE_ON_STACK (10) -#define VM_MAX_EXC_STATE_ON_STACK (4) +#define VM_MAX_STATE_ON_STACK (10 * sizeof(machine_uint_t)) #define DETECT_VM_STACK_OVERFLOW (0) #if 0 @@ -93,7 +93,7 @@ typedef enum { #define PUSH_EXC_BLOCK() \ DECODE_ULABEL; /* except labels are always forward */ \ ++exc_sp; \ - exc_sp->opcode = *save_ip; \ + exc_sp->opcode = *code_state->ip; \ exc_sp->handler = ip + unum; \ exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \ exc_sp->prev_exc = MP_OBJ_NULL; \ @@ -117,47 +117,54 @@ mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, ip += 4; // allocate state for locals and stack - mp_obj_t temp_state[VM_MAX_STATE_ON_STACK]; - mp_obj_t *state = &temp_state[0]; #if DETECT_VM_STACK_OVERFLOW n_state += 1; #endif - if (n_state > VM_MAX_STATE_ON_STACK) { - state = m_new(mp_obj_t, n_state); - } - mp_obj_t *sp = &state[0] - 1; - // allocate state for exceptions - mp_exc_stack_t exc_state[VM_MAX_EXC_STATE_ON_STACK]; - mp_exc_stack_t *exc_stack = &exc_state[0]; - if (n_exc_stack > VM_MAX_EXC_STATE_ON_STACK) { - exc_stack = m_new(mp_exc_stack_t, n_exc_stack); + int state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); + mp_code_state *code_state; + if (state_size > VM_MAX_STATE_ON_STACK) { + code_state = m_new_obj_var(mp_code_state, byte, state_size); + } else { + code_state = alloca(sizeof(mp_code_state) + state_size); } - mp_exc_stack_t *exc_sp = &exc_stack[0] - 1; + + code_state->code_info = code; + code_state->sp = &code_state->state[0] - 1; + code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1; + code_state->n_state = n_state; // init args for (uint i = 0; i < n_args; i++) { - state[n_state - 1 - i] = args[i]; + code_state->state[n_state - 1 - i] = args[i]; } for (uint i = 0; i < n_args2; i++) { - state[n_state - 1 - n_args - i] = args2[i]; + code_state->state[n_state - 1 - n_args - i] = args2[i]; } // set rest of state to MP_OBJ_NULL for (uint i = 0; i < n_state - n_args - n_args2; i++) { - state[i] = MP_OBJ_NULL; + code_state->state[i] = MP_OBJ_NULL; } // bytecode prelude: initialise closed over variables for (uint n_local = *ip++; n_local > 0; n_local--) { uint local_num = *ip++; - state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]); + code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]); } + code_state->ip = ip; + // execute the byte code - mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp, MP_OBJ_NULL); + mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode2(code_state, MP_OBJ_NULL); #if DETECT_VM_STACK_OVERFLOW + if (vm_return_kind == MP_VM_RETURN_NORMAL) { + if (code_state->sp < code_state->state) { + printf("VM stack underflow: " INT_FMT "\n", code_state->sp - code_state->state); + assert(0); + } + } // We can't check the case when an exception is returned in state[n_state - 1] // and there are no arguments, because in this case our detection slot may have // been overwritten by the returned exception (which is allowed). @@ -165,13 +172,13 @@ mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, // Just check to see that we have at least 1 null object left in the state. bool overflow = true; for (uint i = 0; i < n_state - n_args - n_args2; i++) { - if (state[i] == MP_OBJ_NULL) { + if (code_state->state[i] == MP_OBJ_NULL) { overflow = false; break; } } if (overflow) { - printf("VM stack overflow state=%p n_state+1=%u\n", state, n_state); + printf("VM stack overflow state=%p n_state+1=" UINT_FMT "\n", code_state->state, n_state); assert(0); } } @@ -181,13 +188,13 @@ mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, switch (vm_return_kind) { case MP_VM_RETURN_NORMAL: // return value is in *sp - *ret = *sp; + *ret = *code_state->sp; ret_kind = MP_VM_RETURN_NORMAL; break; case MP_VM_RETURN_EXCEPTION: // return value is in state[n_state - 1] - *ret = state[n_state - 1]; + *ret = code_state->state[n_state - 1]; ret_kind = MP_VM_RETURN_EXCEPTION; break; @@ -196,18 +203,13 @@ mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, assert(0); *ret = mp_const_none; ret_kind = MP_VM_RETURN_NORMAL; + break; } // free the state if it was allocated on the heap - if (n_state > VM_MAX_STATE_ON_STACK) { - m_free(state, n_state); - } - - // free the exception state if it was allocated on the heap - if (n_exc_stack > VM_MAX_EXC_STATE_ON_STACK) { - m_free(exc_stack, n_exc_stack); + if (state_size > VM_MAX_STATE_ON_STACK) { + m_del_var(mp_code_state, byte, state_size, code_state); } - return ret_kind; } @@ -217,15 +219,12 @@ mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, // MP_VM_RETURN_NORMAL, sp valid, return value in *sp // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp // MP_VM_RETURN_EXCEPTION, exception in fastn[0] -mp_vm_return_kind_t mp_execute_bytecode2(const byte *code_info, const byte **ip_in_out, - mp_obj_t *fastn, mp_obj_t **sp_in_out, - mp_exc_stack_t *exc_stack, mp_exc_stack_t **exc_sp_in_out, - volatile mp_obj_t inject_exc) { +mp_vm_return_kind_t mp_execute_bytecode2(mp_code_state *code_state, volatile mp_obj_t inject_exc) { #if MICROPY_OPT_COMPUTED_GOTO #include "vmentrytable.h" #define DISPATCH() do { \ TRACE(ip); \ - save_ip = ip; \ + code_state->ip = ip; \ goto *entry_table[*ip++]; \ } while(0) #define ENTRY(op) entry_##op @@ -242,11 +241,13 @@ mp_vm_return_kind_t mp_execute_bytecode2(const byte *code_info, const byte **ip_ // loop and the exception handler, leading to very obscure bugs. #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0) + // Pointers which are constant for particular invocation of mp_execute_bytecode2() + mp_obj_t *const fastn = &code_state->state[code_state->n_state - 1]; + mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state); + // variables that are visible to the exception handler (declared volatile) - volatile bool currently_in_except_block = MP_TAGPTR_TAG(*exc_sp_in_out); // 0 or 1, to detect nested exceptions - mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(*exc_sp_in_out); // stack grows up, exc_sp points to top of stack - const byte *volatile save_ip = *ip_in_out; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop) - mp_obj_t *volatile save_sp = *sp_in_out; // this is so we can access sp in the exception handler when needed + volatile bool currently_in_except_block = MP_TAGPTR_TAG(code_state->exc_sp); // 0 or 1, to detect nested exceptions + mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack // outer exception handling loop for (;;) { @@ -254,8 +255,8 @@ mp_vm_return_kind_t mp_execute_bytecode2(const byte *code_info, const byte **ip_ outer_dispatch_loop: if (nlr_push(&nlr) == 0) { // local variables that are not visible to the exception handler - const byte *ip = *ip_in_out; - mp_obj_t *sp = *sp_in_out; + const byte *ip = code_state->ip; + mp_obj_t *sp = code_state->sp; machine_uint_t unum; mp_obj_t obj_shared; @@ -278,7 +279,7 @@ dispatch_loop: DISPATCH(); #else TRACE(ip); - save_ip = ip; + code_state->ip = ip; switch (*ip++) { #endif @@ -683,7 +684,7 @@ unwind_jump: ENTRY(MP_BC_FOR_ITER): { DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward - save_sp = sp; + code_state->sp = sp; assert(TOP()); mp_obj_t value = mp_iternext_allow_raise(TOP()); if (value == MP_OBJ_STOP_ITERATION) { @@ -771,6 +772,7 @@ unwind_jump: sp -= 2; DISPATCH(); +#if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): DECODE_UINT; sp -= unum - 1; @@ -783,8 +785,9 @@ unwind_jump: mp_obj_set_store(sp[-unum], sp[0]); sp--; DISPATCH(); +#endif -#if MICROPY_PY_SLICE +#if MICROPY_PY_BUILTINS_SLICE ENTRY(MP_BC_BUILD_SLICE): DECODE_UINT; if (unum == 2) { @@ -898,7 +901,7 @@ unwind_return: exc_sp--; } nlr_pop(); - *sp_in_out = sp; + code_state->sp = sp; assert(exc_sp == exc_stack - 1); return MP_VM_RETURN_NORMAL; @@ -929,9 +932,9 @@ unwind_return: ENTRY(MP_BC_YIELD_VALUE): yield: nlr_pop(); - *ip_in_out = ip; - *sp_in_out = sp; - *exc_sp_in_out = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block); + code_state->ip = ip; + code_state->sp = sp; + code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block); return MP_VM_RETURN_YIELD; ENTRY(MP_BC_YIELD_FROM): { @@ -1021,12 +1024,12 @@ exception_handler: // exception occurred // check if it's a StopIteration within a for block - if (*save_ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) { - const byte *ip = save_ip + 1; + if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) { + const byte *ip = code_state->ip + 1; machine_uint_t unum; DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward - *ip_in_out = ip + unum; // jump to after for-block - *sp_in_out = save_sp - 1; // pop the exhausted iterator + code_state->ip = ip + unum; // jump to after for-block + code_state->sp -= 1; // pop the exhausted iterator goto outer_dispatch_loop; // continue with dispatch loop } @@ -1035,11 +1038,12 @@ exception_handler: // But consider how to handle nested exceptions. // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj) if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) { + const byte *code_info = code_state->code_info; machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24); qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24); qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24); machine_uint_t source_line = 1; - machine_uint_t bc = save_ip - code_info - code_info_size; + machine_uint_t bc = code_state->ip - code_info - code_info_size; //printf("find %lu %d %d\n", bc, code_info[12], code_info[13]); for (const byte* ci = code_info + 12; *ci && bc >= ((*ci) & 31); ci++) { bc -= *ci & 31; @@ -1065,7 +1069,7 @@ exception_handler: currently_in_except_block = 1; // catch exception and pass to byte code - *ip_in_out = exc_sp->handler; + code_state->ip = exc_sp->handler; mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp); // save this exception in the stack so it can be used in a reraise, if needed exc_sp->prev_exc = nlr.ret_val; @@ -1073,7 +1077,7 @@ exception_handler: PUSH(mp_const_none); PUSH(nlr.ret_val); PUSH(mp_obj_get_type(nlr.ret_val)); - *sp_in_out = sp; + code_state->sp = sp; } else { // propagate exception to higher level diff --git a/stmhal/accel.c b/stmhal/accel.c index 85c1815636..cfc80f9d3c 100644 --- a/stmhal/accel.c +++ b/stmhal/accel.c @@ -43,9 +43,13 @@ /// \moduleref pyb /// \class Accel - accelerometer control /// -/// Accel is an object that controls the accelerometer. +/// Accel is an object that controls the accelerometer. Example usage: /// -/// Raw values are between -30 and 30. +/// accel = pyb.Accel() +/// for i in range(10): +/// print(accel.x(), accel.y(), accel.z()) +/// +/// Raw values are between -32 and 31. #define MMA_ADDR (0x98) #define MMA_REG_X (0) @@ -118,6 +122,15 @@ STATIC pyb_accel_obj_t pyb_accel_obj; /// \classmethod \constructor() /// Create and return an accelerometer object. +/// +/// Note: if you read accelerometer values immediately after creating this object +/// you will get 0. It takes around 20ms for the first sample to be ready, so, +/// unless you have some other code between creating this object and reading its +/// values, you should put a `pyb.delay(20)` after creating it. For example: +/// +/// accel = pyb.Accel() +/// pyb.delay(20) +/// print(accel.x()) STATIC mp_obj_t pyb_accel_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); diff --git a/stmhal/boards/stm32f4xx-af.csv b/stmhal/boards/stm32f4xx-af.csv index 5746ac8cc9..466be06002 100644 --- a/stmhal/boards/stm32f4xx-af.csv +++ b/stmhal/boards/stm32f4xx-af.csv @@ -1,4 +1,4 @@ -Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15 +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,,ADC PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT,ADC123_IN1 diff --git a/stmhal/modtime.c b/stmhal/modtime.c index 2e50a58df1..4fbee31293 100644 --- a/stmhal/modtime.c +++ b/stmhal/modtime.c @@ -74,11 +74,11 @@ STATIC mp_obj_t time_localtime(void) { MP_DEFINE_CONST_FUN_OBJ_0(time_localtime_obj, time_localtime); STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT if (MP_OBJ_IS_INT(seconds_o)) { #endif HAL_Delay(1000 * mp_obj_get_int(seconds_o)); -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT } else { HAL_Delay((uint32_t)(1000 * mp_obj_get_float(seconds_o))); } diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 33b81336ca..36a60dfa7c 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -44,7 +44,7 @@ */ #define MICROPY_ENABLE_LFN (1) #define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_PY_FROZENSET (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_CMATH (1) diff --git a/stmhal/printf.c b/stmhal/printf.c index 3f88a9c5aa..6cfeda2637 100644 --- a/stmhal/printf.c +++ b/stmhal/printf.c @@ -41,7 +41,7 @@ #include "uart.h" #include "usb.h" -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT #include "formatfloat.h" #endif @@ -162,7 +162,7 @@ int pfenv_printf(const pfenv_t *pfenv, const char *fmt, va_list args) { case 'P': // ? chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, fill, width); break; -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': case 'f': diff --git a/stmhal/servo.c b/stmhal/servo.c index e44e129ef4..3da445fa8d 100644 --- a/stmhal/servo.c +++ b/stmhal/servo.c @@ -271,7 +271,7 @@ STATIC mp_obj_t pyb_servo_angle(uint n_args, const mp_obj_t *args) { // get angle return mp_obj_new_int((self->pulse_cur - self->pulse_centre) * 90 / self->pulse_angle_90); } else { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT self->pulse_dest = self->pulse_centre + self->pulse_angle_90 * mp_obj_get_float(args[1]) / 90.0; #else self->pulse_dest = self->pulse_centre + self->pulse_angle_90 * mp_obj_get_int(args[1]) / 90; @@ -301,7 +301,7 @@ STATIC mp_obj_t pyb_servo_speed(uint n_args, const mp_obj_t *args) { // get speed return mp_obj_new_int((self->pulse_cur - self->pulse_centre) * 100 / self->pulse_speed_100); } else { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT self->pulse_dest = self->pulse_centre + self->pulse_speed_100 * mp_obj_get_float(args[1]) / 100.0; #else self->pulse_dest = self->pulse_centre + self->pulse_speed_100 * mp_obj_get_int(args[1]) / 100; diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h index c01f13a6dd..f7c66d8874 100644 --- a/teensy/mpconfigport.h +++ b/teensy/mpconfigport.h @@ -6,7 +6,7 @@ #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_HELPER_REPL (1) -#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_PY_BUILTINS_FLOAT (1) // type definitions for the specific machine diff --git a/tests/basics/for_break.py b/tests/basics/for_break.py index fa8dabd150..f8bb0578e2 100644 --- a/tests/basics/for_break.py +++ b/tests/basics/for_break.py @@ -13,3 +13,15 @@ def foo(): i -= 1 foo() + +# break from within nested for loop +def bar(): + l = [1, 2, 3] + for e1 in l: + print(e1) + for e2 in l: + print(e1, e2) + if e2 == 2: + break + +bar() diff --git a/tests/basics/for_return.py b/tests/basics/for_return.py new file mode 100644 index 0000000000..0441352ad9 --- /dev/null +++ b/tests/basics/for_return.py @@ -0,0 +1,7 @@ +# test returning from within a for loop + +def f(): + for i in [1, 2, 3]: + return i + +print(f()) diff --git a/tests/micropython/heapalloc.py b/tests/micropython/heapalloc.py new file mode 100644 index 0000000000..c62428a084 --- /dev/null +++ b/tests/micropython/heapalloc.py @@ -0,0 +1,26 @@ +# check that we can do certain things without allocating heap memory + +import gc + +def f(a): + print(a) + +def g(a, b=2): + print(a, b) + +global_var = 1 + +def h(): + global global_var + global_var = 2 # set an existing global variable + for i in range(2): # for loop + f(i) # function call + f(i * 2 + 1) # binary operation with small ints + f(a=i) # keyword arguments + g(i) # default arg (second one) + g(i, i) # 2 args + +# call h with heap allocation disabled +gc.disable() +h() +gc.enable() diff --git a/tests/run-tests b/tests/run-tests index 102655abea..1e6dd50538 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -111,6 +111,7 @@ def run_tests(pyb, tests): def main(): cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.') cmd_parser.add_argument('--pyboard', action='store_true', help='run the tests on the pyboard') + cmd_parser.add_argument('-d', '--test-dirs', nargs='*', help='input test directories (if no files given)') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() @@ -122,12 +123,16 @@ def main(): pyb = None if len(args.files) == 0: - if pyb is None: - # run PC tests - test_dirs = ('basics', 'micropython', 'float', 'import', 'io', 'misc') + if args.test_dirs is None: + if pyb is None: + # run PC tests + test_dirs = ('basics', 'micropython', 'float', 'import', 'io', 'misc') + else: + # run pyboard tests + test_dirs = ('basics', 'float', 'pyb', 'pybnative', 'inlineasm') else: - # run pyboard tests - test_dirs = ('basics', 'float', 'pyb', 'pybnative', 'inlineasm') + # run tests from these directories + test_dirs = args.test_dirs tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files) else: # tests explicitly given diff --git a/unix/modtime.c b/unix/modtime.c index 77d2945b8f..f957b96784 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -64,7 +64,7 @@ void msec_sleep_tv(struct timeval *tv) { #endif STATIC mp_obj_t mod_time_time() { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; gettimeofday(&tv, NULL); mp_float_t val = tv.tv_sec + (mp_float_t)tv.tv_usec / 1000000; @@ -77,7 +77,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time); // Note: this is deprecated since CPy3.3, but pystone still uses it. STATIC mp_obj_t mod_time_clock() { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT // float cannot represent full range of int32 precisely, so we pre-divide // int to reduce resolution, and then actually do float division hoping // to preserve integer part resolution. @@ -89,7 +89,7 @@ STATIC mp_obj_t mod_time_clock() { STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { -#if MICROPY_ENABLE_FLOAT +#if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; mp_float_t val = mp_obj_get_float(arg); double ipart; diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index c56c9fa1a6..1b1d938a84 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -41,7 +41,7 @@ #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_OPT_COMPUTED_GOTO (1) -#define MICROPY_PY_FROZENSET (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_CMATH (1) diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h index 0ac715f405..94304e20d2 100644 --- a/windows/mpconfigport.h +++ b/windows/mpconfigport.h @@ -39,7 +39,7 @@ #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_PY_FROZENSET (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_EXIT (1) |