Commit d99b0528 authored by Damien's avatar Damien
Browse files

Change object representation from 1 big union to individual structs.

A big change.  Micro Python objects are allocated as individual structs
with the first element being a pointer to the type information (which
is itself an object).  This scheme follows CPython.  Much more flexible,
not necessarily slower, uses same heap memory, and can allocate objects
statically.

Also change name prefix, from py_ to mp_ (mp for Micro Python).
parent e2880aa2
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include <string.h> #include <string.h>
#include "misc.h" #include "misc.h"
#include "mpyconfig.h" #include "mpconfig.h"
#include "asmthumb.h" #include "asmthumb.h"
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0) #define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
......
#define PYBC_LOAD_CONST_FALSE (0x10) mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state);
#define PYBC_LOAD_CONST_NONE (0x11) bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out);
#define PYBC_LOAD_CONST_TRUE (0x12)
#define PYBC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess
#define PYBC_LOAD_CONST_INT (0x14) // qstr
#define PYBC_LOAD_CONST_DEC (0x15) // qstr
#define PYBC_LOAD_CONST_ID (0x16) // qstr
#define PYBC_LOAD_CONST_BYTES (0x17) // qstr
#define PYBC_LOAD_CONST_STRING (0x18) // qstr
#define PYBC_LOAD_FAST_0 (0x20)
#define PYBC_LOAD_FAST_1 (0x21)
#define PYBC_LOAD_FAST_2 (0x22)
#define PYBC_LOAD_FAST_N (0x23) // uint
#define PYBC_LOAD_DEREF (0x24) // uint
#define PYBC_LOAD_CLOSURE (0x25) // uint
#define PYBC_LOAD_NAME (0x26) // qstr
#define PYBC_LOAD_GLOBAL (0x27) // qstr
#define PYBC_LOAD_ATTR (0x28) // qstr
#define PYBC_LOAD_METHOD (0x29) // qstr
#define PYBC_LOAD_BUILD_CLASS (0x2a)
#define PYBC_STORE_FAST_0 (0x30)
#define PYBC_STORE_FAST_1 (0x31)
#define PYBC_STORE_FAST_2 (0x32)
#define PYBC_STORE_FAST_N (0x33) // uint
#define PYBC_STORE_DEREF (0x34) // uint
#define PYBC_STORE_NAME (0x35) // qstr
#define PYBC_STORE_GLOBAL (0x36) // qstr
#define PYBC_STORE_ATTR (0x37) // qstr
#define PYBC_STORE_SUBSCR (0x38)
#define PYBC_DELETE_FAST_N (0x39) // uint
#define PYBC_DELETE_DEREF (0x3a) // uint
#define PYBC_DELETE_NAME (0x3b) // qstr
#define PYBC_DELETE_GLOBAL (0x3c) // qstr
#define PYBC_DELETE_ATTR (0x3d) // qstr
#define PYBC_DELETE_SUBSCR (0x3e)
#define PYBC_DUP_TOP (0x40)
#define PYBC_DUP_TOP_TWO (0x41)
#define PYBC_POP_TOP (0x42)
#define PYBC_ROT_TWO (0x43)
#define PYBC_ROT_THREE (0x44)
#define PYBC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
#define PYBC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
#define PYBC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
#define PYBC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
#define PYBC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
#define PYBC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned
#define PYBC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned
#define PYBC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned
#define PYBC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
#define PYBC_WITH_CLEANUP (0x4e)
#define PYBC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
#define PYBC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
#define PYBC_END_FINALLY (0x51)
#define PYBC_GET_ITER (0x52)
#define PYBC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
#define PYBC_POP_BLOCK (0x54)
#define PYBC_POP_EXCEPT (0x55)
#define PYBC_UNARY_OP (0x60) // byte
#define PYBC_BINARY_OP (0x61) // byte
#define PYBC_COMPARE_OP (0x62) // byte
#define PYBC_BUILD_TUPLE (0x70) // uint
#define PYBC_BUILD_LIST (0x71) // uint
#define PYBC_LIST_APPEND (0x72) // uint
#define PYBC_BUILD_MAP (0x73) // uint
#define PYBC_STORE_MAP (0x74)
#define PYBC_MAP_ADD (0x75) // uint
#define PYBC_BUILD_SET (0x76) // uint
#define PYBC_SET_ADD (0x77) // uint
#define PYBC_BUILD_SLICE (0x78) // uint
#define PYBC_UNPACK_SEQUENCE (0x79) // uint
#define PYBC_UNPACK_EX (0x7a) // uint
#define PYBC_RETURN_VALUE (0x80)
#define PYBC_RAISE_VARARGS (0x81) // uint
#define PYBC_YIELD_VALUE (0x82)
#define PYBC_YIELD_FROM (0x83)
#define PYBC_MAKE_FUNCTION (0x90) // uint
#define PYBC_MAKE_CLOSURE (0x91) // uint
#define PYBC_CALL_FUNCTION (0x92) // uint
#define PYBC_CALL_FUNCTION_VAR (0x93) // uint
#define PYBC_CALL_FUNCTION_KW (0x94) // uint
#define PYBC_CALL_FUNCTION_VAR_KW (0x95) // uint
#define PYBC_CALL_METHOD (0x96) // uint
#define PYBC_CALL_METHOD_VAR (0x97) // uint
#define PYBC_CALL_METHOD_KW (0x98) // uint
#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint
#define PYBC_IMPORT_NAME (0xe0) // qstr
#define PYBC_IMPORT_FROM (0xe1) // qstr
#define PYBC_IMPORT_STAR (0xe2)
py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args, uint n_state);
bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out);
#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_FAST_0 (0x20)
#define MP_BC_LOAD_FAST_1 (0x21)
#define MP_BC_LOAD_FAST_2 (0x22)
#define MP_BC_LOAD_FAST_N (0x23) // uint
#define MP_BC_LOAD_DEREF (0x24) // uint
#define MP_BC_LOAD_CLOSURE (0x25) // uint
#define MP_BC_LOAD_NAME (0x26) // qstr
#define MP_BC_LOAD_GLOBAL (0x27) // qstr
#define MP_BC_LOAD_ATTR (0x28) // qstr
#define MP_BC_LOAD_METHOD (0x29) // qstr
#define MP_BC_LOAD_BUILD_CLASS (0x2a)
#define MP_BC_STORE_FAST_0 (0x30)
#define MP_BC_STORE_FAST_1 (0x31)
#define MP_BC_STORE_FAST_2 (0x32)
#define MP_BC_STORE_FAST_N (0x33) // uint
#define MP_BC_STORE_DEREF (0x34) // uint
#define MP_BC_STORE_NAME (0x35) // qstr
#define MP_BC_STORE_GLOBAL (0x36) // qstr
#define MP_BC_STORE_ATTR (0x37) // qstr
#define MP_BC_STORE_SUBSCR (0x38)
#define MP_BC_DELETE_FAST_N (0x39) // uint
#define MP_BC_DELETE_DEREF (0x3a) // uint
#define MP_BC_DELETE_NAME (0x3b) // qstr
#define MP_BC_DELETE_GLOBAL (0x3c) // qstr
#define MP_BC_DELETE_ATTR (0x3d) // qstr
#define MP_BC_DELETE_SUBSCR (0x3e)
#define MP_BC_DUP_TOP (0x40)
#define MP_BC_DUP_TOP_TWO (0x41)
#define MP_BC_POP_TOP (0x42)
#define MP_BC_ROT_TWO (0x43)
#define MP_BC_ROT_THREE (0x44)
#define MP_BC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned
#define MP_BC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned
#define MP_BC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned
#define MP_BC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
#define MP_BC_WITH_CLEANUP (0x4e)
#define MP_BC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
#define MP_BC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
#define MP_BC_END_FINALLY (0x51)
#define MP_BC_GET_ITER (0x52)
#define MP_BC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
#define MP_BC_POP_BLOCK (0x54)
#define MP_BC_POP_EXCEPT (0x55)
#define MP_BC_UNARY_OP (0x60) // byte
#define MP_BC_BINARY_OP (0x61) // byte
#define MP_BC_COMPARE_OP (0x62) // byte
#define MP_BC_BUILD_TUPLE (0x70) // uint
#define MP_BC_BUILD_LIST (0x71) // uint
#define MP_BC_LIST_APPEND (0x72) // uint
#define MP_BC_BUILD_MAP (0x73) // uint
#define MP_BC_STORE_MAP (0x74)
#define MP_BC_MAP_ADD (0x75) // uint
#define MP_BC_BUILD_SET (0x76) // uint
#define MP_BC_SET_ADD (0x77) // uint
#define MP_BC_BUILD_SLICE (0x78) // uint
#define MP_BC_UNPACK_SEQUENCE (0x79) // uint
#define MP_BC_UNPACK_EX (0x7a) // uint
#define MP_BC_RETURN_VALUE (0x80)
#define MP_BC_RAISE_VARARGS (0x81) // uint
#define MP_BC_YIELD_VALUE (0x82)
#define MP_BC_YIELD_FROM (0x83)
#define MP_BC_MAKE_FUNCTION (0x90) // uint
#define MP_BC_MAKE_CLOSURE (0x91) // uint
#define MP_BC_CALL_FUNCTION (0x92) // uint
#define MP_BC_CALL_FUNCTION_VAR (0x93) // uint
#define MP_BC_CALL_FUNCTION_KW (0x94) // uint
#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint
#define MP_BC_CALL_METHOD (0x96) // uint
#define MP_BC_CALL_METHOD_VAR (0x97) // uint
#define MP_BC_CALL_METHOD_KW (0x98) // uint
#define MP_BC_CALL_METHOD_VAR_KW (0x99) // uint
#define MP_BC_IMPORT_NAME (0xe0) // qstr
#define MP_BC_IMPORT_FROM (0xe1) // qstr
#define MP_BC_IMPORT_STAR (0xe2)
...@@ -7,253 +7,258 @@ ...@@ -7,253 +7,258 @@
#include "nlr.h" #include "nlr.h"
#include "misc.h" #include "misc.h"
#include "mpyconfig.h" #include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h" #include "runtime.h"
#include "bc.h" //#include "bc.h"
#include "map.h" #include "map.h"
#include "obj.h"
#include "objprivate.h"
#include "builtin.h" #include "builtin.h"
py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) { mp_obj_t mp_builtin___build_class__(mp_obj_t o_class_fun, mp_obj_t o_class_name) {
// we differ from CPython: we set the new __locals__ object here // we differ from CPython: we set the new __locals__ object here
py_map_t *old_locals = rt_get_map_locals(); mp_map_t *old_locals = rt_get_map_locals();
py_map_t *class_locals = py_map_new(MAP_QSTR, 0); mp_map_t *class_locals = mp_map_new(MP_MAP_QSTR, 0);
rt_set_map_locals(class_locals); rt_set_map_locals(class_locals);
// call the class code // call the class code
rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef); rt_call_function_1(o_class_fun, (mp_obj_t)0xdeadbeef);
// restore old __locals__ object // restore old __locals__ object
rt_set_map_locals(old_locals); rt_set_map_locals(old_locals);
// create and return the new class // create and return the new class
py_obj_base_t *o = m_new(py_obj_base_t, 1); return mp_obj_new_class(class_locals);
o->kind = O_CLASS;
o->u_class.locals = class_locals;
return o;
} }
py_obj_t py_builtin___import__(int n, py_obj_t *args) { mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) {
printf("import:\n"); printf("import:\n");
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
printf(" "); printf(" ");
py_obj_print(args[i]); mp_obj_print(args[i]);
printf("\n"); printf("\n");
} }
return py_const_none; return mp_const_none;
} }
py_obj_t py_builtin___repl_print__(py_obj_t o) { mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
if (o != py_const_none) { if (o != mp_const_none) {
py_obj_print(o); mp_obj_print(o);
printf("\n"); printf("\n");
} }
return py_const_none; return mp_const_none;
} }
py_obj_t py_builtin_abs(py_obj_t o_in) { mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
if (IS_SMALL_INT(o_in)) { if (MP_OBJ_IS_SMALL_INT(o_in)) {
py_small_int_t val = FROM_SMALL_INT(o_in); mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
if (val < 0) { if (val < 0) {
val = -val; val = -val;
} }
return TO_SMALL_INT(val); return MP_OBJ_NEW_SMALL_INT(val);
#if MICROPY_ENABLE_FLOAT #if MICROPY_ENABLE_FLOAT
} else if (IS_O(o_in, O_FLOAT)) { } else if (MP_OBJ_IS_TYPE(o_in, &float_type)) {
py_obj_base_t *o = o_in; mp_float_t value = mp_obj_float_get(o_in);
// TODO check for NaN etc // TODO check for NaN etc
if (o->u_float < 0) { if (value < 0) {
return py_obj_new_float(-o->u_float); return mp_obj_new_float(-value);
} else { } else {
return o_in; return o_in;
} }
} else if (IS_O(o_in, O_COMPLEX)) { } else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) {
py_obj_base_t *o = o_in; mp_float_t real, imag;
return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag)); mp_obj_complex_get(o_in, &real, &imag);
return mp_obj_new_float(machine_sqrt(real*real + imag*imag));
#endif #endif
} else { } else {
assert(0); assert(0);
return py_const_none; return mp_const_none;
} }
} }
py_obj_t py_builtin_all(py_obj_t o_in) { mp_obj_t mp_builtin_all(mp_obj_t o_in) {
py_obj_t iterable = rt_getiter(o_in); mp_obj_t iterable = rt_getiter(o_in);
py_obj_t item; mp_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (!rt_is_true(item)) { if (!rt_is_true(item)) {
return py_const_false; return mp_const_false;
} }
} }
return py_const_true; return mp_const_true;
} }
py_obj_t py_builtin_any(py_obj_t o_in) { mp_obj_t mp_builtin_any(mp_obj_t o_in) {
py_obj_t iterable = rt_getiter(o_in); mp_obj_t iterable = rt_getiter(o_in);
py_obj_t item; mp_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (rt_is_true(item)) { if (rt_is_true(item)) {
return py_const_true; return mp_const_true;
} }
} }
return py_const_false; return mp_const_false;
} }
py_obj_t py_builtin_bool(int n_args, const py_obj_t *args) { mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args) {
switch (n_args) { switch (n_args) {
case 0: return py_const_false; case 0: return mp_const_false;
case 1: if (rt_is_true(args[0])) { return py_const_true; } else { return py_const_false; } case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL)); 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));
} }
} }
py_obj_t py_builtin_callable(py_obj_t o_in) { mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
if (py_obj_is_callable(o_in)) { if (mp_obj_is_callable(o_in)) {
return py_const_true; return mp_const_true;
} else { } else {
return py_const_false; return mp_const_false;
} }
} }
#if MICROPY_ENABLE_FLOAT #if MICROPY_ENABLE_FLOAT
py_obj_t py_builtin_complex(int n_args, const py_obj_t *args) { mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args) {
switch (n_args) { switch (n_args) {
case 0: case 0:
return py_obj_new_complex(0, 0); return mp_obj_new_complex(0, 0);
case 1: case 1:
// TODO allow string as first arg // TODO allow string as first arg
if (IS_O(args[0], O_COMPLEX)) { if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
return args[0]; return args[0];
} else { } else {
return py_obj_new_complex(py_obj_get_float(args[0]), 0); return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
} }
case 2: case 2:
{ {
py_float_t real, imag; mp_float_t real, imag;
if (IS_O(args[0], O_COMPLEX)) { if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
py_obj_get_complex(args[0], &real, &imag); mp_obj_get_complex(args[0], &real, &imag);
} else { } else {
real = py_obj_get_float(args[0]); real = mp_obj_get_float(args[0]);
imag = 0; imag = 0;
} }
if (IS_O(args[1], O_COMPLEX)) { if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
py_float_t real2, imag2; mp_float_t real2, imag2;
py_obj_get_complex(args[1], &real2, &imag2); mp_obj_get_complex(args[1], &real2, &imag2);
real -= imag2; real -= imag2;
imag += real2; imag += real2;
} else { } else {
imag += py_obj_get_float(args[1]); imag += mp_obj_get_float(args[1]);
} }
return py_obj_new_complex(real, imag); return mp_obj_new_complex(real, imag);
} }
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args, NULL)); default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args));
} }
} }
#endif #endif
py_obj_t py_builtin_chr(py_obj_t o_in) { mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
int ord = py_obj_get_int(o_in); int ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) { if (0 <= ord && ord <= 0x10ffff) {
char *str = m_new(char, 2); char *str = m_new(char, 2);
str[0] = ord; str[0] = ord;
str[1] = '\0'; str[1] = '\0';
return py_obj_new_str(qstr_from_str_take(str)); return mp_obj_new_str(qstr_from_str_take(str));
} else { } else {
nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "chr() arg not in range(0x110000)", NULL, NULL)); nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "chr() arg not in range(0x110000)"));
} }
} }
py_obj_t py_builtin_dict(void) { mp_obj_t mp_builtin_dict(void) {
// TODO create from an iterable! // TODO create from an iterable!
return rt_build_map(0); return rt_build_map(0);
} }
py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in) { mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
if (IS_SMALL_INT(o1_in) && IS_SMALL_INT(o2_in)) { if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
py_small_int_t i1 = FROM_SMALL_INT(o1_in); mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
py_small_int_t i2 = FROM_SMALL_INT(o2_in); mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
py_obj_t revs_args[2]; mp_obj_t revs_args[2];
revs_args[1] = TO_SMALL_INT(i1 / i2); revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
revs_args[0] = TO_SMALL_INT(i1 % i2); revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args); return rt_build_tuple(2, revs_args);
} else { } else {
nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", py_obj_get_type_str(o1_in), py_obj_get_type_str(o2_in))); 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)));
} }
} }
py_obj_t py_builtin_hash(py_obj_t o_in) { static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
// TODO hash will generally overflow small integer; can we safely truncate it? // TODO hash will generally overflow small integer; can we safely truncate it?
return py_obj_new_int(py_obj_hash(o_in)); return mp_obj_new_int(mp_obj_hash(o_in));
} }
py_obj_t py_builtin_iter(py_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
return rt_getiter(o_in);
}
py_obj_t py_builtin_next(py_obj_t o_in) { static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
return rt_gen_instance_next(o_in); return rt_getiter(o_in);
} }
py_obj_t py_builtin_len(py_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
py_small_int_t len = 0;
if (IS_O(o_in, O_STR)) { mp_obj_t mp_builtin_len(mp_obj_t o_in) {
py_obj_base_t *o = o_in; mp_small_int_t len = 0;
len = strlen(qstr_str(o->u_str)); if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
} else if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) { len = strlen(qstr_str(mp_obj_str_get(o_in)));
py_obj_base_t *o = o_in; } else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
len = o->u_tuple_list.len; uint seq_len;
} else if (IS_O(o_in, O_MAP)) { mp_obj_t *seq_items;
py_obj_base_t *o = o_in; mp_obj_tuple_get(o_in, &seq_len, &seq_items);
len = seq_len;
} else if (MP_OBJ_IS_TYPE(o_in, &list_type)) {
uint seq_len;
mp_obj_t *seq_items;
mp_obj_list_get(o_in, &seq_len, &seq_items);
len = seq_len;
/* TODO
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
mp_obj_base_t *o = o_in;
len = o->u_map.used; len = o->u_map.used;
*/
} else { } else {
nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "object of type '%s' has no len()", py_obj_get_type_str(o_in), NULL)); 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)));
} }
return TO_SMALL_INT(len); return MP_OBJ_NEW_SMALL_INT(len);
} }
py_obj_t py_builtin_list(int n_args, const py_obj_t *args) { mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) {
switch (n_args) { switch (n_args) {
case 0: return rt_build_list(0, NULL); case 0: return rt_build_list(0, NULL);
case 1: case 1:
{ {
// make list from iterable // make list from iterable
py_obj_t iterable = rt_getiter(args[0]); mp_obj_t iterable = rt_getiter(args[0]);
py_obj_t list = rt_build_list(0, NULL); mp_obj_t list = rt_build_list(0, NULL);
py_obj_t