diff --git a/py/builtin.c b/py/builtin.c index b565ed464..6babc7669 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -88,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(MP_QSTR_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; @@ -104,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) { @@ -152,11 +108,6 @@ mp_obj_t mp_builtin_chr(mp_obj_t o_in) { } } -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); @@ -170,25 +121,6 @@ mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t 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])); - } - } -} - -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)); @@ -196,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); } @@ -241,24 +156,6 @@ mp_obj_t mp_builtin_len(mp_obj_t 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(MP_QSTR_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 @@ -367,26 +264,6 @@ mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *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) { @@ -405,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/compile.c b/py/compile.c index f8fa2cb2c..0e1989031 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1316,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, MP_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]); diff --git a/py/emitpass1.c b/py/emitpass1.c index 1c11241e0..f78ec7e27 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/mpqstrraw.h b/py/mpqstrraw.h index e73bd828e..fe74c3e92 100644 --- a/py/mpqstrraw.h +++ b/py/mpqstrraw.h @@ -13,7 +13,6 @@ Q(__next__) Q(__qualname__) Q(__repl_print__) -Q(assertion_error) Q(micropython) Q(byte_code) Q(native) @@ -23,12 +22,13 @@ Q(asm_thumb) Q(Ellipsis) Q(StopIteration) +Q(AssertionError) Q(AttributeError) Q(IndexError) Q(KeyError) Q(NameError) -Q(TypeError) Q(SyntaxError) +Q(TypeError) Q(ValueError) Q(abs) @@ -55,6 +55,7 @@ Q(print) Q(range) Q(set) Q(sum) +Q(tuple) Q(type) Q(append) diff --git a/py/obj.c b/py/obj.c index 2b834ffe4..77580e1fe 100644 --- a/py/obj.c +++ b/py/obj.c @@ -13,10 +13,6 @@ #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"; @@ -128,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))); } } diff --git a/py/obj.h b/py/obj.h index f0ba6999e..03e67dd47 100644 --- a/py/obj.h +++ b/py/obj.h @@ -58,6 +58,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); @@ -71,6 +72,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 @@ -110,6 +112,7 @@ 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!) @@ -180,6 +183,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); @@ -214,6 +220,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 9b53ffae9..1d94ee03b 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 8bd238c65..264c2effd 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 cba198057..daaa340a7 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 f223c5ff2..197dfa726 100644 --- a/py/objclass.c +++ b/py/objclass.c @@ -64,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 e3354d42d..550bb5067 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 ab9c14677..5408d71cf 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 acf1a9f80..3737f5eab 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -17,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, "{"); @@ -35,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: @@ -58,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 e735852c3..ec03b9bf1 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 f151fe25a..8fc925e0b 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 c4783867a..22b82a9ca 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -70,6 +70,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 @@ -162,6 +163,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 @@ -275,6 +277,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 849212269..7fbca075e 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -40,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 @@ -94,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 6cfcdf6c1..fd8cada7c 100644 --- a/py/objinstance.c +++ b/py/objinstance.c @@ -93,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/objlist.c b/py/objlist.c index 967df44fd..301882611 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -36,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) { @@ -165,6 +188,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 @@ -242,6 +266,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 addab14b7..9263eb44f 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 f7b665e99..11dd4939b 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 b7fd17fa0..b163f779b 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 f225ca7f6..826f8bdc8 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 d99325fd7..a624be963 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -24,6 +24,7 @@ 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 @@ -58,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 03a761863..27c9440d0 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -179,6 +179,7 @@ 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 diff --git a/py/objtuple.c b/py/objtuple.c index b98d6ede7..d55259d1a 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -1,13 +1,14 @@ #include #include -//#include #include #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 83ae48d2d..aeeaebb95 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, ""); +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, "", 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 }, - "", + "type", type_print, // print - NULL, // call_n + NULL, // make_new + type_call_n, // call_n NULL, // unary_op NULL, // binary_op NULL, // getiter diff --git a/py/runtime.c b/py/runtime.c index 72881067d..197c08b55 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -91,26 +91,31 @@ void rt_init(void) { mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__); mp_qstr_map_lookup(&map_builtins, MP_QSTR___repl_print__, true)->value = rt_make_function_1(mp_builtin___repl_print__); - // built-in user functions + // 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, MP_QSTR_complex, true)->value = (mp_obj_t)&complex_type; +#endif + 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, MP_QSTR_float, true)->value = (mp_obj_t)&float_type; +#endif + 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_bool, true)->value = rt_make_function_var(0, mp_builtin_bool); mp_qstr_map_lookup(&map_builtins, MP_QSTR_callable, true)->value = rt_make_function_1(mp_builtin_callable); mp_qstr_map_lookup(&map_builtins, MP_QSTR_chr, true)->value = rt_make_function_1(mp_builtin_chr); -#if MICROPY_ENABLE_FLOAT - mp_qstr_map_lookup(&map_builtins, MP_QSTR_complex, true)->value = (mp_obj_t)&mp_builtin_complex_obj; -#endif - mp_qstr_map_lookup(&map_builtins, MP_QSTR_dict, true)->value = rt_make_function_0(mp_builtin_dict); mp_qstr_map_lookup(&map_builtins, MP_QSTR_divmod, true)->value = rt_make_function_2(mp_builtin_divmod); -#if MICROPY_ENABLE_FLOAT - mp_qstr_map_lookup(&map_builtins, MP_QSTR_float, true)->value = (mp_obj_t)&mp_builtin_float_obj; -#endif mp_qstr_map_lookup(&map_builtins, MP_QSTR_hash, true)->value = (mp_obj_t)&mp_builtin_hash_obj; - mp_qstr_map_lookup(&map_builtins, MP_QSTR_int, true)->value = (mp_obj_t)&mp_builtin_int_obj; mp_qstr_map_lookup(&map_builtins, MP_QSTR_iter, true)->value = (mp_obj_t)&mp_builtin_iter_obj; mp_qstr_map_lookup(&map_builtins, MP_QSTR_len, true)->value = rt_make_function_1(mp_builtin_len); - mp_qstr_map_lookup(&map_builtins, MP_QSTR_list, true)->value = rt_make_function_var(0, mp_builtin_list); mp_qstr_map_lookup(&map_builtins, MP_QSTR_max, true)->value = rt_make_function_var(1, mp_builtin_max); mp_qstr_map_lookup(&map_builtins, MP_QSTR_min, true)->value = rt_make_function_var(1, mp_builtin_min); mp_qstr_map_lookup(&map_builtins, MP_QSTR_next, true)->value = (mp_obj_t)&mp_builtin_next_obj; @@ -118,9 +123,7 @@ void rt_init(void) { mp_qstr_map_lookup(&map_builtins, MP_QSTR_pow, true)->value = rt_make_function_var(2, mp_builtin_pow); mp_qstr_map_lookup(&map_builtins, MP_QSTR_print, true)->value = rt_make_function_var(0, mp_builtin_print); mp_qstr_map_lookup(&map_builtins, MP_QSTR_range, true)->value = rt_make_function_var(1, mp_builtin_range); - mp_qstr_map_lookup(&map_builtins, MP_QSTR_set, true)->value = (mp_obj_t)&mp_builtin_set_obj; mp_qstr_map_lookup(&map_builtins, MP_QSTR_sum, true)->value = rt_make_function_var(1, mp_builtin_sum); - mp_qstr_map_lookup(&map_builtins, MP_QSTR_type, true)->value = (mp_obj_t)&mp_builtin_type_obj; next_unique_code_id = 1; // 0 indicates "no code" unique_codes = NULL; diff --git a/stm/Makefile b/stm/Makefile index 729913bae..d75c945bf 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -73,6 +73,7 @@ PY_O = \ objfun.o \ objgenerator.o \ objinstance.o \ + objint.o \ objlist.o \ objmodule.o \ objnone.o \ diff --git a/stm/i2c.c b/stm/i2c.c index e00cf4130..3f29f02c0 100644 --- a/stm/i2c.c +++ b/stm/i2c.c @@ -330,6 +330,7 @@ static const mp_obj_type_t i2c_obj_type = { { &mp_const_type }, "I2C", i2c_obj_print, // print + NULL, // make_new NULL, // call_n NULL, // unary_op NULL, // binary_op diff --git a/stm/led.c b/stm/led.c index 08077641a..9305716be 100644 --- a/stm/led.c +++ b/stm/led.c @@ -108,6 +108,7 @@ static const mp_obj_type_t led_obj_type = { { &mp_const_type }, "Led", led_obj_print, // print + NULL, // make_new NULL, // call_n NULL, // unary_op NULL, // binary_op diff --git a/stm/main.c b/stm/main.c index b7ae8aacc..0ab44ca8d 100644 --- a/stm/main.c +++ b/stm/main.c @@ -746,6 +746,7 @@ static const mp_obj_type_t file_obj_type = { { &mp_const_type }, "File", file_obj_print, // print + NULL, // make_new NULL, // call_n NULL, // unary_op NULL, // binary_op diff --git a/stm/servo.c b/stm/servo.c index ae421048b..1e31db514 100644 --- a/stm/servo.c +++ b/stm/servo.c @@ -141,6 +141,7 @@ static const mp_obj_type_t servo_obj_type = { { &mp_const_type }, "Servo", servo_obj_print, // print + NULL, // make_new NULL, // call_n NULL, // unary_op NULL, // binary_op diff --git a/unix-cpy/Makefile b/unix-cpy/Makefile index 7fee3438f..a1eb9b77e 100644 --- a/unix-cpy/Makefile +++ b/unix-cpy/Makefile @@ -38,6 +38,7 @@ PY_O = \ objfun.o \ objgenerator.o \ objinstance.o \ + objint.o \ objlist.o \ objmodule.o \ objnone.o \ diff --git a/unix/Makefile b/unix/Makefile index c7be62e99..984f1c3bf 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -45,6 +45,7 @@ PY_O = \ objfun.o \ objgenerator.o \ objinstance.o \ + objint.o \ objlist.o \ objmodule.o \ objnone.o \ diff --git a/unix/main.c b/unix/main.c index ecb2fa338..16fcf6ef8 100644 --- a/unix/main.c +++ b/unix/main.c @@ -192,6 +192,7 @@ static const mp_obj_type_t test_type = { { &mp_const_type }, "Test", test_print, // print + NULL, // make_new NULL, // call_n NULL, // unary_op NULL, // binary_op