diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/asmthumb.c | 5 | ||||
-rw-r--r-- | py/asmx64.c | 6 | ||||
-rw-r--r-- | py/bc0.h | 16 | ||||
-rw-r--r-- | py/builtin.c | 147 | ||||
-rw-r--r-- | py/builtinimport.c | 5 | ||||
-rw-r--r-- | py/compile.c | 83 | ||||
-rw-r--r-- | py/emitbc.c | 1 | ||||
-rw-r--r-- | py/emitcpy.c | 1 | ||||
-rw-r--r-- | py/emitnative.c | 4 | ||||
-rw-r--r-- | py/emitpass1.c | 5 | ||||
-rw-r--r-- | py/grammar.h | 8 | ||||
-rw-r--r-- | py/lexer.c | 2 | ||||
-rw-r--r-- | py/lexer.h | 2 | ||||
-rw-r--r-- | py/mpqstr.h | 13 | ||||
-rw-r--r-- | py/mpqstrraw.h | 65 | ||||
-rw-r--r-- | py/nlrx64.S | 23 | ||||
-rw-r--r-- | py/obj.c | 25 | ||||
-rw-r--r-- | py/obj.h | 8 | ||||
-rw-r--r-- | py/objbool.c | 14 | ||||
-rw-r--r-- | py/objboundmeth.c | 1 | ||||
-rw-r--r-- | py/objcell.c | 1 | ||||
-rw-r--r-- | py/objclass.c | 8 | ||||
-rw-r--r-- | py/objclosure.c | 1 | ||||
-rw-r--r-- | py/objcomplex.c | 45 | ||||
-rw-r--r-- | py/objdict.c | 14 | ||||
-rw-r--r-- | py/objexcept.c | 1 | ||||
-rw-r--r-- | py/objfloat.c | 26 | ||||
-rw-r--r-- | py/objfun.c | 14 | ||||
-rw-r--r-- | py/objgenerator.c | 5 | ||||
-rw-r--r-- | py/objinstance.c | 4 | ||||
-rw-r--r-- | py/objint.c | 48 | ||||
-rw-r--r-- | py/objlist.c | 30 | ||||
-rw-r--r-- | py/objmodule.c | 1 | ||||
-rw-r--r-- | py/objnone.c | 1 | ||||
-rw-r--r-- | py/objrange.c | 2 | ||||
-rw-r--r-- | py/objset.c | 28 | ||||
-rw-r--r-- | py/objslice.c | 31 | ||||
-rw-r--r-- | py/objstr.c | 72 | ||||
-rw-r--r-- | py/objtuple.c | 76 | ||||
-rw-r--r-- | py/objtype.c | 21 | ||||
-rw-r--r-- | py/qstr.c | 101 | ||||
-rw-r--r-- | py/runtime.c | 167 | ||||
-rw-r--r-- | py/runtime.h | 15 | ||||
-rw-r--r-- | py/runtime0.h | 2 | ||||
-rw-r--r-- | py/showbc.c | 4 | ||||
-rw-r--r-- | py/vm.c | 4 |
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 @@ -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 @@ -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))); } } @@ -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 @@ -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; @@ -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; |