summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/asmthumb.c5
-rw-r--r--py/asmx64.c6
-rw-r--r--py/bc0.h16
-rw-r--r--py/builtin.c147
-rw-r--r--py/builtinimport.c5
-rw-r--r--py/compile.c83
-rw-r--r--py/emitbc.c1
-rw-r--r--py/emitcpy.c1
-rw-r--r--py/emitnative.c4
-rw-r--r--py/emitpass1.c5
-rw-r--r--py/grammar.h8
-rw-r--r--py/lexer.c2
-rw-r--r--py/lexer.h2
-rw-r--r--py/mpqstr.h13
-rw-r--r--py/mpqstrraw.h65
-rw-r--r--py/nlrx64.S23
-rw-r--r--py/obj.c25
-rw-r--r--py/obj.h8
-rw-r--r--py/objbool.c14
-rw-r--r--py/objboundmeth.c1
-rw-r--r--py/objcell.c1
-rw-r--r--py/objclass.c8
-rw-r--r--py/objclosure.c1
-rw-r--r--py/objcomplex.c45
-rw-r--r--py/objdict.c14
-rw-r--r--py/objexcept.c1
-rw-r--r--py/objfloat.c26
-rw-r--r--py/objfun.c14
-rw-r--r--py/objgenerator.c5
-rw-r--r--py/objinstance.c4
-rw-r--r--py/objint.c48
-rw-r--r--py/objlist.c30
-rw-r--r--py/objmodule.c1
-rw-r--r--py/objnone.c1
-rw-r--r--py/objrange.c2
-rw-r--r--py/objset.c28
-rw-r--r--py/objslice.c31
-rw-r--r--py/objstr.c72
-rw-r--r--py/objtuple.c76
-rw-r--r--py/objtype.c21
-rw-r--r--py/qstr.c101
-rw-r--r--py/runtime.c167
-rw-r--r--py/runtime.h15
-rw-r--r--py/runtime0.h2
-rw-r--r--py/showbc.c4
-rw-r--r--py/vm.c4
46 files changed, 761 insertions, 395 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c
index ee8041ac9f..ba95d80c68 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -7,6 +7,9 @@
#include "mpconfig.h"
#include "asmthumb.h"
+// wrapper around everything in this file
+#if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
+
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
#define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0)
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
@@ -447,3 +450,5 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
asm_thumb_write_op16(as, OP_SVC(fun_id));
}
}
+
+#endif // MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
diff --git a/py/asmx64.c b/py/asmx64.c
index c425034ba0..ed9ca80f5c 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -6,6 +6,10 @@
#include "misc.h"
#include "asmx64.h"
+#include "mpconfig.h"
+
+// wrapper around everything in this file
+#if MICROPY_EMIT_X64
#if defined(__OpenBSD__) || defined(__MACH__)
#define MAP_ANONYMOUS MAP_ANON
@@ -620,3 +624,5 @@ void asm_x64_call_ind(asm_x64_t* as, void *ptr, int temp_r64) {
asm_x64_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));
*/
}
+
+#endif // MICROPY_EMIT_X64
diff --git a/py/bc0.h b/py/bc0.h
index 773e23d2ea..0a4a49ce66 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -1,12 +1,16 @@
+// Micro Python byte-codes.
+// The comment at the end of the line (if it exists) tells the arguments to the byte-code.
+
#define MP_BC_LOAD_CONST_FALSE (0x10)
#define MP_BC_LOAD_CONST_NONE (0x11)
#define MP_BC_LOAD_CONST_TRUE (0x12)
-#define MP_BC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess
-#define MP_BC_LOAD_CONST_INT (0x14) // qstr
-#define MP_BC_LOAD_CONST_DEC (0x15) // qstr
-#define MP_BC_LOAD_CONST_ID (0x16) // qstr
-#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr
-#define MP_BC_LOAD_CONST_STRING (0x18) // qstr
+#define MP_BC_LOAD_CONST_ELLIPSIS (0x13)
+#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // 24-bit, in excess
+#define MP_BC_LOAD_CONST_INT (0x15) // qstr
+#define MP_BC_LOAD_CONST_DEC (0x16) // qstr
+#define MP_BC_LOAD_CONST_ID (0x17) // qstr
+#define MP_BC_LOAD_CONST_BYTES (0x18) // qstr
+#define MP_BC_LOAD_CONST_STRING (0x19) // qstr
#define MP_BC_LOAD_FAST_0 (0x20)
#define MP_BC_LOAD_FAST_1 (0x21)
diff --git a/py/builtin.c b/py/builtin.c
index d29a2bf8c3..6babc76692 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"
@@ -87,14 +88,6 @@ mp_obj_t mp_builtin_any(mp_obj_t o_in) {
return mp_const_false;
}
-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));
- }
-}
-
mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
if (mp_obj_is_callable(o_in)) {
return mp_const_true;
@@ -103,42 +96,6 @@ mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
}
}
-#if MICROPY_ENABLE_FLOAT
-mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args) {
- assert(0 <= n_args && n_args <= 2);
-
- if (n_args == 0) {
- return mp_obj_new_complex(0, 0);
- } else if (n_args == 1) {
- // TODO allow string as first arg and parse it
- if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
- return args[0];
- } else {
- return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
- }
- } else {
- mp_float_t real, imag;
- if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
- mp_obj_get_complex(args[0], &real, &imag);
- } else {
- real = mp_obj_get_float(args[0]);
- imag = 0;
- }
- if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
- mp_float_t real2, imag2;
- mp_obj_get_complex(args[1], &real2, &imag2);
- real -= imag2;
- imag += real2;
- } else {
- imag += mp_obj_get_float(args[1]);
- }
- return mp_obj_new_complex(real, imag);
- }
-}
-
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_complex_obj, 0, 2, mp_builtin_complex);
-#endif
-
mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
int ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) {
@@ -147,15 +104,10 @@ 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)"));
}
}
-mp_obj_t mp_builtin_dict(void) {
- // TODO create from an iterable!
- return rt_build_map(0);
-}
-
mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
@@ -165,29 +117,10 @@ 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)));
- }
-}
-
-#if MICROPY_ENABLE_FLOAT
-static mp_obj_t mp_builtin_float(int n_args, const mp_obj_t *args) {
- assert(0 <= n_args && n_args <= 1);
-
- if (n_args == 0) {
- return mp_obj_new_float(0);
- } else {
- // TODO allow string as arg and parse it
- if (MP_OBJ_IS_TYPE(args[0], &float_type)) {
- return args[0];
- } else {
- return mp_obj_new_float(mp_obj_get_float(args[0]));
- }
+ 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)));
}
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_float_obj, 0, 1, mp_builtin_float);
-#endif
-
static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
// TODO hash will generally overflow small integer; can we safely truncate it?
return mp_obj_new_int(mp_obj_hash(o_in));
@@ -195,23 +128,6 @@ static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
-static mp_obj_t mp_builtin_int(int n_args, const mp_obj_t *args) {
- assert(0 <= n_args && n_args <= 2);
-
- if (n_args == 0) {
- return MP_OBJ_NEW_SMALL_INT(0);
- } else if (n_args == 1) {
- // TODO if arg is a string then parse it
- return mp_obj_new_int(mp_obj_get_int(args[0]));
- } else { // n_args == 2
- // TODO, parse with given base
- assert(0);
- return MP_OBJ_NEW_SMALL_INT(0);
- }
-}
-
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_int_obj, 0, 2, mp_builtin_int);
-
static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
return rt_getiter(o_in);
}
@@ -235,29 +151,11 @@ 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);
}
-mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) {
- switch (n_args) {
- case 0: return rt_build_list(0, NULL);
- case 1:
- {
- // make list from iterable
- mp_obj_t iterable = rt_getiter(args[0]);
- mp_obj_t list = rt_build_list(0, NULL);
- mp_obj_t item;
- while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
- rt_list_append(list, item);
- }
- 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));
- }
-}
-
mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
if (n_args == 1) {
// given an iterable
@@ -270,7 +168,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 +195,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 +213,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 +226,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 +234,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,36 +260,16 @@ 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));
}
}
-static mp_obj_t mp_builtin_set(int n_args, const mp_obj_t *args) {
- assert(0 <= n_args && n_args <= 1);
-
- if (n_args == 0) {
- // return a new, empty set
- return mp_obj_new_set(0, NULL);
- } else {
- // 1 argument, an iterable from which we make a new set
- mp_obj_t set = mp_obj_new_set(0, NULL);
- mp_obj_t iterable = rt_getiter(args[0]);
- mp_obj_t item;
- while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
- mp_obj_set_store(set, item);
- }
- return set;
- }
-}
-
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_set_obj, 0, 1, mp_builtin_set);
-
mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
mp_obj_t value;
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;
@@ -404,8 +282,7 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
static mp_obj_t mp_builtin_type(mp_obj_t o_in) {
// TODO implement the 3 argument version of type()
if (MP_OBJ_IS_SMALL_INT(o_in)) {
- // TODO implement int-type
- return mp_const_none;
+ return (mp_obj_t)&int_type;
} else {
mp_obj_base_t *o = o_in;
return (mp_obj_t)o->type;
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 68ac20804d..0e19890315 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_AssertionError);
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;
@@ -3083,11 +3056,13 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
// compile pass 2 and 3
#if !MICROPY_EMIT_CPYTHON
emit_t *emit_bc = NULL;
+#if MICROPY_EMIT_NATIVE
emit_t *emit_native = NULL;
#endif
#if MICROPY_EMIT_INLINE_THUMB
emit_inline_asm_t *emit_inline_thumb = NULL;
#endif
+#endif // !MICROPY_EMIT_CPYTHON
for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
if (false) {
// dummy
@@ -3115,6 +3090,8 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
comp->emit_method_table = &emit_cpython_method_table;
#else
switch (s->emit_options) {
+
+#if MICROPY_EMIT_NATIVE
case EMIT_OPT_NATIVE_PYTHON:
case EMIT_OPT_VIPER:
#if MICROPY_EMIT_X64
@@ -3131,6 +3108,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
comp->emit = emit_native;
comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
break;
+#endif // MICROPY_EMIT_NATIVE
default:
if (emit_bc == NULL) {
@@ -3140,7 +3118,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
comp->emit_method_table = &emit_bc_method_table;
break;
}
-#endif
+#endif // !MICROPY_EMIT_CPYTHON
// compile pass 2 and pass 3
compile_scope(comp, s, PASS_2);
@@ -3157,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/emitbc.c b/py/emitbc.c
index dc1988582c..c0ec2469a6 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -249,6 +249,7 @@ static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
case MP_TOKEN_KW_FALSE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_FALSE); break;
case MP_TOKEN_KW_NONE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_NONE); break;
case MP_TOKEN_KW_TRUE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_TRUE); break;
+ case MP_TOKEN_ELLIPSIS: emit_write_byte_1(emit, MP_BC_LOAD_CONST_ELLIPSIS); break;
default: assert(0);
}
}
diff --git a/py/emitcpy.c b/py/emitcpy.c
index 652617cc88..7b2d50fb7e 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -13,6 +13,7 @@
#include "runtime0.h"
#include "emit.h"
+// wrapper around everything in this file
#if MICROPY_EMIT_CPYTHON
struct _emit_t {
diff --git a/py/emitnative.c b/py/emitnative.c
index a29922d96c..cc00c57319 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -34,7 +34,7 @@
#include "runtime.h"
// wrapper around everything in this file
-#if N_X64 || N_THUMB
+#if (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)
#if N_X64
@@ -1319,4 +1319,4 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_yield_from,
};
-#endif // N_X64 || N_THUMB
+#endif // (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)
diff --git a/py/emitpass1.c b/py/emitpass1.c
index 1c11241e0d..f78ec7e27e 100644
--- a/py/emitpass1.c
+++ b/py/emitpass1.c
@@ -7,6 +7,7 @@
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
@@ -44,9 +45,9 @@ static void emit_pass1_load_id(emit_t *emit, qstr qstr) {
bool added;
id_info_t *id = scope_find_or_add_id(emit->scope, qstr, &added);
if (added) {
- if (strcmp(qstr_str(qstr), "AssertionError") == 0) {
- id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
+ if (qstr == MP_QSTR_AssertionError) {
// TODO how much of a hack is this?
+ id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
} else if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) {
// special case, super is a global, and also counts as use of __class__
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
diff --git a/py/grammar.h b/py/grammar.h
index b1faab79e1..4d53bd3fc4 100644
--- a/py/grammar.h
+++ b/py/grammar.h
@@ -113,11 +113,11 @@ DEF_RULE(import_stmt, nc, or(2), rule(import_name), rule(import_from))
DEF_RULE(import_name, c(import_name), and(2), tok(KW_IMPORT), rule(dotted_as_names))
DEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2), tok(KW_IMPORT), rule(import_from_3))
DEF_RULE(import_from_2, nc, or(2), rule(dotted_name), rule(import_from_2b))
-DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipses), opt_rule(dotted_name))
+DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name))
DEF_RULE(import_from_3, nc, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names))
DEF_RULE(import_as_names_paren, nc, and(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))
-DEF_RULE(one_or_more_period_or_ellipses, nc, one_or_more, rule(period_or_ellipses))
-DEF_RULE(period_or_ellipses, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSES))
+DEF_RULE(one_or_more_period_or_ellipsis, nc, one_or_more, rule(period_or_ellipsis))
+DEF_RULE(period_or_ellipsis, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSIS))
DEF_RULE(import_as_name, nc, and(2), tok(NAME), opt_rule(as_name))
DEF_RULE(dotted_as_name, nc, and(2), rule(dotted_name), opt_rule(as_name))
DEF_RULE(as_name, nc, and(2), tok(KW_AS), tok(NAME))
@@ -220,7 +220,7 @@ DEF_RULE(power_dbl_star, c(power_dbl_star), and(2), tok(OP_DBL_STAR), rule(facto
// testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
// trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
-DEF_RULE(atom, nc, or(10), tok(NAME), tok(NUMBER), rule(atom_string), tok(ELLIPSES), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
+DEF_RULE(atom, nc, or(10), tok(NAME), tok(NUMBER), rule(atom_string), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
DEF_RULE(atom_string, c(atom_string), one_or_more, rule(string_or_bytes))
DEF_RULE(string_or_bytes, nc, or(2), tok(STRING), tok(BYTES))
DEF_RULE(atom_paren, c(atom_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(atom_2b), tok(DEL_PAREN_CLOSE))
diff --git a/py/lexer.c b/py/lexer.c
index 4df91b0365..d4205236c3 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -239,7 +239,7 @@ static const uint8_t tok_enc_kind[] = {
MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
- MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSES,
+ MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSIS,
};
// must have the same order as enum in lexer.h
diff --git a/py/lexer.h b/py/lexer.h
index 27244fde96..3cb48ce9e1 100644
--- a/py/lexer.h
+++ b/py/lexer.h
@@ -20,7 +20,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_STRING,
MP_TOKEN_BYTES,
- MP_TOKEN_ELLIPSES,
+ MP_TOKEN_ELLIPSIS,
MP_TOKEN_KW_FALSE, // 12
MP_TOKEN_KW_NONE,
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..fe74c3e927
--- /dev/null
+++ b/py/mpqstrraw.h
@@ -0,0 +1,65 @@
+// 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(micropython)
+Q(byte_code)
+Q(native)
+Q(viper)
+Q(asm_thumb)
+
+Q(Ellipsis)
+Q(StopIteration)
+
+Q(AssertionError)
+Q(AttributeError)
+Q(IndexError)
+Q(KeyError)
+Q(NameError)
+Q(SyntaxError)
+Q(TypeError)
+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(tuple)
+Q(type)
+
+Q(append)
+Q(pop)
+Q(sort)
+Q(join)
+Q(format)
diff --git a/py/nlrx64.S b/py/nlrx64.S
index 6d0e2118f7..441817b4f3 100644
--- a/py/nlrx64.S
+++ b/py/nlrx64.S
@@ -5,9 +5,14 @@
.text
/* uint nlr_push(rdi=nlr_buf_t *nlr) */
+#ifndef __apple_build_version__
.globl nlr_push
.type nlr_push, @function
nlr_push:
+#else
+ .globl _nlr_push
+_nlr_push:
+#endif
movq (%rsp), %rax # load return %rip
movq %rax, 16(%rdi) # store %rip into nlr_buf
movq %rbp, 24(%rdi) # store %rbp into nlr_buf
@@ -22,22 +27,36 @@ nlr_push:
movq %rdi, nlr_top(%rip) # stor new nlr_buf (to make linked list)
xorq %rax, %rax # return 0, normal return
ret # return
+#ifndef __apple_build_version__
.size nlr_push, .-nlr_push
+#endif
/* void nlr_pop() */
+#ifndef __apple_build_version__
.globl nlr_pop
.type nlr_pop, @function
nlr_pop:
+#else
+ .globl _nlr_pop
+_nlr_pop:
+#endif
movq nlr_top(%rip), %rax # get nlr_top into %rax
movq (%rax), %rax # load prev nlr_buf
movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list)
ret # return
+#ifndef __apple_build_version__
.size nlr_pop, .-nlr_pop
+#endif
/* void nlr_jump(rdi=uint val) */
+#ifndef __apple_build_version__
.globl nlr_jump
.type nlr_jump, @function
nlr_jump:
+#else
+ .globl _nlr_jump
+ _nlr_jump:
+#endif
movq %rdi, %rax # put return value in %rax
movq nlr_top(%rip), %rdi # get nlr_top into %rdi
movq %rax, 8(%rdi) # store return value
@@ -55,8 +74,12 @@ nlr_jump:
xorq %rax, %rax # clear return register
inc %al # increase to make 1, non-local return
ret # return
+#ifndef __apple_build_version__
.size nlr_jump, .-nlr_jump
+#endif
+#ifndef __apple_build_version__
.local nlr_top
+#endif
.comm nlr_top,8,8
#endif
diff --git a/py/obj.c b/py/obj.c
index d88d0ac3d7..77580e1fee 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -7,15 +7,12 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "map.h"
-mp_obj_t mp_obj_new_int(machine_int_t value) {
- return MP_OBJ_NEW_SMALL_INT(value);
-}
-
const char *mp_obj_get_type_str(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
return "int";
@@ -127,9 +124,13 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) {
return 1;
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
return MP_OBJ_SMALL_INT_VALUE(arg);
+#if MICROPY_ENABLE_FLOAT
+ } else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
+ // TODO work out if this should be floor, ceil or trunc
+ return (machine_int_t)mp_obj_float_get(arg);
+#endif
} else {
- assert(0);
- return 0;
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg)));
}
}
@@ -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/obj.h b/py/obj.h
index b39b84239f..88a611ba7b 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -60,6 +60,7 @@ typedef mp_obj_t (*mp_fun_t)(void);
typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *);
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o);
+typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, int n_args, const mp_obj_t *args); // args are in reverse order in the array
typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
@@ -73,6 +74,7 @@ struct _mp_obj_type_t {
mp_obj_base_t base;
const char *name;
mp_print_fun_t print;
+ mp_make_new_fun_t make_new; // to make an instance of the type
mp_call_n_fun_t call_n;
mp_unary_op_fun_t unary_op; // can return NULL if op not supported
@@ -112,6 +114,8 @@ extern const mp_obj_type_t mp_const_type;
extern const mp_obj_t mp_const_none;
extern const mp_obj_t mp_const_false;
extern const mp_obj_t mp_const_true;
+extern const mp_obj_t mp_const_empty_tuple;
+extern const mp_obj_t mp_const_ellipsis;
extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!)
// Need to declare this here so we are not dependent on map.h
@@ -181,6 +185,9 @@ extern const mp_obj_type_t bool_type;
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);
+// int
+extern const mp_obj_type_t int_type;
+
// exception
extern const mp_obj_type_t exception_type;
qstr mp_obj_exception_get_type(mp_obj_t self_in);
@@ -215,6 +222,7 @@ uint mp_obj_dict_len(mp_obj_t self_in);
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);
// set
+extern const mp_obj_type_t set_type;
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
// slice
diff --git a/py/objbool.c b/py/objbool.c
index 9b53ffae94..1d94ee03be 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -4,14 +4,16 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
+#include "runtime.h"
typedef struct _mp_obj_bool_t {
mp_obj_base_t base;
bool value;
} mp_obj_bool_t;
-void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
+static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_bool_t *self = self_in;
if (self->value) {
print(env, "True");
@@ -20,10 +22,20 @@ void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_ob
}
}
+// args are reverse in the array
+static mp_obj_t bool_make_new(mp_obj_t type_in, 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(MP_QSTR_TypeError, "bool takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
+ }
+}
+
const mp_obj_type_t bool_type = {
{ &mp_const_type },
"bool",
bool_print, // print
+ bool_make_new, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objboundmeth.c b/py/objboundmeth.c
index 8bd238c65e..264c2effd4 100644
--- a/py/objboundmeth.c
+++ b/py/objboundmeth.c
@@ -37,6 +37,7 @@ const mp_obj_type_t bound_meth_type = {
{ &mp_const_type },
"bound_method",
NULL, // print
+ NULL, // make_new
bound_meth_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objcell.c b/py/objcell.c
index cba1980579..daaa340a7f 100644
--- a/py/objcell.c
+++ b/py/objcell.c
@@ -27,6 +27,7 @@ const mp_obj_type_t cell_type = {
{ &mp_const_type },
"cell",
NULL, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objclass.c b/py/objclass.c
index 203923a722..197dfa7268 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));
}
}
@@ -63,6 +64,7 @@ const mp_obj_type_t class_type = {
{ &mp_const_type },
"class",
NULL, // print
+ NULL, // make_new
class_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objclosure.c b/py/objclosure.c
index e3354d42d9..550bb5067f 100644
--- a/py/objclosure.c
+++ b/py/objclosure.c
@@ -36,6 +36,7 @@ const mp_obj_type_t closure_type = {
{ &mp_const_type },
"closure",
NULL, // print
+ NULL, // make_new
closure_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objcomplex.c b/py/objcomplex.c
index ab9c146774..5408d71cf2 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "map.h"
@@ -29,7 +30,46 @@ void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp
}
}
-mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
+// args are reverse in the array
+static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ switch (n_args) {
+ case 0:
+ return mp_obj_new_complex(0, 0);
+
+ case 1:
+ // TODO allow string as first arg and parse it
+ if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
+ return args[0];
+ } else {
+ return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
+ }
+
+ case 2:
+ {
+ mp_float_t real, imag;
+ if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
+ mp_obj_get_complex(args[1], &real, &imag);
+ } else {
+ real = mp_obj_get_float(args[1]);
+ imag = 0;
+ }
+ if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
+ mp_float_t real2, imag2;
+ mp_obj_get_complex(args[0], &real2, &imag2);
+ real -= imag2;
+ imag += real2;
+ } else {
+ imag += mp_obj_get_float(args[0]);
+ }
+ return mp_obj_new_complex(real, imag);
+ }
+
+ default:
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "complex takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args));
+ }
+}
+
+static mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
mp_obj_complex_t *o = o_in;
switch (op) {
case RT_UNARY_OP_NOT: if (o->real != 0 || o->imag != 0) { return mp_const_true;} else { return mp_const_false; }
@@ -39,7 +79,7 @@ mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
}
}
-mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+static mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
mp_obj_complex_get(lhs_in, &lhs_real, &lhs_imag);
mp_obj_complex_get(rhs_in, &rhs_real, &rhs_imag);
@@ -79,6 +119,7 @@ const mp_obj_type_t complex_type = {
{ &mp_const_type },
"complex",
complex_print, // print
+ complex_make_new, // make_new
NULL, // call_n
complex_unary_op, // unary_op
complex_binary_op, // binary_op
diff --git a/py/objdict.c b/py/objdict.c
index 50ce279040..3737f5eab0 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"
@@ -16,7 +17,7 @@ typedef struct _mp_obj_dict_t {
mp_map_t map;
} mp_obj_dict_t;
-void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
+static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_dict_t *self = self_in;
bool first = true;
print(env, "{");
@@ -34,7 +35,13 @@ void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_ob
print(env, "}");
}
-mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+// args are reverse in the array
+static mp_obj_t dict_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ // TODO create from an iterable!
+ return rt_build_map(0);
+}
+
+static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = lhs_in;
switch (op) {
case RT_BINARY_OP_SUBSCR:
@@ -42,7 +49,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;
}
@@ -57,6 +64,7 @@ const mp_obj_type_t dict_type = {
{ &mp_const_type },
"dict",
dict_print, // print
+ dict_make_new, // make_new
NULL, // call_n
NULL, // unary_op
dict_binary_op, // binary_op
diff --git a/py/objexcept.c b/py/objexcept.c
index e735852c37..ec03b9bf1a 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -39,6 +39,7 @@ const mp_obj_type_t exception_type = {
{ &mp_const_type },
"exception",
exception_print, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objfloat.c b/py/objfloat.c
index f151fe25a0..8fc925e0b6 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
@@ -18,12 +19,30 @@ typedef struct _mp_obj_float_t {
mp_obj_t mp_obj_new_float(mp_float_t value);
-void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
+static void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_float_t *o = o_in;
print(env, "%.8g", o->value);
}
-mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
+static mp_obj_t float_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ switch (n_args) {
+ case 0:
+ return mp_obj_new_float(0);
+
+ case 1:
+ // TODO allow string as arg and parse it
+ if (MP_OBJ_IS_TYPE(args[0], &float_type)) {
+ return args[0];
+ } else {
+ return mp_obj_new_float(mp_obj_get_float(args[0]));
+ }
+
+ default:
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "float takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
+ }
+}
+
+static mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
mp_obj_float_t *o = o_in;
switch (op) {
case RT_UNARY_OP_NOT: if (o->value != 0) { return mp_const_true;} else { return mp_const_false; }
@@ -33,7 +52,7 @@ mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
}
}
-mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+static mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) {
return complex_type.binary_op(op, lhs_in, rhs_in);
}
@@ -61,6 +80,7 @@ const mp_obj_type_t float_type = {
{ &mp_const_type },
"float",
float_print,
+ float_make_new, // make_new
NULL, // call_n
float_unary_op,
float_binary_op,
diff --git a/py/objfun.c b/py/objfun.c
index 9601622d89..50de90bd1f 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
@@ -50,9 +51,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
@@ -72,6 +73,7 @@ const mp_obj_type_t fun_native_type = {
{ &mp_const_type },
"function",
NULL, // print
+ NULL, // make_new
fun_native_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
@@ -153,7 +155,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
@@ -173,6 +175,7 @@ const mp_obj_type_t fun_bc_type = {
{ &mp_const_type },
"function",
NULL, // print
+ NULL, // make_new
fun_bc_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
@@ -262,7 +265,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;
@@ -286,6 +289,7 @@ static const mp_obj_type_t fun_asm_type = {
{ &mp_const_type },
"function",
NULL, // print
+ NULL, // make_new
fun_asm_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objgenerator.c b/py/objgenerator.c
index ecdd72dc6d..7fbca075e2 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);
@@ -39,6 +40,7 @@ const mp_obj_type_t gen_wrap_type = {
{ &mp_const_type },
"generator",
NULL, // print
+ NULL, // make_new
gen_wrap_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
@@ -93,6 +95,7 @@ const mp_obj_type_t gen_instance_type = {
{ &mp_const_type },
"generator",
gen_instance_print, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objinstance.c b/py/objinstance.c
index e5d23af2d5..fd8cada7cb 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) {
@@ -92,6 +93,7 @@ const mp_obj_type_t instance_type = {
{ &mp_const_type },
"instance",
NULL, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objint.c b/py/objint.c
new file mode 100644
index 0000000000..5bc747e8f0
--- /dev/null
+++ b/py/objint.c
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "mpqstr.h"
+#include "obj.h"
+
+typedef struct _mp_obj_int_t {
+ mp_obj_base_t base;
+} mp_obj_int_t;
+
+static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ switch (n_args) {
+ case 0:
+ return MP_OBJ_NEW_SMALL_INT(0);
+
+ case 1:
+ // TODO allow string as arg and parse it
+ return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0]));
+
+ //case 2:
+ // TODO, parse with given base
+
+ default:
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "int takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args));
+ }
+}
+
+const mp_obj_type_t int_type = {
+ { &mp_const_type },
+ "int",
+ NULL,
+ int_make_new, // make_new
+ NULL, // call_n
+ NULL, // unary_op
+ NULL, // binary_op
+ NULL, // getiter
+ NULL, // iternext
+ { { NULL, NULL }, }, // method list
+};
+
+mp_obj_t mp_obj_new_int(machine_int_t value) {
+ return MP_OBJ_NEW_SMALL_INT(value);
+}
diff --git a/py/objlist.c b/py/objlist.c
index 0a795a2b08..ba8a5b50a3 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"
@@ -35,6 +36,29 @@ static void list_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "]");
}
+static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ switch (n_args) {
+ case 0:
+ // return a new, empty list
+ return rt_build_list(0, NULL);
+
+ case 1:
+ {
+ // make list from iterable
+ mp_obj_t iterable = rt_getiter(args[0]);
+ mp_obj_t list = rt_build_list(0, NULL);
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
+ rt_list_append(list, item);
+ }
+ return list;
+ }
+
+ 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));
+ }
+}
+
static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_list_t *o = lhs;
switch (op) {
@@ -81,7 +105,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];
@@ -170,7 +194,7 @@ static mp_obj_t list_index(int n_args, const mp_obj_t *args) {
}
}
- nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "Object not in list."));
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "object not in list"));
}
static mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
@@ -221,6 +245,7 @@ const mp_obj_type_t list_type = {
{ &mp_const_type },
"list",
list_print, // print
+ list_make_new, // make_new
NULL, // call_n
NULL, // unary_op
list_binary_op, // binary_op
@@ -301,6 +326,7 @@ static const mp_obj_type_t list_it_type = {
{ &mp_const_type },
"list_iterator",
NULL, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objmodule.c b/py/objmodule.c
index addab14b75..9263eb44f0 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -25,6 +25,7 @@ const mp_obj_type_t module_type = {
{ &mp_const_type },
"module",
module_print, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objnone.c b/py/objnone.c
index f7b665e997..11dd4939b1 100644
--- a/py/objnone.c
+++ b/py/objnone.c
@@ -18,6 +18,7 @@ const mp_obj_type_t none_type = {
{ &mp_const_type },
"NoneType",
none_print, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objrange.c b/py/objrange.c
index b7fd17fa0a..b163f779b8 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -26,6 +26,7 @@ static const mp_obj_type_t range_type = {
{ &mp_const_type} ,
"range",
NULL, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
@@ -70,6 +71,7 @@ static const mp_obj_type_t range_it_type = {
{ &mp_const_type },
"range_iterator",
NULL, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objset.c b/py/objset.c
index f225ca7f66..826f8bdc86 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -5,7 +5,9 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
+#include "runtime.h"
#include "map.h"
typedef struct _mp_obj_set_t {
@@ -29,10 +31,34 @@ void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
print(env, "}");
}
-static const mp_obj_type_t set_type = {
+static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ switch (n_args) {
+ case 0:
+ // return a new, empty set
+ return mp_obj_new_set(0, NULL);
+
+ case 1:
+ {
+ // 1 argument, an iterable from which we make a new set
+ mp_obj_t set = mp_obj_new_set(0, NULL);
+ mp_obj_t iterable = rt_getiter(args[0]);
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
+ mp_obj_set_store(set, item);
+ }
+ return set;
+ }
+
+ default:
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "set takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
+ }
+}
+
+const mp_obj_type_t set_type = {
{ &mp_const_type },
"set",
set_print, // print
+ set_make_new, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objslice.c b/py/objslice.c
index 03607e4c3e..a624be9631 100644
--- a/py/objslice.c
+++ b/py/objslice.c
@@ -9,6 +9,36 @@
#include "obj.h"
#include "runtime0.h"
+/******************************************************************************/
+/* ellipsis object, a singleton */
+
+typedef struct _mp_obj_ellipsis_t {
+ mp_obj_base_t base;
+} mp_obj_ellipsis_t;
+
+void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
+ print(env, "Ellipsis");
+}
+
+const mp_obj_type_t ellipsis_type = {
+ { &mp_const_type },
+ "ellipsis",
+ ellipsis_print, // print
+ NULL, // make_new
+ NULL, // call_n
+ NULL, // unary_op
+ NULL, // binary_op
+ NULL, // getiter
+ NULL, // iternext
+ {{NULL, NULL},}, // method list
+};
+
+static const mp_obj_ellipsis_t ellipsis_obj = {{&ellipsis_type}};
+const mp_obj_t mp_const_ellipsis = (mp_obj_t)&ellipsis_obj;
+
+/******************************************************************************/
+/* slice object */
+
#if MICROPY_ENABLE_SLICE
// TODO: This implements only variant of slice with 2 integer args only.
@@ -29,6 +59,7 @@ const mp_obj_type_t slice_type = {
"slice",
slice_print,
NULL, // call_n
+ NULL, // make_new
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
diff --git a/py/objstr.c b/py/objstr.c
index 59547e3cd6..a1d139e83a 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"
@@ -16,6 +17,11 @@ typedef struct _mp_obj_str_t {
qstr qstr;
} mp_obj_str_t;
+static mp_obj_t mp_obj_new_str_iterator(mp_obj_str_t *str, int cur);
+
+/******************************************************************************/
+/* str */
+
void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_str_t *self = self_in;
// TODO need to escape chars etc
@@ -41,16 +47,27 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
int len = strlen(lhs_str);
if (start < 0) {
start = len + start;
+ if (start < 0) {
+ start = 0;
+ }
+ } else if (start > len) {
+ start = len;
}
if (stop <= 0) {
stop = len + stop;
+ // CPython returns empty string in such case
+ if (stop < 0) {
+ stop = start;
+ }
+ } else if (stop > len) {
+ stop = len;
}
return mp_obj_new_str(qstr_from_strn_copy(lhs_str + start, stop - start));
#endif
} 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:
@@ -73,6 +90,10 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return MP_OBJ_NULL; // op not supported
}
+static mp_obj_t str_getiter(mp_obj_t o_in) {
+ return mp_obj_new_str_iterator(o_in, 0);
+}
+
mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(self_in, &str_type));
mp_obj_str_t *self = self_in;
@@ -123,7 +144,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, ...) {
@@ -147,7 +168,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++;
@@ -167,10 +188,11 @@ const mp_obj_type_t str_type = {
{ &mp_const_type },
"str",
str_print, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
str_binary_op, // binary_op
- NULL, // getiter
+ str_getiter, // getiter
NULL, // iternext
{ // method list
{ "join", &str_join_obj },
@@ -191,3 +213,45 @@ qstr mp_obj_str_get(mp_obj_t self_in) {
mp_obj_str_t *self = self_in;
return self->qstr;
}
+
+/******************************************************************************/
+/* str iterator */
+
+typedef struct _mp_obj_str_it_t {
+ mp_obj_base_t base;
+ mp_obj_str_t *str;
+ machine_uint_t cur;
+} mp_obj_str_it_t;
+
+mp_obj_t str_it_iternext(mp_obj_t self_in) {
+ mp_obj_str_it_t *self = self_in;
+ const char *str = qstr_str(self->str->qstr);
+ if (self->cur < strlen(str)) {
+ mp_obj_t o_out = mp_obj_new_str(qstr_from_strn_copy(str + self->cur, 1));
+ self->cur += 1;
+ return o_out;
+ } else {
+ return mp_const_stop_iteration;
+ }
+}
+
+static const mp_obj_type_t str_it_type = {
+ { &mp_const_type },
+ "str_iterator",
+ NULL, // print
+ NULL, // make_new
+ NULL, // call_n
+ NULL, // unary_op
+ NULL, // binary_op
+ NULL, // getiter
+ str_it_iternext, // iternext
+ { { NULL, NULL }, }, // method str
+};
+
+mp_obj_t mp_obj_new_str_iterator(mp_obj_str_t *str, int cur) {
+ mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
+ o->base.type = &str_it_type;
+ o->str = str;
+ o->cur = cur;
+ return o;
+}
diff --git a/py/objtuple.c b/py/objtuple.c
index b98d6ede7b..d55259d1a6 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -1,13 +1,14 @@
#include <stdlib.h>
#include <stdint.h>
-//#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
+#include "runtime.h"
typedef struct _mp_obj_tuple_t {
mp_obj_base_t base;
@@ -20,7 +21,7 @@ static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur);
/******************************************************************************/
/* tuple */
-void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
+static void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_tuple_t *o = o_in;
print(env, "(");
for (int i = 0; i < o->len; i++) {
@@ -35,7 +36,48 @@ void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_o
print(env, ")");
}
-mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
+// args are in reverse order in the array
+static mp_obj_t tuple_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
+ switch (n_args) {
+ case 0:
+ // return a empty tuple
+ return mp_const_empty_tuple;
+
+ case 1:
+ {
+ // 1 argument, an iterable from which we make a new tuple
+ if (MP_OBJ_IS_TYPE(args[0], &tuple_type)) {
+ return args[0];
+ }
+
+ // TODO optimise for cases where we know the length of the iterator
+
+ uint alloc = 4;
+ uint len = 0;
+ mp_obj_t *items = m_new(mp_obj_t, alloc);
+
+ mp_obj_t iterable = rt_getiter(args[0]);
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
+ if (len >= alloc) {
+ items = m_renew(mp_obj_t, items, alloc, alloc * 2);
+ alloc *= 2;
+ }
+ items[len++] = item;
+ }
+
+ mp_obj_t tuple = mp_obj_new_tuple(len, items);
+ m_free(items, alloc);
+
+ return tuple;
+ }
+
+ default:
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "tuple takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
+ }
+}
+
+static mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_tuple_t *o = lhs;
switch (op) {
case RT_BINARY_OP_SUBSCR:
@@ -50,20 +92,15 @@ mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
}
-mp_obj_t tuple_getiter(mp_obj_t o_in) {
+static mp_obj_t tuple_getiter(mp_obj_t o_in) {
return mp_obj_new_tuple_iterator(o_in, 0);
}
-void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
- mp_obj_tuple_t *self = self_in;
- *len = self->len;
- *items = &self->items[0];
-}
-
const mp_obj_type_t tuple_type = {
{ &mp_const_type },
"tuple",
tuple_print, // print
+ tuple_make_new, // make_new
NULL, // call_n
NULL, // unary_op
tuple_binary_op, // binary_op
@@ -72,7 +109,14 @@ const mp_obj_type_t tuple_type = {
{{NULL, NULL},}, // method list
};
+// the zero-length tuple
+static const mp_obj_tuple_t empty_tuple_obj = {{&tuple_type}, 0};
+const mp_obj_t mp_const_empty_tuple = (mp_obj_t)&empty_tuple_obj;
+
mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items) {
+ if (n == 0) {
+ return mp_const_empty_tuple;
+ }
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);
o->base.type = &tuple_type;
o->len = n;
@@ -83,6 +127,9 @@ mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items) {
}
mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items) {
+ if (n == 0) {
+ return mp_const_empty_tuple;
+ }
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);
o->base.type = &tuple_type;
o->len = n;
@@ -92,6 +139,12 @@ mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items) {
return o;
}
+void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
+ mp_obj_tuple_t *self = self_in;
+ *len = self->len;
+ *items = &self->items[0];
+}
+
/******************************************************************************/
/* tuple iterator */
@@ -101,7 +154,7 @@ typedef struct _mp_obj_tuple_it_t {
machine_uint_t cur;
} mp_obj_tuple_it_t;
-mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
+static mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
mp_obj_tuple_it_t *self = self_in;
if (self->cur < self->tuple->len) {
mp_obj_t o_out = self->tuple->items[self->cur];
@@ -116,6 +169,7 @@ static const mp_obj_type_t tuple_it_type = {
{ &mp_const_type },
"tuple_iterator",
NULL, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
diff --git a/py/objtype.c b/py/objtype.c
index 83ae48d2d1..aeeaebb95d 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -4,17 +4,30 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
-void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
- print(env, "<a type>");
+static void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
+ mp_obj_type_t *self = self_in;
+ print(env, "<class '%s'>", self->name);
+}
+
+static mp_obj_t type_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
+ mp_obj_type_t *self = self_in;
+ if (self->make_new != NULL) {
+ // TODO we need to init the object if it's an instance of a type
+ return self->make_new(self, n_args, args);
+ } else {
+ nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "cannot create '%s' instances", self->name));
+ }
}
const mp_obj_type_t mp_const_type = {
{ &mp_const_type },
- "<a type>",
+ "type",
type_print, // print
- NULL, // call_n
+ NULL, // make_new
+ type_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
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..197c08b55a 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,64 @@ 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 objects
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_Ellipsis, true)->value = mp_const_ellipsis;
// 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__);
-
- // 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___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 types
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_bool, true)->value = (mp_obj_t)&bool_type;
#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)&complex_type;
#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 = (mp_obj_t)&dict_type;
#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)&float_type;
#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_int, true)->value = (mp_obj_t)&int_type;
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_list, true)->value = (mp_obj_t)&list_type;
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_set, true)->value = (mp_obj_t)&set_type;
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_tuple, true)->value = (mp_obj_t)&tuple_type;
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_type, true)->value = (mp_obj_t)&mp_builtin_type_obj; // TODO
+
+ // built-in user functions; TODO covert all to &mp_builtin_xxx's
+ 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_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);
+ mp_qstr_map_lookup(&map_builtins, MP_QSTR_divmod, true)->value = rt_make_function_2(mp_builtin_divmod);
+ 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_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_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_sum, true)->value = rt_make_function_var(1, mp_builtin_sum);
+
+ next_unique_code_id = 1; // 0 indicates "no code"
unique_codes = NULL;
#ifdef WRITE_CODE
@@ -166,12 +141,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 +157,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 +326,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 +344,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 +362,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 +376,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 +384,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 +436,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 +515,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 +664,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 +727,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 +778,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 +821,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 +840,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/py/showbc.c b/py/showbc.c
index a3bfa2833b..eb7d41b24d 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -46,6 +46,10 @@ void mp_show_byte_code(const byte *ip, int len) {
printf("LOAD_CONST_TRUE");
break;
+ case MP_BC_LOAD_CONST_ELLIPSIS:
+ printf("LOAD_CONST_ELLIPSIS");
+ break;
+
case MP_BC_LOAD_CONST_SMALL_INT:
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
ip += 3;
diff --git a/py/vm.c b/py/vm.c
index 382780640b..8e7ef7485b 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -99,6 +99,10 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
PUSH(mp_const_true);
break;
+ case MP_BC_LOAD_CONST_ELLIPSIS:
+ PUSH(mp_const_ellipsis);
+ break;
+
case MP_BC_LOAD_CONST_SMALL_INT:
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
ip += 3;