summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/argcheck.c16
-rw-r--r--py/asmthumb.c9
-rw-r--r--py/bc.c9
-rw-r--r--py/bc0.h4
-rw-r--r--py/builtinevex.c2
-rw-r--r--py/builtinimport.c10
-rw-r--r--py/compile.c83
-rw-r--r--py/emit.h8
-rw-r--r--py/emitbc.c73
-rw-r--r--py/emitcommon.c16
-rw-r--r--py/emitglue.c2
-rw-r--r--py/emitnative.c67
-rw-r--r--py/lexer.c15
-rw-r--r--py/makeqstrdefs.py2
-rw-r--r--py/misc.h11
-rw-r--r--py/mkenv.mk2
-rw-r--r--py/mkrules.mk6
-rw-r--r--py/modarray.c1
-rw-r--r--py/modbuiltins.c12
-rw-r--r--py/modcmath.c1
-rw-r--r--py/modcollections.c1
-rw-r--r--py/modgc.c1
-rw-r--r--py/modio.c3
-rw-r--r--py/modmath.c1
-rw-r--r--py/modmicropython.c13
-rw-r--r--py/modstruct.c5
-rw-r--r--py/modsys.c1
-rw-r--r--py/modthread.c5
-rw-r--r--py/moduerrno.c1
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/mphal.h4
-rw-r--r--py/mpprint.c4
-rw-r--r--py/mpz.c41
-rw-r--r--py/mpz.h1
-rw-r--r--py/obj.c31
-rw-r--r--py/obj.h1
-rw-r--r--py/objarray.c4
-rw-r--r--py/objbool.c23
-rw-r--r--py/objcomplex.c4
-rw-r--r--py/objdict.c17
-rw-r--r--py/objfloat.c2
-rw-r--r--py/objfun.c33
-rw-r--r--py/objgenerator.c6
-rw-r--r--py/objint.c26
-rw-r--r--py/objint.h8
-rw-r--r--py/objint_longlong.c2
-rw-r--r--py/objint_mpz.c13
-rw-r--r--py/objlist.c2
-rw-r--r--py/objmodule.c13
-rw-r--r--py/objnamedtuple.c2
-rw-r--r--py/objnone.c11
-rw-r--r--py/objobject.c3
-rw-r--r--py/objset.c31
-rw-r--r--py/objstr.c5
-rw-r--r--py/objstringio.c14
-rw-r--r--py/objstringio.h38
-rw-r--r--py/objtype.c21
-rw-r--r--py/parse.c23
-rw-r--r--py/parsenum.c4
-rw-r--r--py/py.mk9
-rw-r--r--py/qstr.c1
-rw-r--r--py/runtime.c58
-rw-r--r--py/runtime.h5
-rw-r--r--py/scope.c89
-rw-r--r--py/scope.h21
-rw-r--r--py/sequence.c2
-rw-r--r--py/showbc.c24
-rw-r--r--py/stream.c24
-rw-r--r--py/vm.c97
-rw-r--r--py/vmentrytable.h4
-rw-r--r--py/vstr.c69
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
diff --git a/py/bc.c b/py/bc.c
index 0d0a0b12f9..07de08fc36 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -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
diff --git a/py/bc0.h b/py/bc0.h
index b0b7d5c795..5ff9e50a89 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -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
diff --git a/py/emit.h b/py/emit.h
index 652e6118fb..ddc1dad0ec 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -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):
diff --git a/py/misc.h b/py/misc.h
index 56ec84ee36..0be4a87758 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -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) {
diff --git a/py/mpz.c b/py/mpz.c
index bb76479569..cceb079cd3 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -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) {
diff --git a/py/mpz.h b/py/mpz.h
index 63ac772ffd..55ef3e15ff 100644
--- a/py/mpz.h
+++ b/py/mpz.h
@@ -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);
diff --git a/py/obj.c b/py/obj.c
index d6ce3dae6a..72b7a216bc 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -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");
}
}
diff --git a/py/obj.h b/py/obj.h
index 22aa196fd1..72d79ce14b 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -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
diff --git a/py/py.mk b/py/py.mk
index e1981d3e98..ec476af0ef 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -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 \
diff --git a/py/qstr.c b/py/qstr.c
index 079b2a8e7e..28df06ca3d 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -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);
diff --git a/py/vm.c b/py/vm.c
index f9bdedff88..363824e5f1 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -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,
diff --git a/py/vstr.c b/py/vstr.c
index 2e53744362..bd05c28de2 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -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;