diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/argcheck.c | 16 | ||||
-rw-r--r-- | py/asmthumb.c | 9 | ||||
-rw-r--r-- | py/bc.c | 9 | ||||
-rw-r--r-- | py/bc0.h | 4 | ||||
-rw-r--r-- | py/builtinevex.c | 2 | ||||
-rw-r--r-- | py/builtinimport.c | 10 | ||||
-rw-r--r-- | py/compile.c | 83 | ||||
-rw-r--r-- | py/emit.h | 8 | ||||
-rw-r--r-- | py/emitbc.c | 73 | ||||
-rw-r--r-- | py/emitcommon.c | 16 | ||||
-rw-r--r-- | py/emitglue.c | 2 | ||||
-rw-r--r-- | py/emitnative.c | 67 | ||||
-rw-r--r-- | py/lexer.c | 15 | ||||
-rw-r--r-- | py/makeqstrdefs.py | 2 | ||||
-rw-r--r-- | py/misc.h | 11 | ||||
-rw-r--r-- | py/mkenv.mk | 2 | ||||
-rw-r--r-- | py/mkrules.mk | 6 | ||||
-rw-r--r-- | py/modarray.c | 1 | ||||
-rw-r--r-- | py/modbuiltins.c | 12 | ||||
-rw-r--r-- | py/modcmath.c | 1 | ||||
-rw-r--r-- | py/modcollections.c | 1 | ||||
-rw-r--r-- | py/modgc.c | 1 | ||||
-rw-r--r-- | py/modio.c | 3 | ||||
-rw-r--r-- | py/modmath.c | 1 | ||||
-rw-r--r-- | py/modmicropython.c | 13 | ||||
-rw-r--r-- | py/modstruct.c | 5 | ||||
-rw-r--r-- | py/modsys.c | 1 | ||||
-rw-r--r-- | py/modthread.c | 5 | ||||
-rw-r--r-- | py/moduerrno.c | 1 | ||||
-rw-r--r-- | py/mpconfig.h | 6 | ||||
-rw-r--r-- | py/mphal.h | 4 | ||||
-rw-r--r-- | py/mpprint.c | 4 | ||||
-rw-r--r-- | py/mpz.c | 41 | ||||
-rw-r--r-- | py/mpz.h | 1 | ||||
-rw-r--r-- | py/obj.c | 31 | ||||
-rw-r--r-- | py/obj.h | 1 | ||||
-rw-r--r-- | py/objarray.c | 4 | ||||
-rw-r--r-- | py/objbool.c | 23 | ||||
-rw-r--r-- | py/objcomplex.c | 4 | ||||
-rw-r--r-- | py/objdict.c | 17 | ||||
-rw-r--r-- | py/objfloat.c | 2 | ||||
-rw-r--r-- | py/objfun.c | 33 | ||||
-rw-r--r-- | py/objgenerator.c | 6 | ||||
-rw-r--r-- | py/objint.c | 26 | ||||
-rw-r--r-- | py/objint.h | 8 | ||||
-rw-r--r-- | py/objint_longlong.c | 2 | ||||
-rw-r--r-- | py/objint_mpz.c | 13 | ||||
-rw-r--r-- | py/objlist.c | 2 | ||||
-rw-r--r-- | py/objmodule.c | 13 | ||||
-rw-r--r-- | py/objnamedtuple.c | 2 | ||||
-rw-r--r-- | py/objnone.c | 11 | ||||
-rw-r--r-- | py/objobject.c | 3 | ||||
-rw-r--r-- | py/objset.c | 31 | ||||
-rw-r--r-- | py/objstr.c | 5 | ||||
-rw-r--r-- | py/objstringio.c | 14 | ||||
-rw-r--r-- | py/objstringio.h | 38 | ||||
-rw-r--r-- | py/objtype.c | 21 | ||||
-rw-r--r-- | py/parse.c | 23 | ||||
-rw-r--r-- | py/parsenum.c | 4 | ||||
-rw-r--r-- | py/py.mk | 9 | ||||
-rw-r--r-- | py/qstr.c | 1 | ||||
-rw-r--r-- | py/runtime.c | 58 | ||||
-rw-r--r-- | py/runtime.h | 5 | ||||
-rw-r--r-- | py/scope.c | 89 | ||||
-rw-r--r-- | py/scope.h | 21 | ||||
-rw-r--r-- | py/sequence.c | 2 | ||||
-rw-r--r-- | py/showbc.c | 24 | ||||
-rw-r--r-- | py/stream.c | 24 | ||||
-rw-r--r-- | py/vm.c | 97 | ||||
-rw-r--r-- | py/vmentrytable.h | 4 | ||||
-rw-r--r-- | py/vstr.c | 69 |
71 files changed, 515 insertions, 661 deletions
diff --git a/py/argcheck.c b/py/argcheck.c index 5733c77f1d..8cef10b165 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -37,8 +37,7 @@ void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "function does not take keyword arguments")); + mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments"); } } @@ -105,10 +104,9 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n out_vals[i].u_bool = mp_obj_is_true(given_arg); } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_INT) { out_vals[i].u_int = mp_obj_get_int(given_arg); - } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ) { - out_vals[i].u_obj = given_arg; } else { - assert(0); + assert((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ); + out_vals[i].u_obj = given_arg; } } if (pos_found < n_pos) { @@ -117,8 +115,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n mp_arg_error_terse_mismatch(); } else { // TODO better error message - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "extra positional arguments given")); + mp_raise_msg(&mp_type_TypeError, "extra positional arguments given"); } } if (kws_found < kws->used) { @@ -126,8 +123,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n mp_arg_error_terse_mismatch(); } else { // TODO better error message - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "extra keyword arguments given")); + mp_raise_msg(&mp_type_TypeError, "extra keyword arguments given"); } } } @@ -140,7 +136,7 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER NORETURN void mp_arg_error_terse_mismatch(void) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "argument num/types mismatch")); + mp_raise_msg(&mp_type_TypeError, "argument num/types mismatch"); } #endif diff --git a/py/asmthumb.c b/py/asmthumb.c index 8341c958e9..1aae3d38eb 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -90,6 +90,15 @@ void asm_thumb_start_pass(asm_thumb_t *as, uint pass) { void asm_thumb_end_pass(asm_thumb_t *as) { (void)as; // could check labels are resolved... + + #if defined(MCU_SERIES_F7) + if (as->pass == ASM_THUMB_PASS_EMIT) { + // flush D-cache, so the code emited is stored in memory + SCB_CleanDCache_by_Addr((uint32_t*)as->code_base, as->code_size); + // invalidate I-cache + SCB_InvalidateICache(); + } + #endif } // all functions must go through this one to emit bytes @@ -185,7 +185,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz } // Didn't find name match with positional args if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); + mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments"); } mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]); continue2:; @@ -234,8 +234,7 @@ continue2:; } else { // no keyword arguments given if (n_kwonly_args != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "function missing keyword-only argument")); + mp_raise_msg(&mp_type_TypeError, "function missing keyword-only argument"); } if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) { *var_pos_kw_args = mp_obj_new_dict(0); @@ -308,8 +307,8 @@ STATIC const byte opcode_format_table[64] = { OC4(B, B, O, U), // 0x44-0x47 OC4(U, U, U, U), // 0x48-0x4b OC4(U, U, U, U), // 0x4c-0x4f - OC4(V, V, V, V), // 0x50-0x53 - OC4(B, V, V, V), // 0x54-0x57 + OC4(V, V, U, V), // 0x50-0x53 + OC4(B, U, V, V), // 0x54-0x57 OC4(V, V, V, B), // 0x58-0x5b OC4(B, B, B, U), // 0x5c-0x5f OC4(V, V, V, V), // 0x60-0x63 @@ -82,13 +82,11 @@ #define MP_BC_BUILD_TUPLE (0x50) // uint #define MP_BC_BUILD_LIST (0x51) // uint -#define MP_BC_LIST_APPEND (0x52) // uint #define MP_BC_BUILD_MAP (0x53) // uint #define MP_BC_STORE_MAP (0x54) -#define MP_BC_MAP_ADD (0x55) // uint #define MP_BC_BUILD_SET (0x56) // uint -#define MP_BC_SET_ADD (0x57) // uint #define MP_BC_BUILD_SLICE (0x58) // uint +#define MP_BC_STORE_COMP (0x57) // uint #define MP_BC_UNPACK_SEQUENCE (0x59) // uint #define MP_BC_UNPACK_EX (0x5a) // uint diff --git a/py/builtinevex.c b/py/builtinevex.c index 74c43b1768..636f869300 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -95,7 +95,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break; case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad compile mode")); + mp_raise_msg(&mp_type_ValueError, "bad compile mode"); } mp_obj_code_t *code = m_new_obj(mp_obj_code_t); diff --git a/py/builtinimport.c b/py/builtinimport.c index ef3545d653..e72eaf4724 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -138,7 +138,7 @@ STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex, const char if (lex == NULL) { // we verified the file exists using stat, but lexer could still fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found")); + mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%s'", fname)); @@ -340,7 +340,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("Warning: no dots in current module name and level>0\n"); p = this_name + this_name_l; } else if (level != -1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "Invalid relative import")); + mp_raise_msg(&mp_type_ImportError, "invalid relative import"); } uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); @@ -355,7 +355,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); if (new_mod_q == MP_QSTR_) { // CPython raises SystemError - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "cannot perform relative import")); + mp_raise_msg(&mp_type_ImportError, "cannot perform relative import"); } module_name = MP_OBJ_NEW_QSTR(new_mod_q); mod_str = new_mod; @@ -425,7 +425,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #endif // couldn't find the file, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found")); + mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%q'", mod_name)); @@ -448,6 +448,8 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj); mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); #if MICROPY_CPYTHON_COMPAT + // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules). + mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj); // Store real name in "__main__" attribute. Choosen semi-randonly, to reuse existing qstr's. mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name)); #endif diff --git a/py/compile.c b/py/compile.c index c8b4e5470d..f84d5e2145 100644 --- a/py/compile.c +++ b/py/compile.c @@ -499,8 +499,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ // sequence of many items uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2); c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes); - } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) { - // TODO can we ever get here? can it be compiled? + } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { goto cannot_assign; } else { // sequence with 2 items @@ -900,8 +899,7 @@ STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { for (int i = 0; i < n; i++) { c_del_stmt(comp, pns1->nodes[i]); } - } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) { - // TODO not implemented; can't del comprehension? can we get here? + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) { goto cannot_delete; } else { // sequence with 2 items @@ -1172,17 +1170,14 @@ STATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) { bool added; id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added); - if (!added && id_info->kind != ID_INFO_KIND_FREE) { + if (added) { + scope_find_local_and_close_over(comp->scope_cur, id_info, qst); + if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { + compile_syntax_error(comp, pn, "no binding for nonlocal found"); + } + } else if (id_info->kind != ID_INFO_KIND_FREE) { compile_syntax_error(comp, pn, "identifier redefined as nonlocal"); - return; - } - id_info_t *id_info2 = scope_find_local_in_parent(comp->scope_cur, qst); - if (id_info2 == NULL || !(id_info2->kind == ID_INFO_KIND_LOCAL || id_info2->kind == ID_INFO_KIND_CELL || id_info2->kind == ID_INFO_KIND_FREE)) { - compile_syntax_error(comp, pn, "no binding for nonlocal found"); - return; } - id_info->kind = ID_INFO_KIND_FREE; - scope_close_over_in_parents(comp->scope_cur, qst); } STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { @@ -1495,6 +1490,8 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ EMIT_ARG(label_assign, l1); // start of exception handler EMIT(start_except_handler); + // at this point the top of the stack contains the exception instance that was raised + uint l2 = comp_next_label(comp); for (int i = 0; i < n_except; i++) { @@ -1528,16 +1525,13 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ EMIT_ARG(pop_jump_if, false, end_finally_label); } - EMIT(pop_top); - + // either discard or store the exception instance if (qstr_exception_local == 0) { EMIT(pop_top); } else { compile_store_id(comp, qstr_exception_local); } - EMIT(pop_top); - uint l3 = 0; if (qstr_exception_local != 0) { l3 = comp_next_label(comp); @@ -1561,7 +1555,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ } EMIT_ARG(jump, l2); EMIT_ARG(label_assign, end_finally_label); - EMIT_ARG(adjust_stack_size, 3); // stack adjust for the 3 exception items + EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance } compile_decrease_except_level(comp); @@ -1711,14 +1705,12 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration); EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH); EMIT_ARG(pop_jump_if, false, try_finally_label); - EMIT(pop_top); - EMIT(pop_top); - EMIT(pop_top); + EMIT(pop_top); // pop exception instance EMIT(pop_except); EMIT_ARG(jump, while_else_label); EMIT_ARG(label_assign, try_finally_label); - EMIT_ARG(adjust_stack_size, 3); + EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack compile_decrease_except_level(comp); EMIT(end_finally); EMIT(end_except_handler); @@ -1779,9 +1771,21 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod EMIT_ARG(label_assign, try_exception_label); // start of exception handler EMIT(start_except_handler); - EMIT(rot_three); + + // at this point the stack contains: ..., __aexit__, self, exc + EMIT(dup_top); + #if MICROPY_CPYTHON_COMPAT + EMIT_ARG(load_attr, MP_QSTR___class__); // get type(exc) + #else + compile_load_id(comp, MP_QSTR_type); + EMIT(rot_two); + EMIT_ARG(call_function, 1, 0, 0); // get type(exc) + #endif EMIT(rot_two); + EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value + // at this point the stack contains: ..., __aexit__, self, type(exc), exc, None EMIT_ARG(call_method, 3, 0, 0); + compile_yield_from(comp); EMIT_ARG(pop_jump_if, true, no_reraise_label); EMIT_ARG(raise_varargs, 0); @@ -1790,7 +1794,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod EMIT(pop_except); EMIT_ARG(jump, end_label); - EMIT_ARG(adjust_stack_size, 5); + EMIT_ARG(adjust_stack_size, 3); // adjust for __aexit__, self, exc compile_decrease_except_level(comp); EMIT(end_finally); EMIT(end_except_handler); @@ -2719,15 +2723,8 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; EMIT_ARG(set_source_line, pns->source_line); compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)]; - if (f == NULL) { -#if MICROPY_DEBUG_PRINTERS - printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns)); - mp_parse_node_print(pn, 0); -#endif - compile_syntax_error(comp, pn, "internal compiler error"); - } else { - f(comp, pns); - } + assert(f != NULL); + f(comp, pns); } } @@ -2832,12 +2829,10 @@ STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) // no annotation return; } - } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star) { + } else { + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star); // double star with possible annotation // fallthrough - } else { - // no annotation - return; } mp_parse_node_t pn_annotation = pns->nodes[1]; @@ -2869,17 +2864,11 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn if (MP_PARSE_NODE_IS_NULL(pn_iter)) { // no more nested if/for; compile inner expression compile_node(comp, pn_inner_expr); - if (comp->scope_cur->kind == SCOPE_LIST_COMP) { - EMIT_ARG(list_append, for_depth + 2); - } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) { - EMIT_ARG(map_add, for_depth + 2); - #if MICROPY_PY_BUILTINS_SET - } else if (comp->scope_cur->kind == SCOPE_SET_COMP) { - EMIT_ARG(set_add, for_depth + 2); - #endif - } else { + if (comp->scope_cur->kind == SCOPE_GEN_EXPR) { EMIT(yield_value); EMIT(pop_top); + } else { + EMIT_ARG(store_comp, comp->scope_cur->kind, for_depth + 2); } } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { // if condition @@ -3285,7 +3274,7 @@ STATIC void scope_compute_things(scope_t *scope) { // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL continue; } - if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { + if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; } // params always count for 1 local, even if they are a cell @@ -119,17 +119,15 @@ typedef struct _emit_method_table_t { void (*binary_op)(emit_t *emit, mp_binary_op_t op); void (*build_tuple)(emit_t *emit, mp_uint_t n_args); void (*build_list)(emit_t *emit, mp_uint_t n_args); - void (*list_append)(emit_t *emit, mp_uint_t list_stack_index); void (*build_map)(emit_t *emit, mp_uint_t n_args); void (*store_map)(emit_t *emit); - void (*map_add)(emit_t *emit, mp_uint_t map_stack_index); #if MICROPY_PY_BUILTINS_SET void (*build_set)(emit_t *emit, mp_uint_t n_args); - void (*set_add)(emit_t *emit, mp_uint_t set_stack_index); #endif #if MICROPY_PY_BUILTINS_SLICE void (*build_slice)(emit_t *emit, mp_uint_t n_args); #endif + void (*store_comp)(emit_t *emit, scope_kind_t kind, mp_uint_t set_stack_index); void (*unpack_sequence)(emit_t *emit, mp_uint_t n_args); void (*unpack_ex)(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void (*make_function)(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); @@ -240,17 +238,15 @@ void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op); void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op); void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args); -void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index); void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_store_map(emit_t *emit); -void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index); #if MICROPY_PY_BUILTINS_SET void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args); -void mp_emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index); #endif #if MICROPY_PY_BUILTINS_SLICE void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args); #endif +void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t list_stack_index); void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); diff --git a/py/emitbc.c b/py/emitbc.c index d871aa4ce9..d6f2bf333c 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -302,15 +302,6 @@ STATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, byte b1, mp_uint c[2] = bytecode_offset >> 8; } -#if MICROPY_EMIT_NATIVE -STATIC void mp_emit_bc_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) { - (void)emit; - (void)op; - (void)arg1; - (void)arg2; -} -#endif - void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->stack_size = 0; @@ -408,9 +399,7 @@ void mp_emit_bc_end_pass(emit_t *emit) { } // check stack is back to zero size - if (emit->stack_size != 0) { - mp_printf(&mp_plat_print, "ERROR: stack size not back to zero; got %d\n", emit->stack_size); - } + assert(emit->stack_size == 0); emit_write_code_info_byte(emit, 0); // end of line number info @@ -528,9 +517,10 @@ void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) { case MP_TOKEN_KW_FALSE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE); break; case MP_TOKEN_KW_NONE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_NONE); break; case MP_TOKEN_KW_TRUE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_TRUE); break; - no_other_choice: - case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); break; - default: assert(0); goto no_other_choice; // to help flow control analysis + default: + assert(tok == MP_TOKEN_ELLIPSIS); + emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); + break; } } @@ -751,10 +741,9 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept } void mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label) { - // TODO We can probably optimise the amount of needed stack space, since - // we don't actually need 4 slots during the entire with block, only in - // the cleanup handler in certain cases. It needs some thinking. - emit_bc_pre(emit, 4); + // The SETUP_WITH opcode pops ctx_mgr from the top of the stack + // and then pushes 3 entries: __exit__, ctx_mgr, as_value. + emit_bc_pre(emit, 2); emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label); } @@ -762,8 +751,9 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { mp_emit_bc_pop_block(emit); mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE); mp_emit_bc_label_assign(emit, label); - emit_bc_pre(emit, -4); + emit_bc_pre(emit, 2); // ensure we have enough stack space to call the __exit__ method emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP); + emit_bc_pre(emit, -4); // cancel the 2 above, plus the 2 from mp_emit_bc_setup_with } void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label) { @@ -837,11 +827,6 @@ void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) { emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args); } -void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index); -} - void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1); emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args); @@ -852,21 +837,11 @@ void mp_emit_bc_store_map(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_STORE_MAP); } -void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index) { - emit_bc_pre(emit, -2); - emit_write_bytecode_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index); -} - #if MICROPY_PY_BUILTINS_SET void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1 - n_args); emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SET, n_args); } - -void mp_emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_SET_ADD, set_stack_index); -} #endif #if MICROPY_PY_BUILTINS_SLICE @@ -876,6 +851,24 @@ void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif +void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) { + int t; + int n; + if (kind == SCOPE_LIST_COMP) { + n = 0; + t = 0; + } else if (!MICROPY_PY_BUILTINS_SET || kind == SCOPE_DICT_COMP) { + n = 1; + t = 1; + } else if (MICROPY_PY_BUILTINS_SET) { + n = 0; + t = 2; + } + emit_bc_pre(emit, -1 - n); + // the lower 2 bits of the opcode argument indicate the collection type + emit_write_bytecode_byte_uint(emit, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t); +} + void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, -1 + n_args); emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args); @@ -952,16 +945,16 @@ void mp_emit_bc_yield_from(emit_t *emit) { } void mp_emit_bc_start_except_handler(emit_t *emit) { - mp_emit_bc_adjust_stack_size(emit, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state + mp_emit_bc_adjust_stack_size(emit, 4); // stack adjust for the exception instance, +3 for possible UNWIND_JUMP state } void mp_emit_bc_end_except_handler(emit_t *emit) { - mp_emit_bc_adjust_stack_size(emit, -5); // stack adjust + mp_emit_bc_adjust_stack_size(emit, -3); // stack adjust } #if MICROPY_EMIT_NATIVE const emit_method_table_t emit_bc_method_table = { - mp_emit_bc_set_native_type, + NULL, // set_native_type is never called when emitting bytecode mp_emit_bc_start_pass, mp_emit_bc_end_pass, mp_emit_bc_last_emit_was_return_value, @@ -1028,17 +1021,15 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_binary_op, mp_emit_bc_build_tuple, mp_emit_bc_build_list, - mp_emit_bc_list_append, mp_emit_bc_build_map, mp_emit_bc_store_map, - mp_emit_bc_map_add, #if MICROPY_PY_BUILTINS_SET mp_emit_bc_build_set, - mp_emit_bc_set_add, #endif #if MICROPY_PY_BUILTINS_SLICE mp_emit_bc_build_slice, #endif + mp_emit_bc_store_comp, mp_emit_bc_unpack_sequence, mp_emit_bc_unpack_ex, mp_emit_bc_make_function, diff --git a/py/emitcommon.c b/py/emitcommon.c index 435188f366..e914431d32 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -35,13 +35,7 @@ void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) { bool added; id_info_t *id = scope_find_or_add_id(scope, qst, &added); if (added) { - id_info_t *id2 = scope_find_local_in_parent(scope, qst); - if (id2 != NULL && (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE)) { - id->kind = ID_INFO_KIND_FREE; - scope_close_over_in_parents(scope, qst); - } else { - id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; - } + scope_find_local_and_close_over(scope, id, qst); } } @@ -50,12 +44,12 @@ void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) { bool added; id_info_t *id = scope_find_or_add_id(scope, qst, &added); if (added) { - if (scope->kind == SCOPE_MODULE || scope->kind == SCOPE_CLASS) { - id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; - } else { + if (SCOPE_IS_FUNC_LIKE(scope->kind)) { id->kind = ID_INFO_KIND_LOCAL; + } else { + id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; } - } else if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { + } else if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { // rebind as a local variable id->kind = ID_INFO_KIND_LOCAL; } diff --git a/py/emitglue.c b/py/emitglue.c index f544ae2944..e04eb32c91 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -426,7 +426,7 @@ mp_raw_code_t *mp_raw_code_load_file(const char *filename) { return rc; } -#elif defined(__thumb2__) +#elif defined(__thumb2__) || defined(__xtensa__) // fatfs file reader (assume thumb2 arch uses fatfs...) #include "lib/fatfs/ff.h" diff --git a/py/emitnative.c b/py/emitnative.c index 2cf4711feb..b54f263d60 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2344,17 +2344,6 @@ STATIC void emit_native_build_list(emit_t *emit, mp_uint_t n_args) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list } -STATIC void emit_native_list_append(emit_t *emit, mp_uint_t list_index) { - // only used in list comprehension - vtype_kind_t vtype_list, vtype_item; - emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); - emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1); - assert(vtype_list == VTYPE_PYOBJ); - assert(vtype_item == VTYPE_PYOBJ); - emit_call(emit, MP_F_LIST_APPEND); - emit_post(emit); -} - STATIC void emit_native_build_map(emit_t *emit, mp_uint_t n_args) { emit_native_pre(emit); emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1); @@ -2371,18 +2360,6 @@ STATIC void emit_native_store_map(emit_t *emit) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map } -STATIC void emit_native_map_add(emit_t *emit, mp_uint_t map_index) { - // only used in list comprehension - vtype_kind_t vtype_map, vtype_key, vtype_value; - emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); - emit_access_stack(emit, map_index, &vtype_map, REG_ARG_1); - assert(vtype_map == VTYPE_PYOBJ); - assert(vtype_key == VTYPE_PYOBJ); - assert(vtype_value == VTYPE_PYOBJ); - emit_call(emit, MP_F_STORE_MAP); - emit_post(emit); -} - #if MICROPY_PY_BUILTINS_SET STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) { emit_native_pre(emit); @@ -2390,17 +2367,6 @@ STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) { emit_call_with_imm_arg(emit, MP_F_BUILD_SET, n_args, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set } - -STATIC void emit_native_set_add(emit_t *emit, mp_uint_t set_index) { - // only used in set comprehension - vtype_kind_t vtype_set, vtype_item; - emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); - emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1); - assert(vtype_set == VTYPE_PYOBJ); - assert(vtype_item == VTYPE_PYOBJ); - emit_call(emit, MP_F_STORE_SET); - emit_post(emit); -} #endif #if MICROPY_PY_BUILTINS_SLICE @@ -2426,6 +2392,35 @@ STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif +STATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) { + mp_fun_kind_t f; + if (kind == SCOPE_LIST_COMP) { + vtype_kind_t vtype_item; + emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); + assert(vtype_item == VTYPE_PYOBJ); + f = MP_F_LIST_APPEND; + #if MICROPY_PY_BUILTINS_SET + } else if (kind == SCOPE_SET_COMP) { + vtype_kind_t vtype_item; + emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); + assert(vtype_item == VTYPE_PYOBJ); + f = MP_F_STORE_SET; + #endif + } else { + // SCOPE_DICT_COMP + vtype_kind_t vtype_key, vtype_value; + emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); + assert(vtype_key == VTYPE_PYOBJ); + assert(vtype_value == VTYPE_PYOBJ); + f = MP_F_STORE_MAP; + } + vtype_kind_t vtype_collection; + emit_access_stack(emit, collection_index, &vtype_collection, REG_ARG_1); + assert(vtype_collection == VTYPE_PYOBJ); + emit_call(emit, f); + emit_post(emit); +} + STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("unpack_sequence %d\n", n_args); vtype_kind_t vtype_base; @@ -2674,17 +2669,15 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_binary_op, emit_native_build_tuple, emit_native_build_list, - emit_native_list_append, emit_native_build_map, emit_native_store_map, - emit_native_map_add, #if MICROPY_PY_BUILTINS_SET emit_native_build_set, - emit_native_set_add, #endif #if MICROPY_PY_BUILTINS_SLICE emit_native_build_slice, #endif + emit_native_store_comp, emit_native_unpack_sequence, emit_native_unpack_ex, emit_native_make_function, diff --git a/py/lexer.c b/py/lexer.c index 820f91be78..4a7c8f580a 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -343,7 +343,6 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) { lex->tok_kind = MP_TOKEN_NEWLINE; mp_uint_t num_spaces = lex->column - 1; - lex->emit_dent = 0; if (num_spaces == indent_top(lex)) { } else if (num_spaces > indent_top(lex)) { indent_push(lex, num_spaces); @@ -359,16 +358,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) { } } else if (is_end(lex)) { - if (indent_top(lex) > 0) { - lex->tok_kind = MP_TOKEN_NEWLINE; - lex->emit_dent = 0; - while (indent_top(lex) > 0) { - indent_pop(lex); - lex->emit_dent -= 1; - } - } else { - lex->tok_kind = MP_TOKEN_END; - } + lex->tok_kind = MP_TOKEN_END; } else if (is_char_or(lex, '\'', '\"') || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"')) @@ -723,7 +713,8 @@ mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_ vstr_init(&lex->vstr, 32); // check for memory allocation error - if (lex->indent_level == NULL || vstr_had_error(&lex->vstr)) { + // note: vstr_init above may fail on malloc, but so may mp_lexer_next_token_into below + if (lex->indent_level == NULL) { mp_lexer_free(lex); return NULL; } diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 69aaefb3e6..92a19c3920 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -11,7 +11,7 @@ import os # Blacklist of qstrings that are specially handled in further # processing and should be ignored -QSTRING_BLACK_LIST = {'NULL', 'number_of', } +QSTRING_BLACK_LIST = set(['NULL', 'number_of']) def write_out(fname, output): @@ -139,7 +139,6 @@ typedef struct _vstr_t { size_t alloc; size_t len; char *buf; - bool had_error : 1; bool fixed_buf : 1; } vstr_t; @@ -152,13 +151,11 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf); struct _mp_print_t; void vstr_init_print(vstr_t *vstr, size_t alloc, struct _mp_print_t *print); void vstr_clear(vstr_t *vstr); -vstr_t *vstr_new(void); -vstr_t *vstr_new_size(size_t alloc); +vstr_t *vstr_new(size_t alloc); void vstr_free(vstr_t *vstr); -void vstr_reset(vstr_t *vstr); -bool vstr_had_error(vstr_t *vstr); -char *vstr_str(vstr_t *vstr); -size_t vstr_len(vstr_t *vstr); +static inline void vstr_reset(vstr_t *vstr) { vstr->len = 0; } +static inline char *vstr_str(vstr_t *vstr) { return vstr->buf; } +static inline size_t vstr_len(vstr_t *vstr) { return vstr->len; } void vstr_hint_size(vstr_t *vstr, size_t size); char *vstr_extend(vstr_t *vstr, size_t size); char *vstr_add_len(vstr_t *vstr, size_t len); diff --git a/py/mkenv.mk b/py/mkenv.mk index b7f8c2aff4..e7262907c8 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -58,6 +58,8 @@ CXX += -m32 LD += -m32 endif +MAKE_FROZEN = ../tools/make-frozen.py + all: .PHONY: all diff --git a/py/mkrules.mk b/py/mkrules.mk index a3a408dc89..26e4aeab3f 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -100,6 +100,12 @@ $(OBJ_DIRS): $(HEADER_BUILD): $(MKDIR) -p $@ +ifneq ($(FROZEN_DIR),) +$(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DEPS) + $(ECHO) "Generating $@" + $(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@ +endif + ifneq ($(PROG),) # Build a standalone executable (unix does this) diff --git a/py/modarray.c b/py/modarray.c index cfee011e10..356e48bee0 100644 --- a/py/modarray.c +++ b/py/modarray.c @@ -37,7 +37,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_tab const mp_obj_module_t mp_module_array = { .base = { &mp_type_module }, - .name = MP_QSTR_array, .globals = (mp_obj_dict_t*)&mp_module_array_globals, }; diff --git a/py/modbuiltins.c b/py/modbuiltins.c index ac3d3041f5..57e52efa52 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -178,7 +178,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { str[3] = (c & 0x3F) | 0x80; len = 4; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)")); + mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"); } return mp_obj_new_str(str, len, true); #else @@ -187,7 +187,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { char str[1] = {ord}; return mp_obj_new_str(str, 1, true); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(256)")); + mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(256)"); } #endif } @@ -286,7 +286,7 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t if (default_elem != NULL) { best_obj = default_elem->value; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "arg is an empty sequence")); + mp_raise_msg(&mp_type_ValueError, "arg is an empty sequence"); } } return best_obj; @@ -507,8 +507,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { if (n_args > 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "must use keyword argument for key function")); + mp_raise_msg(&mp_type_TypeError, "must use keyword argument for key function"); } mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args); mp_obj_list_sort(1, &self, kwargs); @@ -577,6 +576,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len); STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_builtins) }, + // built-in core functions { MP_ROM_QSTR(MP_QSTR___build_class__), MP_ROM_PTR(&mp_builtin___build_class___obj) }, { MP_ROM_QSTR(MP_QSTR___import__), MP_ROM_PTR(&mp_builtin___import___obj) }, @@ -727,6 +728,5 @@ MP_DEFINE_CONST_DICT(mp_module_builtins_globals, mp_module_builtins_globals_tabl const mp_obj_module_t mp_module_builtins = { .base = { &mp_type_module }, - .name = MP_QSTR_builtins, .globals = (mp_obj_dict_t*)&mp_module_builtins_globals, }; diff --git a/py/modcmath.c b/py/modcmath.c index 33fe9c73f5..7ad8f5ad60 100644 --- a/py/modcmath.c +++ b/py/modcmath.c @@ -160,7 +160,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_cmath_globals, mp_module_cmath_globals_tab const mp_obj_module_t mp_module_cmath = { .base = { &mp_type_module }, - .name = MP_QSTR_cmath, .globals = (mp_obj_dict_t*)&mp_module_cmath_globals, }; diff --git a/py/modcollections.c b/py/modcollections.c index dceaa203de..e610a28d24 100644 --- a/py/modcollections.c +++ b/py/modcollections.c @@ -40,7 +40,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_collections_globals, mp_module_collections const mp_obj_module_t mp_module_collections = { .base = { &mp_type_module }, - .name = MP_QSTR_ucollections, .globals = (mp_obj_dict_t*)&mp_module_collections_globals, }; diff --git a/py/modgc.c b/py/modgc.c index 976fb89980..24564622ec 100644 --- a/py/modgc.c +++ b/py/modgc.c @@ -119,7 +119,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table); const mp_obj_module_t mp_module_gc = { .base = { &mp_type_module }, - .name = MP_QSTR_gc, .globals = (mp_obj_dict_t*)&mp_module_gc_globals, }; diff --git a/py/modio.c b/py/modio.c index f8826c71a7..d5da0b1db7 100644 --- a/py/modio.c +++ b/py/modio.c @@ -102,7 +102,7 @@ STATIC mp_obj_t bufwriter_flush(mp_obj_t self_in) { assert(out_sz == self->len); self->len = 0; if (err != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err))); + mp_raise_OSError(err); } } @@ -153,7 +153,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_io_globals, mp_module_io_globals_table); const mp_obj_module_t mp_module_io = { .base = { &mp_type_module }, - .name = MP_QSTR_uio, .globals = (mp_obj_dict_t*)&mp_module_io_globals, }; diff --git a/py/modmath.c b/py/modmath.c index 54262f6115..0c70f34cd1 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -268,7 +268,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_math_globals, mp_module_math_globals_table const mp_obj_module_t mp_module_math = { .base = { &mp_type_module }, - .name = MP_QSTR_math, .globals = (mp_obj_dict_t*)&mp_module_math_globals, }; diff --git a/py/modmicropython.c b/py/modmicropython.c index 805bda51d2..675d169cc4 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -34,6 +34,16 @@ // Various builtins specific to MicroPython runtime, // living in micropython module +STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + return MP_OBJ_NEW_SMALL_INT(MP_STATE_VM(mp_optimise_value)); + } else { + MP_STATE_VM(mp_optimise_value) = mp_obj_get_int(args[0]); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level); + #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS @@ -120,6 +130,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) }, + { MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR_opt_level), MP_ROM_PTR(&mp_micropython_opt_level_obj) }, #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS { MP_ROM_QSTR(MP_QSTR_mem_total), MP_ROM_PTR(&mp_micropython_mem_total_obj) }, @@ -145,6 +157,5 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython const mp_obj_module_t mp_module_micropython = { .base = { &mp_type_module }, - .name = MP_QSTR_micropython, .globals = (mp_obj_dict_t*)&mp_module_micropython_globals, }; diff --git a/py/modstruct.c b/py/modstruct.c index be0d0110de..88411ff0fc 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -156,9 +156,6 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { } for (uint i = 0; i < num_items;) { - if (*fmt == '\0') { - break; - } mp_uint_t sz = 1; if (unichar_isdigit(*fmt)) { sz = get_fmt_num(&fmt); @@ -191,6 +188,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, siz for (i = 0; i < n_args;) { mp_uint_t sz = 1; if (*fmt == '\0') { + // more arguments given than used by format string; CPython raises struct.error here break; } if (unichar_isdigit(*fmt)) { @@ -265,7 +263,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_struct_globals, mp_module_struct_globals_t const mp_obj_module_t mp_module_ustruct = { .base = { &mp_type_module }, - .name = MP_QSTR_ustruct, .globals = (mp_obj_dict_t*)&mp_module_struct_globals, }; diff --git a/py/modsys.c b/py/modsys.c index 3bc5c2bafc..8c368ac35b 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -203,7 +203,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table); const mp_obj_module_t mp_module_sys = { .base = { &mp_type_module }, - .name = MP_QSTR_sys, .globals = (mp_obj_dict_t*)&mp_module_sys_globals, }; diff --git a/py/modthread.c b/py/modthread.c index 6c8340c928..6f55281adc 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -93,7 +93,7 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { self->locked = true; return mp_const_true; } else { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-ret))); + mp_raise_OSError(-ret); } #endif } @@ -239,7 +239,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) } else { // positional and keyword arguments if (mp_obj_get_type(args[2]) != &mp_type_dict) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting a dict for keyword args")); + mp_raise_msg(&mp_type_TypeError, "expecting a dict for keyword args"); } mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map; th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used); @@ -294,7 +294,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_thread_globals, mp_module_thread_globals_t const mp_obj_module_t mp_module_thread = { .base = { &mp_type_module }, - .name = MP_QSTR__thread, .globals = (mp_obj_dict_t*)&mp_module_thread_globals, }; diff --git a/py/moduerrno.c b/py/moduerrno.c index 343b29ba08..4a5e87419f 100644 --- a/py/moduerrno.c +++ b/py/moduerrno.c @@ -89,7 +89,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uerrno_globals, mp_module_uerrno_globals_t const mp_obj_module_t mp_module_uerrno = { .base = { &mp_type_module }, - .name = MP_QSTR_uerrno, .globals = (mp_obj_dict_t*)&mp_module_uerrno_globals, }; diff --git a/py/mpconfig.h b/py/mpconfig.h index e33a41f7a0..dcdaffe0f4 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -860,6 +860,12 @@ typedef double mp_float_t; #define MICROPY_PY_UERRNO (0) #endif +// Whether to provide "utime" module functions implementation +// in terms of mp_hal_* functions. +#ifndef MICROPY_PY_UTIME_MP_HAL +#define MICROPY_PY_UTIME_MP_HAL (0) +#endif + // Whether to provide "_thread" module #ifndef MICROPY_PY_THREAD #define MICROPY_PY_THREAD (0) diff --git a/py/mphal.h b/py/mphal.h index 54a45b0240..8d5654f9e3 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -66,6 +66,10 @@ mp_uint_t mp_hal_ticks_ms(void); mp_uint_t mp_hal_ticks_us(void); #endif +#ifndef mp_hal_ticks_cpu +mp_uint_t mp_hal_ticks_cpu(void); +#endif + // If port HAL didn't define its own pin API, use generic // "virtual pin" API from the core. #ifndef mp_hal_pin_obj_t diff --git a/py/mpprint.c b/py/mpprint.c index 97ea33ad2a..9ad0f3f9a0 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -252,8 +252,8 @@ int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char // enough, a dynamic one will be allocated. char stack_buf[sizeof(mp_int_t) * 4]; char *buf = stack_buf; - mp_uint_t buf_size = sizeof(stack_buf); - mp_uint_t fmt_size = 0; + size_t buf_size = sizeof(stack_buf); + size_t fmt_size = 0; char *str; if (prec > 1) { @@ -645,18 +645,6 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, const mpz_dig_t *den #define MIN_ALLOC (2) -STATIC const uint8_t log_base2_floor[] = { - 0, - 0, 1, 1, 2, - 2, 2, 2, 3, - 3, 3, 3, 3, - 3, 3, 3, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 5 -}; - void mpz_init_zero(mpz_t *z) { z->neg = 0; z->fixed_dig = 0; @@ -734,11 +722,9 @@ STATIC void mpz_need_dig(mpz_t *z, mp_uint_t need) { } if (z->dig == NULL || z->alloc < need) { - if (z->fixed_dig) { - // cannot reallocate fixed buffers - assert(0); - return; - } + // if z has fixed digit buffer there's not much we can do as the caller will + // be expecting a buffer with at least "need" bytes (but it shouldn't happen) + assert(!z->fixed_dig); z->dig = m_renew(mpz_dig_t, z->dig, z->alloc, need); z->alloc = need; } @@ -1497,13 +1483,10 @@ mpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2) { quo * rhs + rem = lhs 0 <= rem < rhs can have lhs, rhs the same + assumes rhs != 0 (undefined behaviour if it is) */ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs) { - if (rhs->len == 0) { - mpz_set_from_int(dest_quo, 0); - mpz_set_from_int(dest_rem, 0); - return; - } + assert(!mpz_is_zero(rhs)); mpz_need_dig(dest_quo, lhs->len + 1); // +1 necessary? memset(dest_quo->dig, 0, (lhs->len + 1) * sizeof(mpz_dig_t)); @@ -1657,18 +1640,6 @@ mp_float_t mpz_as_float(const mpz_t *i) { } #endif -mp_uint_t mpz_as_str_size(const mpz_t *i, mp_uint_t base, const char *prefix, char comma) { - if (base < 2 || base > 32) { - return 0; - } - - mp_uint_t num_digits = i->len * DIG_SIZE / log_base2_floor[base] + 1; - mp_uint_t num_commas = comma ? num_digits / 3: 0; - mp_uint_t prefix_len = prefix ? strlen(prefix) : 0; - - return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte -} - #if 0 this function is unused char *mpz_as_str(const mpz_t *i, mp_uint_t base) { @@ -1678,7 +1649,7 @@ char *mpz_as_str(const mpz_t *i, mp_uint_t base) { } #endif -// assumes enough space as calculated by mpz_as_str_size +// assumes enough space as calculated by mp_int_format_size // returns length of string, not including null byte mp_uint_t mpz_as_str_inpl(const mpz_t *i, mp_uint_t base, const char *prefix, char base_char, char comma, char *str) { if (str == NULL || base < 2 || base > 32) { @@ -127,6 +127,7 @@ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs); +static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; } mp_int_t mpz_hash(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value); bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value); @@ -233,8 +233,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return mp_obj_int_get_checked(arg); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to int")); + mp_raise_msg(&mp_type_TypeError, "can't convert to int"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); @@ -282,8 +281,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { return mp_obj_float_get(arg); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to float")); + mp_raise_msg(&mp_type_TypeError, "can't convert to float"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); @@ -312,8 +310,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { mp_obj_complex_get(arg, real, imag); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to complex")); + mp_raise_msg(&mp_type_TypeError, "can't convert to complex"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); @@ -331,8 +328,7 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) { mp_obj_list_get(o, len, items); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "expected tuple/list")); + mp_raise_msg(&mp_type_TypeError, "expected tuple/list"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o))); @@ -346,8 +342,7 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) { mp_obj_get_array(o, &seq_len, items); if (seq_len != len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "tuple/list has wrong length")); + mp_raise_msg(&mp_type_ValueError, "tuple/list has wrong length"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "requested length %d but object has length %d", (int)len, (int)seq_len)); @@ -362,8 +357,7 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, i = MP_OBJ_SMALL_INT_VALUE(index); } else if (!mp_obj_get_int_maybe(index, &i)) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "indices must be integers")); + mp_raise_msg(&mp_type_TypeError, "indices must be integers"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%q indices must be integers, not %s", @@ -383,7 +377,7 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, } else { if (i < 0 || (mp_uint_t)i >= len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "index out of range")); + mp_raise_msg(&mp_type_IndexError, "index out of range"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%q index out of range", type->name)); @@ -416,8 +410,7 @@ mp_obj_t mp_obj_len(mp_obj_t o_in) { mp_obj_t len = mp_obj_len_maybe(o_in); if (len == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object has no len")); + mp_raise_msg(&mp_type_TypeError, "object has no len"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); @@ -458,8 +451,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { } if (value == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object does not support item deletion")); + mp_raise_msg(&mp_type_TypeError, "object does not support item deletion"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base))); @@ -474,8 +466,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object does not support item assignment")); + mp_raise_msg(&mp_type_TypeError, "object does not support item assignment"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base))); @@ -504,7 +495,7 @@ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (!mp_get_buffer(obj, bufinfo, flags)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object with buffer protocol required")); + mp_raise_msg(&mp_type_TypeError, "object with buffer protocol required"); } } @@ -765,7 +765,6 @@ MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj); // module typedef struct _mp_obj_module_t { mp_obj_base_t base; - qstr name; mp_obj_dict_t *globals; } mp_obj_module_t; mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in); diff --git a/py/objarray.c b/py/objarray.c index 2cd0fef6b6..8e1d32f0f4 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -95,7 +95,7 @@ STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) { int typecode_size = mp_binary_get_size('@', typecode, NULL); if (typecode_size == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode")); + mp_raise_msg(&mp_type_ValueError, "bad typecode"); } mp_obj_array_t *o = m_new_obj(mp_obj_array_t); #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY @@ -395,7 +395,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value); if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) { compat_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible")); + mp_raise_msg(&mp_type_ValueError, "lhs and rhs should be compatible"); } src_len = src_slice->len; src_items = src_slice->items; diff --git a/py/objbool.c b/py/objbool.c index 8882a835d3..5bc04bb6f9 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -56,26 +56,19 @@ STATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); - switch (n_args) { - case 0: - return mp_const_false; - case 1: - default: // must be 0 or 1 - if (mp_obj_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } + if (n_args == 0) { + return mp_const_false; + } else { + return mp_obj_new_bool(mp_obj_is_true(args[0])); } } STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) { - mp_int_t value = ((mp_obj_bool_t*)MP_OBJ_TO_PTR(o_in))->value; - switch (op) { - case MP_UNARY_OP_BOOL: return o_in; - // needs to hash to the same value as if converting to an integer - case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(value); - case MP_UNARY_OP_POSITIVE: return MP_OBJ_NEW_SMALL_INT(value); - case MP_UNARY_OP_NEGATIVE: return MP_OBJ_NEW_SMALL_INT(-value); - case MP_UNARY_OP_INVERT: return MP_OBJ_NEW_SMALL_INT(~value); - default: return MP_OBJ_NULL; // op not supported + if (op == MP_UNARY_OP_LEN) { + return MP_OBJ_NULL; } + mp_obj_bool_t *self = MP_OBJ_TO_PTR(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) { diff --git a/py/objcomplex.c b/py/objcomplex.c index 5da655eb3c..96be25255c 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -197,7 +197,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_imag == 0) { if (rhs_real == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "complex division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "complex division by zero"); } lhs_real /= rhs_real; lhs_imag /= rhs_real; @@ -226,7 +226,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_real = 1; rhs_real = 0; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power")); + mp_raise_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power"); } } else { mp_float_t ln1 = MICROPY_FLOAT_C_FUN(log)(abs1); diff --git a/py/objdict.c b/py/objdict.c index 7a74557dc1..4942d37791 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -162,7 +162,7 @@ mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); if (elem == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>")); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index)); } else { return elem->value; } @@ -178,7 +178,7 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); if (elem == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>")); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index)); } else { return elem->value; } @@ -250,15 +250,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy); // this is a classmethod STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { mp_obj_t iter = mp_getiter(args[1]); - mp_obj_t len = mp_obj_len_maybe(iter); mp_obj_t value = mp_const_none; mp_obj_t next = MP_OBJ_NULL; - mp_obj_t self_out; if (n_args > 2) { value = args[2]; } + // optimisation to allocate result based on len of argument + mp_obj_t self_out; + mp_obj_t len = mp_obj_len_maybe(args[1]); if (len == MP_OBJ_NULL) { /* object's type doesn't have a __len__ slot */ self_out = mp_obj_new_dict(0); @@ -282,7 +283,7 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp if (elem == NULL || elem->value == MP_OBJ_NULL) { if (deflt == MP_OBJ_NULL) { if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>")); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, key)); } else { value = mp_const_none; } @@ -342,7 +343,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { mp_uint_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "popitem(): dictionary is empty")); + mp_raise_msg(&mp_type_KeyError, "popitem(): dictionary is empty"); } self->map.used--; mp_obj_t items[] = {next->key, next->value}; @@ -384,9 +385,7 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { - nlr_raise(mp_obj_new_exception_msg( - &mp_type_ValueError, - "dictionary update sequence has the wrong length")); + mp_raise_msg(&mp_type_ValueError, "dictionary update sequence has the wrong length"); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } diff --git a/py/objfloat.c b/py/objfloat.c index 85b8b13861..73d07feac8 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -198,7 +198,7 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { zero_division_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } // Python specs require that x == (x//y)*y + (x%y) so we must // call divmod to compute the correct floor division, which diff --git a/py/objfun.c b/py/objfun.c index 3fd25fb224..405f38127a 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -266,23 +266,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const #endif mp_obj_t result; - switch (vm_return_kind) { - case MP_VM_RETURN_NORMAL: - // return value is in *sp - result = *code_state->sp; - break; - - case MP_VM_RETURN_EXCEPTION: - // return value is in state[n_state - 1] - result = code_state->state[n_state - 1]; - break; - - case MP_VM_RETURN_YIELD: // byte-code shouldn't yield - default: - assert(0); - result = mp_const_none; - vm_return_kind = MP_VM_RETURN_NORMAL; - break; + if (vm_return_kind == MP_VM_RETURN_NORMAL) { + // return value is in *sp + result = *code_state->sp; + } else { + // must be an exception because normal functions can't yield + assert(vm_return_kind == MP_VM_RETURN_EXCEPTION); + // return value is in fastn[0]==state[n_state - 1] + result = code_state->state[n_state - 1]; } // free the state if it was allocated on the heap @@ -409,17 +400,15 @@ STATIC mp_obj_t fun_viper_call(mp_obj_t self_in, size_t n_args, size_t n_kw, con ret = ((viper_fun_2_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8)); } else if (n_args == 3) { ret = ((viper_fun_3_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8), mp_convert_obj_to_native(args[2], self->type_sig >> 12)); - } else if (n_args == 4) { + } else { + // compiler allows at most 4 arguments + assert(n_args == 4); ret = ((viper_fun_4_t)fun)( mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8), mp_convert_obj_to_native(args[2], self->type_sig >> 12), mp_convert_obj_to_native(args[3], self->type_sig >> 16) ); - } else { - // TODO 5 or more arguments not supported for viper call - assert(0); - ret = 0; } return mp_convert_native_to_obj(ret, self->type_sig); diff --git a/py/objgenerator.c b/py/objgenerator.c index 8c32a36496..cbef9fea3d 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -105,7 +105,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ } 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")); + mp_raise_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator"); } } else { *self->code_state.sp = send_value; @@ -157,7 +157,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o case MP_VM_RETURN_YIELD: if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); + mp_raise_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"); } return ret; @@ -209,7 +209,7 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, mp_const_none, MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj), &ret)) { case MP_VM_RETURN_YIELD: - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); + mp_raise_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"); // Swallow StopIteration & GeneratorExit (== successful close), and re-raise any other case MP_VM_RETURN_EXCEPTION: diff --git a/py/objint.c b/py/objint.c index 9f948a1455..f8988d6c94 100644 --- a/py/objint.c +++ b/py/objint.c @@ -133,8 +133,8 @@ void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t // enough, a dynamic one will be allocated. char stack_buf[sizeof(mp_int_t) * 4]; char *buf = stack_buf; - mp_uint_t buf_size = sizeof(stack_buf); - mp_uint_t fmt_size; + size_t buf_size = sizeof(stack_buf); + size_t fmt_size; char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0'); mp_print_str(print, str); @@ -162,14 +162,14 @@ STATIC const uint8_t log_base2_floor[] = { 4, 4, 4, 5 }; -STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) { +size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) { if (base < 2 || base > 32) { return 0; } - uint num_digits = sizeof(fmt_int_t) * 8 / log_base2_floor[base] + 1; - uint num_commas = comma ? num_digits / 3: 0; - uint prefix_len = prefix ? strlen(prefix) : 0; + size_t num_digits = num_bits / log_base2_floor[base] + 1; + size_t num_commas = comma ? num_digits / 3 : 0; + size_t prefix_len = prefix ? strlen(prefix) : 0; return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte } @@ -180,7 +180,7 @@ STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) // // The resulting formatted string will be returned from this function and the // formatted size will be in *fmt_size. -char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { fmt_int_t num; if (MP_OBJ_IS_SMALL_INT(self_in)) { @@ -211,7 +211,7 @@ char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, sign = '-'; } - uint needed_size = int_as_str_size_formatted(base, prefix, comma); + size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); *buf_size = needed_size; @@ -294,19 +294,19 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // This is called only with strings whose value doesn't fit in SMALL_INT mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build")); + mp_raise_msg(&mp_type_OverflowError, "long int not supported in this build"); return mp_const_none; } // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT) mp_obj_t mp_obj_new_int_from_ll(long long val) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } @@ -316,7 +316,7 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) { return MP_OBJ_NEW_SMALL_INT(value); } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } @@ -342,7 +342,7 @@ mp_obj_t mp_obj_new_int(mp_int_t value) { if (MP_SMALL_INT_FITS(value)) { return MP_OBJ_NEW_SMALL_INT(value); } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } diff --git a/py/objint.h b/py/objint.h index c79eb874a9..6e627f1bd7 100644 --- a/py/objint.h +++ b/py/objint.h @@ -50,13 +50,15 @@ typedef enum { mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val); #endif // MICROPY_PY_BUILTINS_FLOAT +size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma); + void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); -char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); -char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); mp_int_t mp_obj_int_hash(mp_obj_t self_in); -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, 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); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index f10e46447b..b051cfbe64 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -53,7 +53,7 @@ const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX}; #endif -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, byte *buf) { +void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; long long val = self->val; diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 3a30eb9d9b..0a1d68598d 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -90,12 +90,12 @@ STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) { // formatted size will be in *fmt_size. // // This particular routine should only be called for the mpz representation of the int. -char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); - mp_uint_t needed_size = mpz_as_str_size(&self->mpz, base, prefix, comma); + size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); *buf_size = needed_size; @@ -107,7 +107,7 @@ char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_ return str; } -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, byte *buf) { +void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); mpz_as_bytes(&self->mpz, big_endian, len, buf); @@ -234,8 +234,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: { if (mpz_is_zero(zrhs)) { zero_division_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, - "division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } mpz_t rem; mpz_init_zero(&rem); mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs); @@ -272,7 +271,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_INPLACE_RSHIFT: { mp_int_t irhs = mp_obj_int_get_checked(rhs_in); if (irhs < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); + mp_raise_msg(&mp_type_ValueError, "negative shift count"); } if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) { mpz_shl_inpl(&res->mpz, zlhs, irhs); @@ -398,7 +397,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return value; } else { // overflow - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "overflow converting long int to machine word")); + mp_raise_msg(&mp_type_OverflowError, "overflow converting long int to machine word"); } } } diff --git a/py/objlist.c b/py/objlist.c index b5e8b99651..6d4a20a507 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -266,7 +266,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); if (self->len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list")); + mp_raise_msg(&mp_type_IndexError, "pop from empty list"); } mp_uint_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; diff --git a/py/objmodule.c b/py/objmodule.c index dc2ce787b4..9b06e3b7b5 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -37,17 +37,23 @@ STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin (void)kind; mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); + const char *module_name = ""; + mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP); + if (elem != NULL) { + module_name = mp_obj_str_get_str(elem->value); + } + #if MICROPY_PY___FILE__ // If we store __file__ to imported modules then try to lookup this // symbol to give more information about the module. - mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); + elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); if (elem != NULL) { - mp_printf(print, "<module '%q' from '%s'>", self->name, mp_obj_str_get_str(elem->value)); + mp_printf(print, "<module '%s' from '%s'>", module_name, mp_obj_str_get_str(elem->value)); return; } #endif - mp_printf(print, "<module '%q'>", self->name); + mp_printf(print, "<module '%s'>", module_name); } STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { @@ -106,7 +112,6 @@ mp_obj_t mp_obj_new_module(qstr module_name) { // create new module object mp_obj_module_t *o = m_new_obj(mp_obj_module_t); o->base.type = &mp_type_module; - o->name = module_name; o->globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE)); // store __name__ entry in the module diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 38cda1ad75..18931a16c2 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -73,7 +73,7 @@ STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else { // delete/store attribute // provide more detailed error message than we'd get by just returning - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "can't set attribute")); + mp_raise_msg(&mp_type_AttributeError, "can't set attribute"); } } diff --git a/py/objnone.c b/py/objnone.c index 69eab03fe2..5d5b83540d 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -43,20 +43,11 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } -STATIC mp_obj_t none_unary_op(mp_uint_t op, mp_obj_t o_in) { - (void)o_in; - switch (op) { - case MP_UNARY_OP_BOOL: return mp_const_false; - case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); - default: return MP_OBJ_NULL; // op not supported - } -} - const mp_obj_type_t mp_type_NoneType = { { &mp_type_type }, .name = MP_QSTR_NoneType, .print = none_print, - .unary_op = none_unary_op, + .unary_op = mp_generic_unary_op, }; const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; diff --git a/py/objobject.c b/py/objobject.c index bba6f053e6..b33dc491c4 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -50,8 +50,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__); STATIC mp_obj_t object___new__(mp_obj_t cls) { if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "__new__ arg must be a user-type")); + mp_raise_msg(&mp_type_TypeError, "__new__ arg must be a user-type"); } mp_obj_t o = MP_OBJ_SENTINEL; mp_obj_t res = mp_obj_instance_make_new(MP_OBJ_TO_PTR(cls), 1, 0, &o); diff --git a/py/objset.c b/py/objset.c index fb89c07f3d..fc124fcd8c 100644 --- a/py/objset.c +++ b/py/objset.c @@ -57,27 +57,21 @@ STATIC bool is_set_or_frozenset(mp_obj_t o) { ; } -#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")); - } -} -#else -#define check_set_or_frozenset(o) check_set(o) -#endif +// 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 (!MP_OBJ_IS_TYPE(o, &mp_type_set)) { - // Emulate CPython behavior + #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' - #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")); - } - #endif - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'set' object required")); + 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) { @@ -395,7 +389,7 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); if (obj == MP_OBJ_NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set")); + mp_raise_msg(&mp_type_KeyError, "pop from an empty set"); } return obj; } @@ -441,6 +435,7 @@ STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { } STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) { + check_set(args[0]); for (mp_uint_t i = 1; i < n_args; i++) { set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]); } diff --git a/py/objstr.c b/py/objstr.c index 406ccf290a..f082e95591 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -881,9 +881,14 @@ STATIC mp_obj_t arg_as_int(mp_obj_t arg) { return arg; } +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE STATIC NORETURN void terse_str_format_value_error(void) { mp_raise_ValueError("bad format string"); } +#else +// define to nothing to improve coverage +#define terse_str_format_value_error() +#endif STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { vstr_t vstr; diff --git a/py/objstringio.c b/py/objstringio.c index eb2e516bb3..a430fca3b7 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -30,22 +30,16 @@ #include "py/nlr.h" #include "py/objstr.h" +#include "py/objstringio.h" #include "py/runtime.h" #include "py/stream.h" #if MICROPY_PY_IO -typedef struct _mp_obj_stringio_t { - mp_obj_base_t base; - vstr_t *vstr; - // StringIO has single pointer used for both reading and writing - mp_uint_t pos; -} mp_obj_stringio_t; - #if MICROPY_CPYTHON_COMPAT STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { if (o->vstr == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "I/O operation on closed file")); + mp_raise_msg(&mp_type_ValueError, "I/O operation on closed file"); } } #else @@ -156,7 +150,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t); o->base.type = type; - o->vstr = vstr_new(); + o->vstr = vstr_new(16); o->pos = 0; return o; } @@ -177,7 +171,7 @@ STATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, s STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, diff --git a/py/objstringio.h b/py/objstringio.h new file mode 100644 index 0000000000..853bfb11b7 --- /dev/null +++ b/py/objstringio.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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. + */ +#ifndef MICROPY_INCLUDED_PY_OBJSTRINGIO_H +#define MICROPY_INCLUDED_PY_OBJSTRINGIO_H + +#include "py/obj.h" + +typedef struct _mp_obj_stringio_t { + mp_obj_base_t base; + vstr_t *vstr; + // StringIO has single pointer used for both reading and writing + mp_uint_t pos; +} mp_obj_stringio_t; + +#endif // MICROPY_INCLUDED_PY_OBJSTRINGIO_H diff --git a/py/objtype.c b/py/objtype.c index 907308a757..8b46c54001 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -311,8 +311,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size } if (init_ret != mp_const_none) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "__init__() should return None")); + mp_raise_msg(&mp_type_TypeError, "__init__() should return None"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); @@ -508,7 +507,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des // the code. const mp_obj_t *proxy = mp_obj_property_get(member); if (proxy[0] == mp_const_none) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "unreadable attribute")); + mp_raise_msg(&mp_type_AttributeError, "unreadable attribute"); } else { dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); } @@ -710,8 +709,7 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons mp_obj_t call = mp_obj_instance_get_call(self_in); if (call == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not callable")); + mp_raise_msg(&mp_type_TypeError, "object not callable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(self_in))); @@ -793,7 +791,7 @@ STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]); default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments")); + mp_raise_msg(&mp_type_TypeError, "type takes 1 or 3 arguments"); } } @@ -804,7 +802,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp if (self->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "cannot create instance")); + mp_raise_msg(&mp_type_TypeError, "cannot create instance"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%q' instances", self->name)); @@ -892,8 +890,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "type is not an acceptable base type")); + mp_raise_msg(&mp_type_TypeError, "type is not an acceptable base type"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "type '%q' is not an acceptable base type", t->name)); @@ -927,7 +924,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) const mp_obj_type_t *native_base; uint num_native_bases = instance_count_native_bases(o, &native_base); if (num_native_bases > 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict")); + mp_raise_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"); } mp_map_t *locals_map = &o->locals_dict->map; @@ -1074,7 +1071,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) { mp_obj_tuple_get(classinfo, &len, &items); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes")); + mp_raise_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"); } for (uint i = 0; i < len; i++) { @@ -1088,7 +1085,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class")); + mp_raise_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"); } return mp_obj_is_subclass(object, classinfo); } diff --git a/py/parse.c b/py/parse.c index 1ec995cd8f..5920828fe9 100644 --- a/py/parse.c +++ b/py/parse.c @@ -398,21 +398,24 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, return (mp_parse_node_t)pn; } -STATIC void push_result_token(parser_t *parser) { +STATIC void push_result_token(parser_t *parser, const rule_t *rule) { mp_parse_node_t pn; mp_lexer_t *lex = parser->lexer; if (lex->tok_kind == MP_TOKEN_NAME) { qstr id = qstr_from_strn(lex->vstr.buf, lex->vstr.len); #if MICROPY_COMP_CONST - // lookup identifier in table of dynamic constants - mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP); - if (elem != NULL) { + // if name is a standalone identifier, look it up in the table of dynamic constants + mp_map_elem_t *elem; + if (rule->rule_id == RULE_atom + && (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(elem->value)); - } else - #endif - { + } else { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id); } + #else + (void)rule; + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id); + #endif } else if (lex->tok_kind == MP_TOKEN_INTEGER) { mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex); if (MP_OBJ_IS_SMALL_INT(o)) { @@ -765,7 +768,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK; if (kind == RULE_ARG_TOK) { if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) { - push_result_token(&parser); + push_result_token(&parser, rule); mp_lexer_to_next(lex); goto next_rule; } @@ -810,7 +813,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { if (lex->tok_kind == tok_kind) { // matched token if (tok_kind == MP_TOKEN_NAME) { - push_result_token(&parser); + push_result_token(&parser, rule); } mp_lexer_to_next(lex); } else { @@ -950,7 +953,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { if (i & 1 & n) { // separators which are tokens are not pushed to result stack } else { - push_result_token(&parser); + push_result_token(&parser, rule); } mp_lexer_to_next(lex); // got element of list, so continue parsing list diff --git a/py/parsenum.c b/py/parsenum.c index 83a6abd202..1010ad3055 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -27,7 +27,7 @@ #include <stdbool.h> #include <stdlib.h> -#include "py/nlr.h" +#include "py/runtime.h" #include "py/parsenumbase.h" #include "py/parsenum.h" #include "py/smallint.h" @@ -55,7 +55,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m // check radix base if ((base != 0 && base < 2) || base > 36) { // this won't be reached if lex!=NULL - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36")); + mp_raise_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36"); } // skip leading space @@ -24,6 +24,11 @@ CFLAGS_MOD += -DMICROPY_PY_USSL=1 ifeq ($(MICROPY_SSL_AXTLS),1) CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I../lib/axtls/ssl -I../lib/axtls/crypto -I../lib/axtls/config LDFLAGS_MOD += -Lbuild -laxtls +else ifeq ($(MICROPY_SSL_MBEDTLS),1) +# Can be overriden by ports which have "builtin" mbedTLS +MICROPY_SSL_MBEDTLS_INCLUDE ?= ../lib/mbedtls/include +CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE) +LDFLAGS_MOD += -L../lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto endif endif @@ -89,6 +94,8 @@ btree/bt_utils.c \ mpool/mpool.c \ ) CFLAGS_MOD += -DMICROPY_PY_BTREE=1 +# we need to suppress certain warnings to get berkeley-db to compile cleanly +$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter endif # py object files @@ -210,6 +217,7 @@ PY_O_BASENAME = \ ../extmod/machine_i2c.o \ ../extmod/machine_spi.o \ ../extmod/modussl_axtls.o \ + ../extmod/modussl_mbedtls.o \ ../extmod/modurandom.o \ ../extmod/modwebsocket.o \ ../extmod/modwebrepl.o \ @@ -221,6 +229,7 @@ PY_O_BASENAME = \ ../extmod/vfs_fat_file.o \ ../extmod/vfs_fat_lexer.o \ ../extmod/vfs_fat_misc.o \ + ../extmod/utime_mphal.o \ ../extmod/moduos_dupterm.o \ ../lib/embed/abort_.o \ ../lib/utils/printf.o \ @@ -275,7 +275,6 @@ size_t qstr_len(qstr q) { return Q_GET_LENGTH(qd); } -// XXX to remove! const char *qstr_str(qstr q) { const byte *qd = find_qstr(q); return (const char*)Q_GET_DATA(qd); diff --git a/py/runtime.c b/py/runtime.c index 48e815f0fa..6eda77ee9c 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -55,7 +55,6 @@ const mp_obj_module_t mp_module___main__ = { .base = { &mp_type_module }, - .name = MP_QSTR___main__, .globals = (mp_obj_dict_t*)&MP_STATE_VM(dict_main), }; @@ -139,8 +138,7 @@ mp_obj_t mp_load_global(qstr qst) { elem = mp_map_lookup((mp_map_t*)&mp_module_builtins_globals.map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); if (elem == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError, - "name not defined")); + mp_raise_msg(&mp_type_NameError, "name not defined"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%q' is not defined", qst)); @@ -231,8 +229,7 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) { } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "unsupported type for operator")); + mp_raise_msg(&mp_type_TypeError, "unsupported type for operator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported type for %q: '%s'", @@ -324,7 +321,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_INPLACE_LSHIFT: { if (rhs_val < 0) { // negative shift not allowed - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); + mp_raise_msg(&mp_type_ValueError, "negative shift count"); } else if (rhs_val >= (mp_int_t)BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) { // left-shift will overflow, so use higher precision integer lhs = mp_obj_new_int_from_ll(lhs_val); @@ -339,7 +336,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_INPLACE_RSHIFT: if (rhs_val < 0) { // negative shift not allowed - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); + mp_raise_msg(&mp_type_ValueError, "negative shift count"); } else { // standard precision is enough for right-shift if (rhs_val >= (mp_int_t)BITS_PER_WORD) { @@ -415,7 +412,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { lhs = mp_obj_new_float(lhs_val); goto generic_binary_op; #else - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support")); + mp_raise_msg(&mp_type_ValueError, "negative power with no float support"); #endif } else { mp_int_t ans = 1; @@ -516,8 +513,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not iterable")); + mp_raise_msg(&mp_type_TypeError, "object not iterable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(rhs))); @@ -539,8 +535,7 @@ generic_binary_op: unsupported_op: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "unsupported type for operator")); + mp_raise_msg(&mp_type_TypeError, "unsupported type for operator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported types for %q: '%s', '%s'", @@ -548,7 +543,7 @@ unsupported_op: } zero_division: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } mp_obj_t mp_call_function_0(mp_obj_t fun) { @@ -582,8 +577,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not callable")); + mp_raise_msg(&mp_type_TypeError, "object not callable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in))); @@ -814,16 +808,14 @@ void mp_unpack_sequence(mp_obj_t seq_in, mp_uint_t num, mp_obj_t *items) { too_short: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "wrong number of values to unpack")); + mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", (int)seq_len)); } too_long: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "wrong number of values to unpack")); + mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", (int)num)); @@ -889,8 +881,7 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) { too_short: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "wrong number of values to unpack")); + mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", (int)seq_len)); @@ -929,8 +920,7 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]); if (arg0_type != self->type) { if (MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "argument has wrong type")); + mp_raise_msg(&mp_type_TypeError, "argument has wrong type"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "argument should be a '%q' not a '%q'", self->type->name, arg0_type->name)); @@ -1046,8 +1036,7 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // no attribute/method called attr if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, - "no such attribute")); + mp_raise_msg(&mp_type_AttributeError, "no such attribute"); } else { // following CPython, we give a more detailed error message for type objects if (MP_OBJ_IS_TYPE(base, &mp_type_type)) { @@ -1075,8 +1064,7 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, - "no such attribute")); + mp_raise_msg(&mp_type_AttributeError, "no such attribute"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%q'", @@ -1106,8 +1094,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in) { // object not iterable if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not iterable")); + mp_raise_msg(&mp_type_TypeError, "object not iterable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in))); @@ -1129,8 +1116,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { return mp_call_method_n_kw(0, 0, dest); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not an iterator")); + mp_raise_msg(&mp_type_TypeError, "object not an iterator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in))); @@ -1166,8 +1152,7 @@ mp_obj_t mp_iternext(mp_obj_t o_in) { } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not an iterator")); + mp_raise_msg(&mp_type_TypeError, "object not an iterator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in))); @@ -1385,8 +1370,7 @@ void *m_malloc_fail(size_t num_bytes) { // dummy #if MICROPY_ENABLE_GC } else if (gc_is_locked()) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, - "memory allocation failed, heap is locked")); + mp_raise_msg(&mp_type_MemoryError, "memory allocation failed, heap is locked"); #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, @@ -1406,6 +1390,10 @@ NORETURN void mp_raise_TypeError(const char *msg) { mp_raise_msg(&mp_type_TypeError, msg); } +NORETURN void mp_raise_OSError(int errno_) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_))); +} + NORETURN void mp_not_implemented(const char *msg) { mp_raise_msg(&mp_type_NotImplementedError, msg); } diff --git a/py/runtime.h b/py/runtime.h index 06e68924b2..80488098ae 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -52,8 +52,8 @@ typedef union _mp_arg_val_t { } mp_arg_val_t; typedef struct _mp_arg_t { - qstr qst; - mp_uint_t flags; + uint16_t qst; + uint16_t flags; mp_arg_val_t defval; } mp_arg_t; @@ -137,6 +137,7 @@ NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg); //NORETURN void nlr_raise_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); NORETURN void mp_raise_ValueError(const char *msg); NORETURN void mp_raise_TypeError(const char *msg); +NORETURN void mp_raise_OSError(int errno_); NORETURN void mp_not_implemented(const char *msg); // Raise NotImplementedError with given message NORETURN void mp_exc_recursion_depth(void); diff --git a/py/scope.c b/py/scope.c index e408251733..8143e655c9 100644 --- a/py/scope.c +++ b/py/scope.c @@ -30,36 +30,27 @@ #if MICROPY_ENABLE_COMPILER +// these low numbered qstrs should fit in 8 bits +STATIC const uint8_t scope_simple_name_table[] = { + [SCOPE_MODULE] = MP_QSTR__lt_module_gt_, + [SCOPE_LAMBDA] = MP_QSTR__lt_lambda_gt_, + [SCOPE_LIST_COMP] = MP_QSTR__lt_listcomp_gt_, + [SCOPE_DICT_COMP] = MP_QSTR__lt_dictcomp_gt_, + [SCOPE_SET_COMP] = MP_QSTR__lt_setcomp_gt_, + [SCOPE_GEN_EXPR] = MP_QSTR__lt_genexpr_gt_, +}; + scope_t *scope_new(scope_kind_t kind, const byte *pn, qstr source_file, mp_uint_t emit_options) { scope_t *scope = m_new0(scope_t, 1); scope->kind = kind; scope->pn = pn; scope->source_file = source_file; - switch (kind) { - case SCOPE_MODULE: - scope->simple_name = MP_QSTR__lt_module_gt_; - break; - case SCOPE_FUNCTION: - case SCOPE_CLASS: - pt_extract_id(pn, &scope->simple_name); // function name - break; - case SCOPE_LAMBDA: - scope->simple_name = MP_QSTR__lt_lambda_gt_; - break; - case SCOPE_LIST_COMP: - scope->simple_name = MP_QSTR__lt_listcomp_gt_; - break; - case SCOPE_DICT_COMP: - scope->simple_name = MP_QSTR__lt_dictcomp_gt_; - break; - case SCOPE_SET_COMP: - scope->simple_name = MP_QSTR__lt_setcomp_gt_; - break; - case SCOPE_GEN_EXPR: - scope->simple_name = MP_QSTR__lt_genexpr_gt_; - break; - default: - assert(0); + if (kind == SCOPE_FUNCTION || kind == SCOPE_CLASS) { + qstr id; + pt_extract_id(pn, &id); // function name + scope->simple_name = id; + } else { + scope->simple_name = scope_simple_name_table[kind]; } scope->emit_options = emit_options; scope->id_info_alloc = MICROPY_ALLOC_SCOPE_ID_INIT; @@ -115,22 +106,10 @@ id_info_t *scope_find_global(scope_t *scope, qstr qst) { return scope_find(scope, qst); } -id_info_t *scope_find_local_in_parent(scope_t *scope, qstr qst) { - if (scope->parent == NULL) { - return NULL; - } - for (scope_t *s = scope->parent; s->parent != NULL; s = s->parent) { - id_info_t *id = scope_find(s, qst); - if (id != NULL) { - return id; - } - } - return NULL; -} - -void scope_close_over_in_parents(scope_t *scope, qstr qst) { +STATIC void scope_close_over_in_parents(scope_t *scope, qstr qst) { assert(scope->parent != NULL); // we should have at least 1 parent - for (scope_t *s = scope->parent; s->parent != NULL; s = s->parent) { + for (scope_t *s = scope->parent;; s = s->parent) { + assert(s->parent != NULL); // we should not get to the outer scope bool added; id_info_t *id = scope_find_or_add_id(s, qst, &added); if (added) { @@ -138,16 +117,34 @@ void scope_close_over_in_parents(scope_t *scope, qstr qst) { id->kind = ID_INFO_KIND_FREE; } else { // variable is declared in this scope, so finish - switch (id->kind) { - case ID_INFO_KIND_LOCAL: id->kind = ID_INFO_KIND_CELL; break; // variable local to this scope, close it over - case ID_INFO_KIND_FREE: break; // variable already closed over in a parent scope - case ID_INFO_KIND_CELL: break; // variable already closed over in this scope - default: assert(0); // TODO + if (id->kind == ID_INFO_KIND_LOCAL) { + // variable local to this scope, close it over + id->kind = ID_INFO_KIND_CELL; + } else { + // ID_INFO_KIND_FREE: variable already closed over in a parent scope + // ID_INFO_KIND_CELL: variable already closed over in this scope + assert(id->kind == ID_INFO_KIND_FREE || id->kind == ID_INFO_KIND_CELL); } return; } } - assert(0); // we should have found the variable in one of the parents +} + +void scope_find_local_and_close_over(scope_t *scope, id_info_t *id, qstr qst) { + if (scope->parent != NULL) { + for (scope_t *s = scope->parent; s->parent != NULL; s = s->parent) { + id_info_t *id2 = scope_find(s, qst); + if (id2 != NULL) { + if (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE) { + id->kind = ID_INFO_KIND_FREE; + scope_close_over_in_parents(scope, qst); + return; + } + break; + } + } + } + id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; } #endif // MICROPY_ENABLE_COMPILER diff --git a/py/scope.h b/py/scope.h index e210a5a9cf..012d906475 100644 --- a/py/scope.h +++ b/py/scope.h @@ -52,14 +52,26 @@ typedef struct _id_info_t { qstr qst; } id_info_t; +#define SCOPE_IS_FUNC_LIKE(s) ((s) >= SCOPE_LAMBDA) + // scope is a "block" in Python parlance -typedef enum { SCOPE_MODULE, SCOPE_FUNCTION, SCOPE_LAMBDA, SCOPE_LIST_COMP, SCOPE_DICT_COMP, SCOPE_SET_COMP, SCOPE_GEN_EXPR, SCOPE_CLASS } scope_kind_t; +typedef enum { + SCOPE_MODULE, + SCOPE_CLASS, + SCOPE_LAMBDA, + SCOPE_LIST_COMP, + SCOPE_DICT_COMP, + SCOPE_SET_COMP, + SCOPE_GEN_EXPR, + SCOPE_FUNCTION, +} scope_kind_t; + typedef struct _scope_t { scope_kind_t kind; struct _scope_t *parent; const byte *pn; // points to the node after the scope index node - qstr source_file; - qstr simple_name; + uint16_t source_file; // a qstr + uint16_t simple_name; // a qstr mp_raw_code_t *raw_code; uint8_t scope_flags; // see runtime0.h uint8_t emit_options; // see compile.h @@ -79,7 +91,6 @@ void scope_free(scope_t *scope); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added); id_info_t *scope_find(scope_t *scope, qstr qstr); id_info_t *scope_find_global(scope_t *scope, qstr qstr); -id_info_t *scope_find_local_in_parent(scope_t *scope, qstr qstr); -void scope_close_over_in_parents(scope_t *scope, qstr qstr); +void scope_find_local_and_close_over(scope_t *scope, id_info_t *id, qstr qst); #endif // __MICROPY_INCLUDED_PY_SCOPE_H__ diff --git a/py/sequence.c b/py/sequence.c index 239f1b2cc5..0acdd25be0 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -235,7 +235,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args } } - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "object not in sequence")); + mp_raise_msg(&mp_type_ValueError, "object not in sequence"); } mp_obj_t mp_seq_count_obj(const mp_obj_t *items, mp_uint_t len, mp_obj_t value) { diff --git a/py/showbc.c b/py/showbc.c index dd5959f4a9..684d9af0c0 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -32,6 +32,9 @@ #if MICROPY_DEBUG_PRINTERS +// redirect all printfs in this file to the platform print stream +#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__) + #define DECODE_UINT { \ unum = 0; \ do { \ @@ -96,6 +99,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m #if MICROPY_PERSISTENT_CODE qstr block_name = code_info[0] | (code_info[1] << 8); qstr source_file = code_info[2] | (code_info[3] << 8); + code_info += 4; #else qstr block_name = mp_decode_uint(&code_info); qstr source_file = mp_decode_uint(&code_info); @@ -409,11 +413,6 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("BUILD_LIST " UINT_FMT, unum); break; - case MP_BC_LIST_APPEND: - DECODE_UINT; - printf("LIST_APPEND " UINT_FMT, unum); - break; - case MP_BC_BUILD_MAP: DECODE_UINT; printf("BUILD_MAP " UINT_FMT, unum); @@ -423,21 +422,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("STORE_MAP"); break; - case MP_BC_MAP_ADD: - DECODE_UINT; - printf("MAP_ADD " UINT_FMT, unum); - break; - case MP_BC_BUILD_SET: DECODE_UINT; printf("BUILD_SET " UINT_FMT, unum); break; - case MP_BC_SET_ADD: - DECODE_UINT; - printf("SET_ADD " UINT_FMT, unum); - break; - #if MICROPY_PY_BUILTINS_SLICE case MP_BC_BUILD_SLICE: DECODE_UINT; @@ -445,6 +434,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { break; #endif + case MP_BC_STORE_COMP: + DECODE_UINT; + printf("STORE_COMP " UINT_FMT, unum); + break; + case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; printf("UNPACK_SEQUENCE " UINT_FMT, unum); diff --git a/py/stream.c b/py/stream.c index eef9080b7b..cc8a63ac2e 100644 --- a/py/stream.c +++ b/py/stream.c @@ -101,7 +101,7 @@ const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { // CPython: io.UnsupportedOperation, OSError subclass - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "stream operation not supported")); + mp_raise_msg(&mp_type_OSError, "stream operation not supported"); } return stream_p; } @@ -159,7 +159,7 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl } break; } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } if (out_sz < more_bytes) { @@ -227,7 +227,7 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl // this as EOF. return mp_const_none; } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } else { vstr.len = out_sz; return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); @@ -256,7 +256,7 @@ mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len, byte fla // no single byte could be readily written to it." return mp_const_none; } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } else { return MP_OBJ_NEW_SMALL_INT(out_sz); } @@ -315,7 +315,7 @@ STATIC mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { if (mp_is_nonblocking_error(error)) { return mp_const_none; } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } else { return MP_OBJ_NEW_SMALL_INT(out_sz); } @@ -343,7 +343,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { } break; } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } if (out_sz == 0) { break; @@ -355,10 +355,6 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { } else { p = vstr_extend(&vstr, DEFAULT_BUFFER_SIZE); current_read = DEFAULT_BUFFER_SIZE; - if (p == NULL) { - // TODO - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory")); - } } } @@ -406,7 +402,7 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) goto done; } } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } if (out_sz == 0) { done: @@ -461,7 +457,7 @@ STATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) { int error; mp_uint_t res = stream_p->ioctl(args[0], MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error); if (res == MP_STREAM_ERROR) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } // TODO: Could be uint64 @@ -482,7 +478,7 @@ STATIC mp_obj_t stream_flush(mp_obj_t self) { int error; mp_uint_t res = stream_p->ioctl(self, MP_STREAM_FLUSH, 0, &error); if (res == MP_STREAM_ERROR) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } return mp_const_none; } @@ -504,7 +500,7 @@ STATIC mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) { int error; mp_uint_t res = stream_p->ioctl(args[0], mp_obj_get_int(args[1]), val, &error); if (res == MP_STREAM_ERROR) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); + mp_raise_OSError(error); } return mp_obj_new_int(res); @@ -587,6 +587,8 @@ dispatch_loop: // and __exit__ method (with self) underneath it. Bytecode calls __exit__, // and "deletes" it off stack, shifting "exception control block" // to its place. + // The bytecode emitter ensures that there is enough space on the Python + // value stack to hold the __exit__ method plus an additional 4 entries. if (TOP() == mp_const_none) { // stack: (..., __exit__, ctx_mgr, None) sp[1] = mp_const_none; @@ -620,31 +622,26 @@ dispatch_loop: } sp -= 2; // we removed (__exit__, ctx_mgr) } else { - assert(mp_obj_is_exception_type(TOP())); - // stack: (..., __exit__, ctx_mgr, traceback, exc_val, exc_type) - // Need to pass (sp[0], sp[-1], sp[-2]) as arguments so must reverse the - // order of these on the value stack (don't want to create a temporary - // array because it increases stack footprint of the VM). - mp_obj_t obj = sp[-2]; - sp[-2] = sp[0]; - sp[0] = obj; - mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp - 4); + assert(mp_obj_is_exception_instance(TOP())); + // stack: (..., __exit__, ctx_mgr, exc_instance) + // Need to pass (exc_type, exc_instance, None) as arguments to __exit__. + sp[1] = sp[0]; + sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0])); + sp[2] = mp_const_none; + sp -= 2; + mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp); if (mp_obj_is_true(ret_value)) { // We need to silence/swallow the exception. This is done // by popping the exception and the __exit__ handler and // replacing it with None, which signals END_FINALLY to just // execute the finally handler normally. - sp -= 4; SET_TOP(mp_const_none); assert(exc_sp >= exc_stack); POP_EXC_BLOCK(); } else { // We need to re-raise the exception. We pop __exit__ handler - // and copy the 3 exception values down (remembering that they - // are reversed due to above code). - sp[-4] = sp[0]; - sp[-3] = sp[-1]; - sp -= 2; + // by copying the exception instance down to the new top-of-stack. + sp[0] = sp[3]; } } DISPATCH(); @@ -698,18 +695,12 @@ unwind_jump:; ENTRY(MP_BC_END_FINALLY): MARK_EXC_IP_SELECTIVE(); - // not fully implemented - // if TOS is an exception, reraises the exception (3 values on TOS) // if TOS is None, just pops it and continues - // if TOS is an integer, does something else - // else error - if (mp_obj_is_exception_type(TOP())) { - RAISE(sp[-1]); - } + // if TOS is an integer, finishes coroutine and returns control to caller + // if TOS is an exception, reraises the exception if (TOP() == mp_const_none) { sp--; - } else { - assert(MP_OBJ_IS_SMALL_INT(TOP())); + } else if (MP_OBJ_IS_SMALL_INT(TOP())) { // We finished "finally" coroutine and now dispatch back // to our caller, based on TOS value mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP()); @@ -719,6 +710,9 @@ unwind_jump:; assert(reason == UNWIND_JUMP); goto unwind_jump; } + } else { + assert(mp_obj_is_exception_instance(TOP())); + RAISE(TOP()); } DISPATCH(); @@ -751,14 +745,9 @@ unwind_jump:; // matched against: SETUP_EXCEPT ENTRY(MP_BC_POP_EXCEPT): - // TODO need to work out how blocks work etc - // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate assert(exc_sp >= exc_stack); assert(currently_in_except_block); - //sp = (mp_obj_t*)(*exc_sp--); - //exc_sp--; // discard ip POP_EXC_BLOCK(); - //sp -= 3; // pop 3 exception values DISPATCH(); ENTRY(MP_BC_BUILD_TUPLE): { @@ -777,15 +766,6 @@ unwind_jump:; DISPATCH(); } - ENTRY(MP_BC_LIST_APPEND): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[unum] is a list - mp_obj_list_append(sp[-unum], sp[0]); - sp--; - DISPATCH(); - } - ENTRY(MP_BC_BUILD_MAP): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; @@ -799,15 +779,6 @@ unwind_jump:; mp_obj_dict_store(sp[0], sp[2], sp[1]); DISPATCH(); - ENTRY(MP_BC_MAP_ADD): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[-unum - 1] is a map - mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]); - sp -= 2; - DISPATCH(); - } - #if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): { MARK_EXC_IP_SELECTIVE(); @@ -816,15 +787,6 @@ unwind_jump:; SET_TOP(mp_obj_new_set(unum, sp)); DISPATCH(); } - - ENTRY(MP_BC_SET_ADD): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[-unum] is a set - mp_obj_set_store(sp[-unum], sp[0]); - sp--; - DISPATCH(); - } #endif #if MICROPY_PY_BUILTINS_SLICE @@ -845,6 +807,25 @@ unwind_jump:; } #endif + ENTRY(MP_BC_STORE_COMP): { + MARK_EXC_IP_SELECTIVE(); + DECODE_UINT; + mp_obj_t obj = sp[-(unum >> 2)]; + if ((unum & 3) == 0) { + mp_obj_list_append(obj, sp[0]); + sp--; + } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) { + mp_obj_dict_store(obj, sp[0], sp[-1]); + sp -= 2; + #if MICROPY_PY_BUILTINS_SET + } else { + mp_obj_set_store(obj, sp[0]); + sp--; + #endif + } + DISPATCH(); + } + ENTRY(MP_BC_UNPACK_SEQUENCE): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; @@ -1367,10 +1348,8 @@ unwind_loop: mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp); // save this exception in the stack so it can be used in a reraise, if needed exc_sp->prev_exc = nlr.ret_val; - // push(traceback, exc-val, exc-type) - PUSH(mp_const_none); + // push exception object so it can be handled by bytecode PUSH(MP_OBJ_FROM_PTR(nlr.ret_val)); - PUSH(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type)); code_state->sp = sp; #if MICROPY_STACKLESS diff --git a/py/vmentrytable.h b/py/vmentrytable.h index 9df1e40a32..dd30dd7a54 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -78,17 +78,15 @@ static const void *const entry_table[256] = { [MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT, [MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE, [MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST, - [MP_BC_LIST_APPEND] = &&entry_MP_BC_LIST_APPEND, [MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP, [MP_BC_STORE_MAP] = &&entry_MP_BC_STORE_MAP, - [MP_BC_MAP_ADD] = &&entry_MP_BC_MAP_ADD, #if MICROPY_PY_BUILTINS_SET [MP_BC_BUILD_SET] = &&entry_MP_BC_BUILD_SET, - [MP_BC_SET_ADD] = &&entry_MP_BC_SET_ADD, #endif #if MICROPY_PY_BUILTINS_SLICE [MP_BC_BUILD_SLICE] = &&entry_MP_BC_BUILD_SLICE, #endif + [MP_BC_STORE_COMP] = &&entry_MP_BC_STORE_COMP, [MP_BC_UNPACK_SEQUENCE] = &&entry_MP_BC_UNPACK_SEQUENCE, [MP_BC_UNPACK_EX] = &&entry_MP_BC_UNPACK_EX, [MP_BC_MAKE_FUNCTION] = &&entry_MP_BC_MAKE_FUNCTION, @@ -44,11 +44,6 @@ void vstr_init(vstr_t *vstr, size_t alloc) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = m_new(char, vstr->alloc); - if (vstr->buf == NULL) { - vstr->had_error = true; - return; - } - vstr->had_error = false; vstr->fixed_buf = false; } @@ -63,7 +58,6 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = buf; - vstr->had_error = false; vstr->fixed_buf = true; } @@ -80,20 +74,8 @@ void vstr_clear(vstr_t *vstr) { vstr->buf = NULL; } -vstr_t *vstr_new(void) { +vstr_t *vstr_new(size_t alloc) { vstr_t *vstr = m_new_obj(vstr_t); - if (vstr == NULL) { - return NULL; - } - vstr_init(vstr, 16); - return vstr; -} - -vstr_t *vstr_new_size(size_t alloc) { - vstr_t *vstr = m_new_obj(vstr_t); - if (vstr == NULL) { - return NULL; - } vstr_init(vstr, alloc); return vstr; } @@ -107,39 +89,12 @@ void vstr_free(vstr_t *vstr) { } } -void vstr_reset(vstr_t *vstr) { - vstr->len = 0; - vstr->had_error = false; -} - -bool vstr_had_error(vstr_t *vstr) { - return vstr->had_error; -} - -char *vstr_str(vstr_t *vstr) { - if (vstr->had_error) { - return NULL; - } - return vstr->buf; -} - -size_t vstr_len(vstr_t *vstr) { - if (vstr->had_error) { - return 0; - } - return vstr->len; -} - // 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; } char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size); - if (new_buf == NULL) { - vstr->had_error = true; - return NULL; - } char *p = new_buf + vstr->alloc; vstr->alloc += size; vstr->buf = new_buf; @@ -153,10 +108,6 @@ STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { } size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16); char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc); - if (new_buf == NULL) { - vstr->had_error = true; - return false; - } vstr->alloc = new_alloc; vstr->buf = new_buf; } @@ -164,14 +115,11 @@ STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { } void vstr_hint_size(vstr_t *vstr, size_t size) { - // it's not an error if we fail to allocate for the size hint - bool er = vstr->had_error; vstr_ensure_extra(vstr, size); - vstr->had_error = er; } char *vstr_add_len(vstr_t *vstr, size_t len) { - if (vstr->had_error || !vstr_ensure_extra(vstr, len)) { + if (!vstr_ensure_extra(vstr, len)) { return NULL; } char *buf = vstr->buf + vstr->len; @@ -181,9 +129,6 @@ char *vstr_add_len(vstr_t *vstr, size_t len) { // Doesn't increase len, just makes sure there is a null byte at the end char *vstr_null_terminated_str(vstr_t *vstr) { - if (vstr->had_error) { - return NULL; - } // If there's no more room, add single byte if (vstr->alloc == vstr->len) { if (vstr_extend(vstr, 1) == NULL) { @@ -248,7 +193,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->had_error || !vstr_ensure_extra(vstr, 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) { @@ -263,9 +208,6 @@ copy: } char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) { - if (vstr->had_error) { - return NULL; - } size_t l = vstr->len; if (byte_pos > l) { byte_pos = l; @@ -303,9 +245,6 @@ void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) { } void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { - if (vstr->had_error) { - return; - } if (len > vstr->len) { vstr->len = 0; } else { @@ -314,7 +253,7 @@ void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { } void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) { - if (vstr->had_error || byte_pos >= vstr->len) { + if (byte_pos >= vstr->len) { return; } else if (byte_pos + bytes_to_cut >= vstr->len) { vstr->len = byte_pos; |