diff --git a/py/builtin.c b/py/builtin.c index d29a2bf8c3..b565ed4640 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -8,6 +8,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime0.h" #include "runtime.h" @@ -91,7 +92,7 @@ mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args) { switch (n_args) { case 0: return mp_const_false; case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } - default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args)); } } @@ -147,7 +148,7 @@ mp_obj_t mp_builtin_chr(mp_obj_t o_in) { str[1] = '\0'; return mp_obj_new_str(qstr_from_str_take(str, 2)); } else { - nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "chr() arg not in range(0x110000)")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)")); } } @@ -165,7 +166,7 @@ mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2); return rt_build_tuple(2, revs_args); } else { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); } } @@ -235,7 +236,7 @@ mp_obj_t mp_builtin_len(mp_obj_t o_in) { } else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) { len = mp_obj_dict_len(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); } return MP_OBJ_NEW_SMALL_INT(len); } @@ -254,7 +255,7 @@ mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) { } return list; } - default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args)); } } @@ -270,7 +271,7 @@ mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) { } } if (max_obj == NULL) { - nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "max() arg is an empty sequence")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "max() arg is an empty sequence")); } return max_obj; } else { @@ -297,7 +298,7 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) { } } if (min_obj == NULL) { - nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "min() arg is an empty sequence")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "min() arg is an empty sequence")); } return min_obj; } else { @@ -315,7 +316,7 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) { static mp_obj_t mp_builtin_next(mp_obj_t o) { mp_obj_t ret = rt_iternext(o); if (ret == mp_const_stop_iteration) { - nlr_jump(mp_obj_new_exception(qstr_from_str_static("StopIteration"))); + nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration)); } else { return ret; } @@ -328,7 +329,7 @@ mp_obj_t mp_builtin_ord(mp_obj_t o_in) { if (strlen(str) == 1) { return mp_obj_new_int(str[0]); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str))); } } @@ -336,7 +337,7 @@ mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) { switch (n_args) { case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]); case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise... - default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); } } @@ -362,7 +363,7 @@ mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) { case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1); case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1); case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2])); - default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); } } @@ -391,7 +392,7 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { switch (n_args) { case 1: value = mp_obj_new_int(0); break; case 2: value = args[1]; break; - default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args)); } mp_obj_t iterable = rt_getiter(args[0]); mp_obj_t item; diff --git a/py/builtinimport.c b/py/builtinimport.c index 47dbf21216..90a0fc3394 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -58,7 +58,9 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) { return mp_const_none; } - if (!mp_compile(pn, false)) { + mp_obj_t module_fun = mp_compile(pn, false); + + if (module_fun == mp_const_none) { // TODO handle compile error correctly rt_locals_set(old_locals); rt_globals_set(old_globals); @@ -66,7 +68,6 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) { } // complied successfully, execute it - mp_obj_t module_fun = rt_make_function_from_id(1); // TODO we should return from mp_compile the unique_code_id for the module nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { rt_call_function_0(module_fun); diff --git a/py/compile.c b/py/compile.c index 8db7c6d942..f8fa2cb2c2 100644 --- a/py/compile.c +++ b/py/compile.c @@ -7,6 +7,7 @@ #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "lexer.h" #include "parse.h" #include "scope.h" @@ -38,20 +39,6 @@ typedef enum { #define EMIT_OPT_ASM_THUMB (4) typedef struct _compiler_t { - qstr qstr___class__; - qstr qstr___locals__; - qstr qstr___name__; - qstr qstr___module__; - qstr qstr___qualname__; - qstr qstr___doc__; - qstr qstr_assertion_error; - qstr qstr_micropython; - qstr qstr_byte_code; - qstr qstr_native; - qstr qstr_viper; - qstr qstr_asm_thumb; - qstr qstr_range; - bool is_repl; pass_kind_t pass; bool had_error; // try to keep compiler clean from nlr @@ -202,7 +189,7 @@ static int comp_next_label(compiler_t *comp) { } static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) { - scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options); + scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(), emit_options); scope->parent = comp->scope_cur; scope->next = NULL; if (comp->scope_head == NULL) { @@ -903,7 +890,7 @@ qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint // returns true if it was a built-in decorator (even if the built-in had an error) static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) { - if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) { + if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) { return false; } @@ -913,16 +900,16 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_ } qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]); - if (attr == comp->qstr_byte_code) { + if (attr == MP_QSTR_byte_code) { *emit_options = EMIT_OPT_BYTE_CODE; #if MICROPY_EMIT_NATIVE - } else if (attr == comp->qstr_native) { + } else if (attr == MP_QSTR_native) { *emit_options = EMIT_OPT_NATIVE_PYTHON; - } else if (attr == comp->qstr_viper) { + } else if (attr == MP_QSTR_viper) { *emit_options = EMIT_OPT_VIPER; #endif #if MICROPY_EMIT_INLINE_THUMB - } else if (attr == comp->qstr_asm_thumb) { + } else if (attr == MP_QSTR_asm_thumb) { *emit_options = EMIT_OPT_ASM_THUMB; #endif } else { @@ -1329,7 +1316,7 @@ void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { int l_end = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], true, l_end); - EMIT(load_id, comp->qstr_assertion_error); + EMIT(load_id, MP_QSTR_assertion_error); if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // assertion message compile_node(comp, pns->nodes[1]); @@ -1495,7 +1482,7 @@ void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // for viper it will be much, much faster if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) { mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1]; - if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == comp->qstr_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) { + if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) { mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0]; mp_parse_node_t *args; int n_args = list_get(&pn_range_args, PN_arglist, &args); @@ -1743,7 +1730,7 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) { // for REPL, evaluate then print the expression - EMIT(load_id, qstr_from_str_static("__repl_print__")); + EMIT(load_id, MP_QSTR___repl_print__); compile_node(comp, pns->nodes[0]); EMIT(call_function, 1, 0, false, false); EMIT(pop_top); @@ -2683,7 +2670,7 @@ void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { if (kind == MP_PARSE_NODE_STRING) { compile_node(comp, pns->nodes[0]); // a doc string // store doc string - EMIT(store_id, comp->qstr___doc__); + EMIT(store_id, MP_QSTR___doc__); } } } @@ -2796,35 +2783,35 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { if (comp->pass == PASS_1) { bool added; - id_info_t *id_info = scope_find_or_add_id(scope, comp->qstr___class__, &added); + id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added); assert(added); id_info->kind = ID_INFO_KIND_LOCAL; - id_info = scope_find_or_add_id(scope, comp->qstr___locals__, &added); + id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added); assert(added); id_info->kind = ID_INFO_KIND_LOCAL; id_info->param = true; scope->num_params = 1; // __locals__ is the parameter } - EMIT(load_id, comp->qstr___locals__); + EMIT(load_id, MP_QSTR___locals__); EMIT(store_locals); - EMIT(load_id, comp->qstr___name__); - EMIT(store_id, comp->qstr___module__); + EMIT(load_id, MP_QSTR___name__); + EMIT(store_id, MP_QSTR___module__); EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name - EMIT(store_id, comp->qstr___qualname__); + EMIT(store_id, MP_QSTR___qualname__); check_for_doc_string(comp, pns->nodes[2]); compile_node(comp, pns->nodes[2]); // 2 is class body - id_info_t *id = scope_find(scope, comp->qstr___class__); + id_info_t *id = scope_find(scope, MP_QSTR___class__); assert(id != NULL); if (id->kind == ID_INFO_KIND_LOCAL) { EMIT(load_const_tok, MP_TOKEN_KW_NONE); } else { #if MICROPY_EMIT_CPYTHON - EMIT(load_closure, comp->qstr___class__, 0); // XXX check this is the correct local num + EMIT(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num #else - EMIT(load_fast, comp->qstr___class__, 0); // XXX check this is the correct local num + EMIT(load_fast, MP_QSTR___class__, 0); // XXX check this is the correct local num #endif } EMIT(return_value); @@ -2917,7 +2904,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) { scope->num_locals = 0; for (int i = 0; i < scope->id_info_len; i++) { id_info_t *id = &scope->id_info[i]; - if (scope->kind == SCOPE_CLASS && id->qstr == comp->qstr___class__) { + if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) { // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL continue; } @@ -3021,20 +3008,6 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) { mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) { compiler_t *comp = m_new(compiler_t, 1); - comp->qstr___class__ = qstr_from_str_static("__class__"); - comp->qstr___locals__ = qstr_from_str_static("__locals__"); - comp->qstr___name__ = qstr_from_str_static("__name__"); - comp->qstr___module__ = qstr_from_str_static("__module__"); - comp->qstr___qualname__ = qstr_from_str_static("__qualname__"); - comp->qstr___doc__ = qstr_from_str_static("__doc__"); - comp->qstr_assertion_error = qstr_from_str_static("AssertionError"); - comp->qstr_micropython = qstr_from_str_static("micropython"); - comp->qstr_byte_code = qstr_from_str_static("byte_code"); - comp->qstr_native = qstr_from_str_static("native"); - comp->qstr_viper = qstr_from_str_static("viper"); - comp->qstr_asm_thumb = qstr_from_str_static("asm_thumb"); - comp->qstr_range = qstr_from_str_static("range"); - comp->is_repl = is_repl; comp->had_error = false; @@ -3048,10 +3021,10 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) { pn = fold_constants(pn); // set the outer scope - scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE); + scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE); // compile pass 1 - comp->emit = emit_pass1_new(comp->qstr___class__); + comp->emit = emit_pass1_new(MP_QSTR___class__); comp->emit_method_table = &emit_pass1_method_table; comp->emit_inline_asm = NULL; comp->emit_inline_asm_method_table = NULL; @@ -3162,10 +3135,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) { } else { #if MICROPY_EMIT_CPYTHON // can't create code, so just return true + (void)module_scope; // to suppress warning that module_scope is unused return mp_const_true; #else // return function that executes the outer module - return rt_make_function_from_id(1); + return rt_make_function_from_id(module_scope->unique_code_id); #endif } } diff --git a/py/mpqstr.h b/py/mpqstr.h new file mode 100644 index 0000000000..1440fb3b80 --- /dev/null +++ b/py/mpqstr.h @@ -0,0 +1,13 @@ +// See mpqstrraw.h for a list of qstr's that are available as constants. +// Reference them as MP_QSTR_xxxx. +// +// Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static("xxx") +// for qstrs that are referenced this way, but you don't want to have them in ROM. + +enum { + MP_QSTR_nil = 0, +#define Q(id) MP_QSTR_##id, +#include "mpqstrraw.h" +#undef Q + MP_QSTR_number_of, +} category_t; diff --git a/py/mpqstrraw.h b/py/mpqstrraw.h new file mode 100644 index 0000000000..85cf1ff7bd --- /dev/null +++ b/py/mpqstrraw.h @@ -0,0 +1,63 @@ +// All the qstr definitions in this file are available as constants. +// That is, they are in ROM and you can reference them simple as MP_QSTR_xxxx. + +Q(__build_class__) +Q(__class__) +Q(__doc__) +Q(__init__) +Q(__locals__) +Q(__main__) +Q(__module__) +Q(__name__) +Q(__next__) +Q(__qualname__) +Q(__repl_print__) + +Q(assertion_error) +Q(micropython) +Q(byte_code) +Q(native) +Q(viper) +Q(asm_thumb) + +Q(StopIteration) + +Q(AttributeError) +Q(IndexError) +Q(KeyError) +Q(NameError) +Q(TypeError) +Q(SyntaxError) +Q(ValueError) + +Q(abs) +Q(all) +Q(any) +Q(bool) +Q(callable) +Q(chr) +Q(complex) +Q(dict) +Q(divmod) +Q(float) +Q(hash) +Q(int) +Q(iter) +Q(len) +Q(list) +Q(max) +Q(min) +Q(next) +Q(ord) +Q(pow) +Q(print) +Q(range) +Q(set) +Q(sum) +Q(type) + +Q(append) +Q(pop) +Q(sort) +Q(join) +Q(format) diff --git a/py/obj.c b/py/obj.c index d88d0ac3d7..2b834ffe43 100644 --- a/py/obj.c +++ b/py/obj.c @@ -7,6 +7,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime0.h" #include "runtime.h" @@ -144,7 +145,7 @@ machine_float_t mp_obj_get_float(mp_obj_t arg) { } else if (MP_OBJ_IS_TYPE(arg, &float_type)) { return mp_obj_float_get(arg); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); } } @@ -164,7 +165,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { } else if (MP_OBJ_IS_TYPE(arg, &complex_type)) { mp_obj_complex_get(arg, real, imag); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); } } #endif @@ -188,11 +189,11 @@ mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) { mp_obj_list_get(o_in, &seq_len, &seq_items); } if (seq_len != n) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len)); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len)); } return seq_items; } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); } } @@ -204,10 +205,10 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index) i += len; } if (i < 0 || i >= len) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_IndexError, "%s index out of range", type->name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_IndexError, "%s index out of range", type->name)); } return i; } else { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index))); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index))); } } diff --git a/py/objclass.c b/py/objclass.c index 203923a722..f223c5ff25 100644 --- a/py/objclass.c +++ b/py/objclass.c @@ -6,6 +6,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime.h" #include "map.h" @@ -25,7 +26,7 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_t o = mp_obj_new_instance(self_in); // look for __init__ function - mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, qstr_from_str_static("__init__"), false); + mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, MP_QSTR___init__, false); if (init_fn != NULL) { // call __init__ function @@ -40,13 +41,13 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { m_del(mp_obj_t, args2, n_args + 1); } if (init_ret != mp_const_none) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); } } else { // TODO if (n_args != 0) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args)); } } diff --git a/py/objdict.c b/py/objdict.c index 50ce279040..acf1a9f801 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -6,6 +6,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime0.h" #include "runtime.h" @@ -42,7 +43,7 @@ mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // dict load mp_map_elem_t *elem = mp_map_lookup_helper(&o->map, rhs_in, false); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg(rt_q_KeyError, "")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "")); } else { return elem->value; } diff --git a/py/objfun.c b/py/objfun.c index e998bd28d2..c4783867a5 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -6,6 +6,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "map.h" #include "runtime.h" @@ -24,7 +25,7 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { // check number of arguments if (n_args != self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args)); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args)); } // dispatch function call @@ -47,9 +48,9 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { // function takes a variable number of arguments if (n_args < self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "() missing %d required positional arguments: ", (const char*)(machine_int_t)(self->n_args_min - n_args))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "() missing %d required positional arguments: ", (const char*)(machine_int_t)(self->n_args_min - n_args))); } else if (n_args > self->n_args_max) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, " expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, " expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); } // TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args @@ -141,7 +142,7 @@ mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_fun_bc_t *self = self_in; if (n_args != self->n_args) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args)); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args)); } // optimisation: allow the compiler to optimise this tail call for @@ -250,7 +251,7 @@ mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_fun_asm_t *self = self_in; if (n_args != self->n_args) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args)); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args)); } machine_uint_t ret; diff --git a/py/objgenerator.c b/py/objgenerator.c index ecdd72dc6d..849212269b 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -6,6 +6,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime.h" #include "bc.h" @@ -29,7 +30,7 @@ mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { const byte *bc_code; mp_obj_fun_bc_get(self_fun, &bc_n_args, &bc_n_state, &bc_code); if (n_args != bc_n_args) { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args)); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args)); } return mp_obj_new_gen_instance(bc_code, self->n_state, n_args, args); diff --git a/py/objinstance.c b/py/objinstance.c index e5d23af2d5..6cfcdf6c15 100644 --- a/py/objinstance.c +++ b/py/objinstance.c @@ -6,6 +6,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime.h" #include "map.h" @@ -44,7 +45,7 @@ mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) { return elem->value; } } - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(self_in), qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(self_in), qstr_str(attr))); } void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { diff --git a/py/objlist.c b/py/objlist.c index e371057981..30d3a41e4a 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -6,6 +6,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime0.h" #include "runtime.h" @@ -81,7 +82,7 @@ static mp_obj_t list_pop(int n_args, const mp_obj_t *args) { assert(MP_OBJ_IS_TYPE(args[0], &list_type)); mp_obj_list_t *self = args[0]; if (self->len == 0) { - nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "pop from empty list")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "pop from empty list")); } uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? mp_obj_new_int(-1) : args[1]); mp_obj_t ret = self->items[index]; diff --git a/py/objstr.c b/py/objstr.c index 54e6f37705..03a761863f 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -7,6 +7,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime0.h" #include "runtime.h" @@ -61,7 +62,7 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } else { // Message doesn't match CPython, but we don't have so much bytes as they // to spend them on verbose wording - nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "index must be int")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int")); } case RT_BINARY_OP_ADD: @@ -134,7 +135,7 @@ mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { return mp_obj_new_str(qstr_from_str_take(joined_str, required_len + 1)); bad_arg: - nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "?str.join expecting a list of str's")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's")); } void vstr_printf_wrapper(void *env, const char *fmt, ...) { @@ -158,7 +159,7 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) { vstr_add_char(vstr, '{'); } else if (*str == '}') { if (arg_i >= n_args) { - nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "tuple index out of range")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range")); } mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]); arg_i++; diff --git a/py/qstr.c b/py/qstr.c index 0dd8a04b70..0ed7aa9a24 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -2,55 +2,110 @@ #include #include "misc.h" +#include "mpqstr.h" -static int qstrs_alloc; -static int qstrs_len; -static const char **qstrs; +// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings) +// ultimately we will replace this with a static hash table of some kind +// also probably need to include the length in the string data, to allow null bytes in the string + +#if 0 // print debugging info +#include +#define DEBUG_printf(args...) printf(args) +#else // don't print debugging info +#define DEBUG_printf(args...) (void)0 +#endif + +typedef struct _qstr_pool_t { + struct _qstr_pool_t *prev; + uint total_prev_len; + uint alloc; + uint len; + const char *qstrs[]; +} qstr_pool_t; + +const static qstr_pool_t const_pool = { + NULL, // no previous pool + 0, // no previous pool + 10, // set so that the first dynamically allocated pool is twice this size; must be <= the len (just below) + MP_QSTR_number_of, // corresponds to number of strings in array just below + { + "nil", // must be first, since 0 qstr is nil +#define Q(id) #id, +#include "mpqstrraw.h" +#undef Q + }, +}; + +static qstr_pool_t *last_pool = (qstr_pool_t*)&const_pool; // we won't modify the const_pool since it has no allocated room left void qstr_init(void) { - qstrs_alloc = 400; - qstrs_len = 1; - qstrs = m_new(const char*, qstrs_alloc); - qstrs[0] = "nil"; + // nothing to do! } static qstr qstr_add(const char *str) { - if (qstrs_len >= qstrs_alloc) { - qstrs = m_renew(const char*, qstrs, qstrs_alloc, qstrs_alloc * 2); - qstrs_alloc *= 2; + DEBUG_printf("QSTR: add %s\n", str); + + // make sure we have room in the pool for a new qstr + if (last_pool->len >= last_pool->alloc) { + qstr_pool_t *pool = m_new_obj_var(qstr_pool_t, const char*, last_pool->alloc * 2); + pool->prev = last_pool; + pool->total_prev_len = last_pool->total_prev_len + last_pool->len; + pool->alloc = last_pool->alloc * 2; + pool->len = 0; + last_pool = pool; + DEBUG_printf("QSTR: allocate new pool of size %d\n", last_pool->alloc); } - qstrs[qstrs_len++] = str; - return qstrs_len - 1; + + // add the new qstr + last_pool->qstrs[last_pool->len++] = str; + + // return id for the newly-added qstr + return last_pool->total_prev_len + last_pool->len - 1; } qstr qstr_from_str_static(const char *str) { - for (int i = 0; i < qstrs_len; i++) { - if (strcmp(qstrs[i], str) == 0) { - return i; + for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) { + for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) { + if (strcmp(*qstr, str) == 0) { + return pool->total_prev_len + (qstr - pool->qstrs); + } } } return qstr_add(str); } qstr qstr_from_str_take(char *str, int alloc_len) { - for (int i = 0; i < qstrs_len; i++) { - if (strcmp(qstrs[i], str) == 0) { - m_del(char, str, alloc_len); - return i; + for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) { + for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) { + if (strcmp(*qstr, str) == 0) { + m_del(char, str, alloc_len); + return pool->total_prev_len + (qstr - pool->qstrs); + } } } return qstr_add(str); } qstr qstr_from_strn_copy(const char *str, int len) { - for (int i = 0; i < qstrs_len; i++) { - if (strncmp(qstrs[i], str, len) == 0 && qstrs[i][len] == '\0') { - return i; + for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) { + for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) { + if (strncmp(*qstr, str, len) == 0 && (*qstr)[len] == '\0') { + return pool->total_prev_len + (qstr - pool->qstrs); + } } } return qstr_add(strndup(str, len)); } +// convert qstr id to pointer to its string const char *qstr_str(qstr qstr) { - return qstrs[qstr]; + // search + for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) { + if (qstr >= pool->total_prev_len) { + return pool->qstrs[qstr - pool->total_prev_len]; + } + } + + // not found, return nil + return const_pool.qstrs[0]; } diff --git a/py/runtime.c b/py/runtime.c index 3144321f3a..a1f9ee3b7b 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -11,6 +11,7 @@ #include "nlr.h" #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "obj.h" #include "runtime0.h" #include "runtime.h" @@ -27,22 +28,6 @@ #define DEBUG_OP_printf(args...) (void)0 #endif -// TODO make these predefined so they don't take up RAM -qstr rt_q_append; -qstr rt_q_pop; -qstr rt_q_sort; -qstr rt_q_join; -qstr rt_q_format; -qstr rt_q___build_class__; -qstr rt_q___next__; -qstr rt_q_AttributeError; -qstr rt_q_IndexError; -qstr rt_q_KeyError; -qstr rt_q_NameError; -qstr rt_q_TypeError; -qstr rt_q_SyntaxError; -qstr rt_q_ValueError; - // locals and globals need to be pointers because they can be the same in outer module scope static mp_map_t *map_locals; static mp_map_t *map_globals; @@ -83,74 +68,58 @@ FILE *fp_write_code = NULL; #endif void rt_init(void) { - rt_q_append = qstr_from_str_static("append"); - rt_q_pop = qstr_from_str_static("pop"); - rt_q_sort = qstr_from_str_static("sort"); - rt_q_join = qstr_from_str_static("join"); - rt_q_format = qstr_from_str_static("format"); - rt_q___build_class__ = qstr_from_str_static("__build_class__"); - rt_q___next__ = qstr_from_str_static("__next__"); - rt_q_AttributeError = qstr_from_str_static("AttributeError"); - rt_q_IndexError = qstr_from_str_static("IndexError"); - rt_q_KeyError = qstr_from_str_static("KeyError"); - rt_q_NameError = qstr_from_str_static("NameError"); - rt_q_TypeError = qstr_from_str_static("TypeError"); - rt_q_SyntaxError = qstr_from_str_static("SyntaxError"); - rt_q_ValueError = qstr_from_str_static("ValueError"); - // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New()) map_locals = map_globals = mp_map_new(MP_MAP_QSTR, 1); - mp_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = mp_obj_new_str(qstr_from_str_static("__main__")); + mp_qstr_map_lookup(map_globals, MP_QSTR___name__, true)->value = mp_obj_new_str(MP_QSTR___main__); // init built-in hash table mp_map_init(&map_builtins, MP_MAP_QSTR, 3); // built-in exceptions (TODO, make these proper classes) - mp_qstr_map_lookup(&map_builtins, rt_q_AttributeError, true)->value = mp_obj_new_exception(rt_q_AttributeError); - mp_qstr_map_lookup(&map_builtins, rt_q_IndexError, true)->value = mp_obj_new_exception(rt_q_IndexError); - mp_qstr_map_lookup(&map_builtins, rt_q_KeyError, true)->value = mp_obj_new_exception(rt_q_KeyError); - mp_qstr_map_lookup(&map_builtins, rt_q_NameError, true)->value = mp_obj_new_exception(rt_q_NameError); - mp_qstr_map_lookup(&map_builtins, rt_q_TypeError, true)->value = mp_obj_new_exception(rt_q_TypeError); - mp_qstr_map_lookup(&map_builtins, rt_q_SyntaxError, true)->value = mp_obj_new_exception(rt_q_SyntaxError); - mp_qstr_map_lookup(&map_builtins, rt_q_ValueError, true)->value = mp_obj_new_exception(rt_q_ValueError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_AttributeError, true)->value = mp_obj_new_exception(MP_QSTR_AttributeError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_IndexError, true)->value = mp_obj_new_exception(MP_QSTR_IndexError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_KeyError, true)->value = mp_obj_new_exception(MP_QSTR_KeyError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_NameError, true)->value = mp_obj_new_exception(MP_QSTR_NameError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_TypeError, true)->value = mp_obj_new_exception(MP_QSTR_TypeError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_SyntaxError, true)->value = mp_obj_new_exception(MP_QSTR_SyntaxError); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_ValueError, true)->value = mp_obj_new_exception(MP_QSTR_ValueError); // built-in core functions - mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(mp_builtin___repl_print__); + mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__); + mp_qstr_map_lookup(&map_builtins, MP_QSTR___repl_print__, true)->value = rt_make_function_1(mp_builtin___repl_print__); // built-in user functions - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(mp_builtin_abs); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("all"), true)->value = rt_make_function_1(mp_builtin_all); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("any"), true)->value = rt_make_function_1(mp_builtin_any); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("bool"), true)->value = rt_make_function_var(0, mp_builtin_bool); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("callable"), true)->value = rt_make_function_1(mp_builtin_callable); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("chr"), true)->value = rt_make_function_1(mp_builtin_chr); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_abs, true)->value = rt_make_function_1(mp_builtin_abs); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_all, true)->value = rt_make_function_1(mp_builtin_all); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_any, true)->value = rt_make_function_1(mp_builtin_any); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_bool, true)->value = rt_make_function_var(0, mp_builtin_bool); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_callable, true)->value = rt_make_function_1(mp_builtin_callable); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_chr, true)->value = rt_make_function_1(mp_builtin_chr); #if MICROPY_ENABLE_FLOAT - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("complex"), true)->value = (mp_obj_t)&mp_builtin_complex_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_complex, true)->value = (mp_obj_t)&mp_builtin_complex_obj; #endif - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("dict"), true)->value = rt_make_function_0(mp_builtin_dict); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("divmod"), true)->value = rt_make_function_2(mp_builtin_divmod); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_dict, true)->value = rt_make_function_0(mp_builtin_dict); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_divmod, true)->value = rt_make_function_2(mp_builtin_divmod); #if MICROPY_ENABLE_FLOAT - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("float"), true)->value = (mp_obj_t)&mp_builtin_float_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_float, true)->value = (mp_obj_t)&mp_builtin_float_obj; #endif - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("hash"), true)->value = (mp_obj_t)&mp_builtin_hash_obj; - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("int"), true)->value = (mp_obj_t)&mp_builtin_int_obj; - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("iter"), true)->value = (mp_obj_t)&mp_builtin_iter_obj; - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(mp_builtin_len); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("list"), true)->value = rt_make_function_var(0, mp_builtin_list); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("max"), true)->value = rt_make_function_var(1, mp_builtin_max); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("min"), true)->value = rt_make_function_var(1, mp_builtin_min); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("next"), true)->value = (mp_obj_t)&mp_builtin_next_obj; - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("ord"), true)->value = rt_make_function_1(mp_builtin_ord); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("pow"), true)->value = rt_make_function_var(2, mp_builtin_pow); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, mp_builtin_print); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_var(1, mp_builtin_range); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("set"), true)->value = (mp_obj_t)&mp_builtin_set_obj; - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("sum"), true)->value = rt_make_function_var(1, mp_builtin_sum); - mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("type"), true)->value = (mp_obj_t)&mp_builtin_type_obj; - - - next_unique_code_id = 2; // 1 is reserved for the __main__ module scope + mp_qstr_map_lookup(&map_builtins, MP_QSTR_hash, true)->value = (mp_obj_t)&mp_builtin_hash_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_int, true)->value = (mp_obj_t)&mp_builtin_int_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_iter, true)->value = (mp_obj_t)&mp_builtin_iter_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_len, true)->value = rt_make_function_1(mp_builtin_len); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_list, true)->value = rt_make_function_var(0, mp_builtin_list); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_max, true)->value = rt_make_function_var(1, mp_builtin_max); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_min, true)->value = rt_make_function_var(1, mp_builtin_min); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_next, true)->value = (mp_obj_t)&mp_builtin_next_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_ord, true)->value = rt_make_function_1(mp_builtin_ord); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_pow, true)->value = rt_make_function_var(2, mp_builtin_pow); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_print, true)->value = rt_make_function_var(0, mp_builtin_print); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_range, true)->value = rt_make_function_var(1, mp_builtin_range); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_set, true)->value = (mp_obj_t)&mp_builtin_set_obj; + mp_qstr_map_lookup(&map_builtins, MP_QSTR_sum, true)->value = rt_make_function_var(1, mp_builtin_sum); + mp_qstr_map_lookup(&map_builtins, MP_QSTR_type, true)->value = (mp_obj_t)&mp_builtin_type_obj; + + next_unique_code_id = 1; // 0 indicates "no code" unique_codes = NULL; #ifdef WRITE_CODE @@ -166,12 +135,8 @@ void rt_deinit(void) { #endif } -int rt_get_unique_code_id(bool is_main_module) { - if (is_main_module) { - return 1; - } else { - return next_unique_code_id++; - } +int rt_get_unique_code_id(void) { + return next_unique_code_id++; } static void alloc_unique_codes(void) { @@ -186,7 +151,7 @@ static void alloc_unique_codes(void) { void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator) { alloc_unique_codes(); - assert(unique_code_id < next_unique_code_id); + assert(1 <= unique_code_id && unique_code_id < next_unique_code_id); unique_codes[unique_code_id].kind = MP_CODE_BYTE; unique_codes[unique_code_id].n_args = n_args; unique_codes[unique_code_id].n_locals = n_locals; @@ -355,7 +320,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) { } } if (*s != 0) { - nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "invalid syntax for number")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "invalid syntax for number")); } if (exp_neg) { exp_val = -exp_val; @@ -373,7 +338,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) { return mp_obj_new_float(dec_val); } #else - nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "decimal numbers not supported")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "decimal numbers not supported")); #endif } @@ -391,7 +356,7 @@ mp_obj_t rt_load_name(qstr qstr) { if (elem == NULL) { elem = mp_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); } } } @@ -405,7 +370,7 @@ mp_obj_t rt_load_global(qstr qstr) { if (elem == NULL) { elem = mp_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); } } return elem->value; @@ -413,9 +378,9 @@ mp_obj_t rt_load_global(qstr qstr) { mp_obj_t rt_load_build_class(void) { DEBUG_OP_printf("load_build_class\n"); - mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, false); + mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, false); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg(rt_q_NameError, "name '__build_class__' is not defined")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_NameError, "name '__build_class__' is not defined")); } return elem->value; } @@ -465,7 +430,7 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) { } } // TODO specify in error message what the operator is - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bad operand type for unary operator: '%s'", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bad operand type for unary operator: '%s'", o->type->name)); } } @@ -544,7 +509,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } // TODO specify in error message what the operator is - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs))); } mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) { @@ -693,13 +658,13 @@ mp_obj_t rt_call_function_n(mp_obj_t fun_in, int n_args, const mp_obj_t *args) { DEBUG_OP_printf("calling function %p(n_args=%d, args=%p)\n", fun_in, n_args, args); if (MP_OBJ_IS_SMALL_INT(fun_in)) { - nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not callable")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not callable")); } else { mp_obj_base_t *fun = fun_in; if (fun->type->call_n != NULL) { return fun->type->call_n(fun_in, n_args, args); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not callable", fun->type->name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name)); } } } @@ -756,14 +721,14 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) { mp_obj_list_get(seq_in, &seq_len, &seq_items); } if (seq_len < num) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len)); } else if (seq_len > num) { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num)); } memcpy(items, seq_items, num * sizeof(mp_obj_t)); } else { // TODO call rt_getiter and extract via rt_iternext - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in))); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in))); } } @@ -807,12 +772,12 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) { } no_attr: - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { DEBUG_OP_printf("load method %s\n", qstr_str(attr)); - if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == rt_q___next__) { + if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == MP_QSTR___next__) { dest[1] = (mp_obj_t)&mp_builtin_next_obj; dest[0] = base; return; @@ -850,7 +815,7 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { mp_map_t *globals = mp_obj_module_get_globals(base); mp_qstr_map_lookup(globals, attr, true)->value = value; } else { - nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } } @@ -869,26 +834,26 @@ void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_obj_t rt_getiter(mp_obj_t o_in) { if (MP_OBJ_IS_SMALL_INT(o_in)) { - nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not iterable")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not iterable")); } else { mp_obj_base_t *o = o_in; if (o->type->getiter != NULL) { return o->type->getiter(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", o->type->name)); } } } mp_obj_t rt_iternext(mp_obj_t o_in) { if (MP_OBJ_IS_SMALL_INT(o_in)) { - nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "? 'int' object is not iterable")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "? 'int' object is not iterable")); } else { mp_obj_base_t *o = o_in; if (o->type->iternext != NULL) { return o->type->iternext(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "? '%s' object is not iterable", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "? '%s' object is not iterable", o->type->name)); } } } diff --git a/py/runtime.h b/py/runtime.h index cf9180275e..96f1671f67 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -1,18 +1,3 @@ -extern qstr rt_q_append; -extern qstr rt_q_pop; -extern qstr rt_q_sort; -extern qstr rt_q_join; -extern qstr rt_q_format; -extern qstr rt_q___build_class__; -extern qstr rt_q___next__; -extern qstr rt_q_AttributeError; -extern qstr rt_q_IndexError; -extern qstr rt_q_KeyError; -extern qstr rt_q_NameError; -extern qstr rt_q_TypeError; -extern qstr rt_q_SyntaxError; -extern qstr rt_q_ValueError; - int rt_is_true(mp_obj_t arg); mp_obj_t rt_load_const_dec(qstr qstr); diff --git a/py/runtime0.h b/py/runtime0.h index 8ec2c058f0..97dbe5ddbc 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -81,7 +81,7 @@ extern void *const rt_fun_table[RT_F_NUMBER_OF]; void rt_init(void); void rt_deinit(void); -int rt_get_unique_code_id(bool is_main_module); +int rt_get_unique_code_id(void); void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator); void rt_assign_native_code(int unique_code_id, void *f, uint len, int n_args); void rt_assign_inline_asm_code(int unique_code_id, void *f, uint len, int n_args); diff --git a/stm/main.c b/stm/main.c index e8db2be2ca..b7ae8aacca 100644 --- a/stm/main.c +++ b/stm/main.c @@ -15,6 +15,7 @@ #include "misc.h" #include "ff.h" #include "mpconfig.h" +#include "mpqstr.h" #include "nlr.h" #include "misc.h" #include "lexer.h" @@ -621,7 +622,7 @@ mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) { } pin_error: - nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "pin %s does not exist", pin_name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not exist", pin_name)); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio); diff --git a/unix/main.c b/unix/main.c index 1aa3331202..e73f69ee24 100644 --- a/unix/main.c +++ b/unix/main.c @@ -217,6 +217,13 @@ int main(int argc, char **argv) { rt_store_name(qstr_from_str_static("test"), test_obj_new(42)); + /* + printf("bytes:\n"); + printf(" total %d\n", m_get_total_bytes_allocated()); + printf(" cur %d\n", m_get_current_bytes_allocated()); + printf(" peak %d\n", m_get_peak_bytes_allocated()); + */ + if (argc == 1) { do_repl(); } else if (argc == 2) {