summaryrefslogtreecommitdiffstatshomepage
path: root/py/builtin.c
diff options
context:
space:
mode:
authorDamien <damien.p.george@gmail.com>2013-12-21 18:17:45 +0000
committerDamien <damien.p.george@gmail.com>2013-12-21 18:17:45 +0000
commitd99b05282d14ceb0163cbcd059aa37bdb415af43 (patch)
tree978135f9fe83d3c4d5b3c95f84cb104c0092936a /py/builtin.c
parente2880aa2fdc75298df487df7519d483acb03959c (diff)
downloadmicropython-d99b05282d14ceb0163cbcd059aa37bdb415af43.tar.gz
micropython-d99b05282d14ceb0163cbcd059aa37bdb415af43.zip
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).
Diffstat (limited to 'py/builtin.c')
-rw-r--r--py/builtin.c321
1 files changed, 176 insertions, 145 deletions
diff --git a/py/builtin.c b/py/builtin.c
index e45cdc98bc..11e19fdea9 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -7,253 +7,258 @@
#include "nlr.h"
#include "misc.h"
-#include "mpyconfig.h"
+#include "mpconfig.h"
+#include "obj.h"
+#include "runtime0.h"
#include "runtime.h"
-#include "bc.h"
-
+//#include "bc.h"
#include "map.h"
-#include "obj.h"
-#include "objprivate.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
- py_map_t *old_locals = rt_get_map_locals();
- py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
+ mp_map_t *old_locals = rt_get_map_locals();
+ mp_map_t *class_locals = mp_map_new(MP_MAP_QSTR, 0);
rt_set_map_locals(class_locals);
// 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
rt_set_map_locals(old_locals);
// create and return the new class
- py_obj_base_t *o = m_new(py_obj_base_t, 1);
- o->kind = O_CLASS;
- o->u_class.locals = class_locals;
- return o;
+ return mp_obj_new_class(class_locals);
}
-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");
for (int i = 0; i < n; i++) {
printf(" ");
- py_obj_print(args[i]);
+ mp_obj_print(args[i]);
printf("\n");
}
- return py_const_none;
+ return mp_const_none;
}
-py_obj_t py_builtin___repl_print__(py_obj_t o) {
- if (o != py_const_none) {
- py_obj_print(o);
+mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
+ if (o != mp_const_none) {
+ mp_obj_print(o);
printf("\n");
}
- return py_const_none;
+ return mp_const_none;
}
-py_obj_t py_builtin_abs(py_obj_t o_in) {
- if (IS_SMALL_INT(o_in)) {
- py_small_int_t val = FROM_SMALL_INT(o_in);
+mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
+ if (MP_OBJ_IS_SMALL_INT(o_in)) {
+ mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
if (val < 0) {
val = -val;
}
- return TO_SMALL_INT(val);
+ return MP_OBJ_NEW_SMALL_INT(val);
#if MICROPY_ENABLE_FLOAT
- } else if (IS_O(o_in, O_FLOAT)) {
- py_obj_base_t *o = o_in;
+ } else if (MP_OBJ_IS_TYPE(o_in, &float_type)) {
+ mp_float_t value = mp_obj_float_get(o_in);
// TODO check for NaN etc
- if (o->u_float < 0) {
- return py_obj_new_float(-o->u_float);
+ if (value < 0) {
+ return mp_obj_new_float(-value);
} else {
return o_in;
}
- } else if (IS_O(o_in, O_COMPLEX)) {
- py_obj_base_t *o = o_in;
- return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
+ } else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) {
+ mp_float_t real, imag;
+ mp_obj_complex_get(o_in, &real, &imag);
+ return mp_obj_new_float(machine_sqrt(real*real + imag*imag));
#endif
} else {
assert(0);
- return py_const_none;
+ return mp_const_none;
}
}
-py_obj_t py_builtin_all(py_obj_t o_in) {
- py_obj_t iterable = rt_getiter(o_in);
- py_obj_t item;
- while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+mp_obj_t mp_builtin_all(mp_obj_t o_in) {
+ mp_obj_t iterable = rt_getiter(o_in);
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
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) {
- py_obj_t iterable = rt_getiter(o_in);
- py_obj_t item;
- while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+mp_obj_t mp_builtin_any(mp_obj_t o_in) {
+ mp_obj_t iterable = rt_getiter(o_in);
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
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) {
- case 0: return py_const_false;
- case 1: if (rt_is_true(args[0])) { return py_const_true; } else { return py_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));
+ 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));
}
}
-py_obj_t py_builtin_callable(py_obj_t o_in) {
- if (py_obj_is_callable(o_in)) {
- return py_const_true;
+mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
+ if (mp_obj_is_callable(o_in)) {
+ return mp_const_true;
} else {
- return py_const_false;
+ return mp_const_false;
}
}
#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) {
case 0:
- return py_obj_new_complex(0, 0);
+ return mp_obj_new_complex(0, 0);
case 1:
// 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];
} 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:
{
- py_float_t real, imag;
- if (IS_O(args[0], O_COMPLEX)) {
- py_obj_get_complex(args[0], &real, &imag);
+ mp_float_t real, imag;
+ if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
+ mp_obj_get_complex(args[0], &real, &imag);
} else {
- real = py_obj_get_float(args[0]);
+ real = mp_obj_get_float(args[0]);
imag = 0;
}
- if (IS_O(args[1], O_COMPLEX)) {
- py_float_t real2, imag2;
- py_obj_get_complex(args[1], &real2, &imag2);
+ 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 += 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
-py_obj_t py_builtin_chr(py_obj_t o_in) {
- int ord = py_obj_get_int(o_in);
+mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
+ int ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) {
char *str = m_new(char, 2);
str[0] = ord;
str[1] = '\0';
- return py_obj_new_str(qstr_from_str_take(str));
+ return mp_obj_new_str(qstr_from_str_take(str));
} 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!
return rt_build_map(0);
}
-py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in) {
- if (IS_SMALL_INT(o1_in) && IS_SMALL_INT(o2_in)) {
- py_small_int_t i1 = FROM_SMALL_INT(o1_in);
- py_small_int_t i2 = FROM_SMALL_INT(o2_in);
- py_obj_t revs_args[2];
- revs_args[1] = TO_SMALL_INT(i1 / i2);
- revs_args[0] = TO_SMALL_INT(i1 % i2);
+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);
+ mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
+ mp_obj_t revs_args[2];
+ revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
+ revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args);
} 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?
- 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) {
- return rt_getiter(o_in);
-}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
-py_obj_t py_builtin_next(py_obj_t o_in) {
- return rt_gen_instance_next(o_in);
+static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
+ return rt_getiter(o_in);
}
-py_obj_t py_builtin_len(py_obj_t o_in) {
- py_small_int_t len = 0;
- if (IS_O(o_in, O_STR)) {
- py_obj_base_t *o = o_in;
- len = strlen(qstr_str(o->u_str));
- } else if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
- py_obj_base_t *o = o_in;
- len = o->u_tuple_list.len;
- } else if (IS_O(o_in, O_MAP)) {
- py_obj_base_t *o = o_in;
+MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
+
+mp_obj_t mp_builtin_len(mp_obj_t o_in) {
+ mp_small_int_t len = 0;
+ if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
+ len = strlen(qstr_str(mp_obj_str_get(o_in)));
+ } else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
+ uint seq_len;
+ mp_obj_t *seq_items;
+ 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;
+ */
} 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) {
case 0: return rt_build_list(0, NULL);
case 1:
{
// make list from iterable
- py_obj_t iterable = rt_getiter(args[0]);
- py_obj_t list = rt_build_list(0, NULL);
- py_obj_t item;
- while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+ 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(py_obj_new_exception_2(rt_q_TypeError, "list() 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, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
-py_obj_t py_builtin_max(int n_args, const py_obj_t *args) {
+mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
if (n_args == 1) {
// given an iterable
- py_obj_t iterable = rt_getiter(args[0]);
- py_obj_t max_obj = NULL;
- py_obj_t item;
- while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
- if (max_obj == NULL || py_obj_less(max_obj, item)) {
+ mp_obj_t iterable = rt_getiter(args[0]);
+ mp_obj_t max_obj = NULL;
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
+ if (max_obj == NULL || mp_obj_less(max_obj, item)) {
max_obj = item;
}
}
if (max_obj == NULL) {
- nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "max() arg is an empty sequence", NULL, NULL));
+ nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "max() arg is an empty sequence"));
}
return max_obj;
} else {
// given many args
- py_obj_t max_obj = args[0];
+ mp_obj_t max_obj = args[0];
for (int i = 1; i < n_args; i++) {
- if (py_obj_less(max_obj, args[i])) {
+ if (mp_obj_less(max_obj, args[i])) {
max_obj = args[i];
}
}
@@ -261,26 +266,26 @@ py_obj_t py_builtin_max(int n_args, const py_obj_t *args) {
}
}
-py_obj_t py_builtin_min(int n_args, const py_obj_t *args) {
+mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
if (n_args == 1) {
// given an iterable
- py_obj_t iterable = rt_getiter(args[0]);
- py_obj_t min_obj = NULL;
- py_obj_t item;
- while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
- if (min_obj == NULL || py_obj_less(item, min_obj)) {
+ mp_obj_t iterable = rt_getiter(args[0]);
+ mp_obj_t min_obj = NULL;
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
+ if (min_obj == NULL || mp_obj_less(item, min_obj)) {
min_obj = item;
}
}
if (min_obj == NULL) {
- nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "min() arg is an empty sequence", NULL, NULL));
+ nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "min() arg is an empty sequence"));
}
return min_obj;
} else {
// given many args
- py_obj_t min_obj = args[0];
+ mp_obj_t min_obj = args[0];
for (int i = 1; i < n_args; i++) {
- if (py_obj_less(args[i], min_obj)) {
+ if (mp_obj_less(args[i], min_obj)) {
min_obj = args[i];
}
}
@@ -288,59 +293,85 @@ py_obj_t py_builtin_min(int n_args, const py_obj_t *args) {
}
}
-py_obj_t py_builtin_ord(py_obj_t o_in) {
- const char *str = qstr_str(py_obj_get_qstr(o_in));
+static mp_obj_t mp_builtin_next(mp_obj_t o_in) {
+ return mp_obj_gen_instance_next(o_in);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next);
+
+mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
+ const char *str = qstr_str(mp_obj_get_qstr(o_in));
if (strlen(str) == 1) {
- return py_obj_new_int(str[0]);
+ return mp_obj_new_int(str[0]);
} else {
- nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str), NULL));
+ 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)));
}
}
-py_obj_t py_builtin_pow(int n_args, const py_obj_t *args) {
+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(py_obj_new_exception_2(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
+ 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));
}
}
-py_obj_t py_builtin_print(int n_args, const py_obj_t *args) {
+mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args) {
for (int i = 0; i < n_args; i++) {
if (i > 0) {
printf(" ");
}
- if (IS_O(args[i], O_STR)) {
+ if (MP_OBJ_IS_TYPE(args[i], &str_type)) {
// special case, print string raw
- printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str));
+ printf("%s", qstr_str(mp_obj_str_get(args[i])));
} else {
// print the object Python style
- py_obj_print(args[i]);
+ mp_obj_print(args[i]);
}
}
printf("\n");
- return py_const_none;
+ return mp_const_none;
}
-py_obj_t py_builtin_range(int n_args, const py_obj_t *args) {
+mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) {
switch (n_args) {
- case 1: return py_obj_new_range(0, py_obj_get_int(args[0]), 1);
- case 2: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), 1);
- case 3: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), py_obj_get_int(args[2]));
- default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
+ 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));
+ }
+}
+
+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;
}
}
-py_obj_t py_builtin_sum(int n_args, const py_obj_t *args) {
- py_obj_t value;
+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 = py_obj_new_int(0); break;
+ case 1: value = mp_obj_new_int(0); break;
case 2: value = args[1]; break;
- default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
+ 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));
}
- py_obj_t iterable = rt_getiter(args[0]);
- py_obj_t item;
- while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+ mp_obj_t iterable = rt_getiter(args[0]);
+ mp_obj_t item;
+ while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
value = rt_binary_op(RT_BINARY_OP_ADD, value, item);
}
return value;