summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtin.c25
-rw-r--r--py/builtinimport.c5
-rw-r--r--py/compile.c76
-rw-r--r--py/mpqstr.h13
-rw-r--r--py/mpqstrraw.h63
-rw-r--r--py/obj.c13
-rw-r--r--py/objclass.c7
-rw-r--r--py/objdict.c3
-rw-r--r--py/objfun.c11
-rw-r--r--py/objgenerator.c3
-rw-r--r--py/objinstance.c3
-rw-r--r--py/objlist.c3
-rw-r--r--py/objstr.c7
-rw-r--r--py/qstr.c101
-rw-r--r--py/runtime.c157
-rw-r--r--py/runtime.h15
-rw-r--r--py/runtime0.h2
-rw-r--r--stm/main.c3
-rw-r--r--unix/main.c7
19 files changed, 295 insertions, 222 deletions
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, "<value>"));
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
} 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, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args)));
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (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, "<fun name> 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, "<fun name> 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 <string.h>
#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 <stdio.h>
+#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) {