py: Add iter_buf to getiter type method.
Allows to iterate over the following without allocating on the heap: - tuple - list - string, bytes - bytearray, array - dict (not dict.keys, dict.values, dict.items) - set, frozenset Allows to call the following without heap memory: - all, any, min, max, sum TODO: still need to allocate stack memory in bytecode for iter_buf.
This commit is contained in:
parent
101886f529
commit
ae8d867586
@ -664,7 +664,7 @@ const mp_obj_type_t pyb_uart_type = {
|
||||
.name = MP_QSTR_UART,
|
||||
.print = pyb_uart_print,
|
||||
.make_new = pyb_uart_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &uart_stream_p,
|
||||
.locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
|
||||
|
@ -285,7 +285,7 @@ const mp_obj_type_t pyb_uart_type = {
|
||||
.name = MP_QSTR_UART,
|
||||
.print = pyb_uart_print,
|
||||
.make_new = pyb_uart_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &uart_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict,
|
||||
|
@ -184,7 +184,8 @@ STATIC mp_obj_t btree_items(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_items_obj, 1, 4, btree_items);
|
||||
|
||||
STATIC mp_obj_t btree_getiter(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
(void)iter_buf;
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->next_flags != 0) {
|
||||
// If we're called immediately after keys(), values(), or items(),
|
||||
|
@ -264,7 +264,7 @@ const mp_obj_type_t mp_type_fileio = {
|
||||
.name = MP_QSTR_FileIO,
|
||||
.print = file_obj_print,
|
||||
.make_new = file_obj_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &fileio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
|
||||
@ -283,7 +283,7 @@ const mp_obj_type_t mp_type_textio = {
|
||||
.name = MP_QSTR_TextIOWrapper,
|
||||
.print = file_obj_print,
|
||||
.make_new = file_obj_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &textio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
|
||||
|
@ -1806,6 +1806,7 @@ STATIC void emit_native_get_iter(emit_t *emit) {
|
||||
vtype_kind_t vtype;
|
||||
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
|
||||
assert(vtype == VTYPE_PYOBJ);
|
||||
assert(0); // TODO allocate memory for iter_buf
|
||||
emit_call(emit, MP_F_GETITER);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
|
@ -117,7 +117,8 @@ STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) {
|
||||
mp_obj_t iterable = mp_getiter(o_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(o_in, &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (!mp_obj_is_true(item)) {
|
||||
@ -129,7 +130,8 @@ STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) {
|
||||
mp_obj_t iterable = mp_getiter(o_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(o_in, &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (mp_obj_is_true(item)) {
|
||||
@ -258,7 +260,7 @@ STATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
|
||||
return mp_getiter(o_in);
|
||||
return mp_getiter(o_in, NULL);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
|
||||
|
||||
@ -270,7 +272,8 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t
|
||||
mp_obj_t key_fn = key_elem == NULL ? MP_OBJ_NULL : key_elem->value;
|
||||
if (n_args == 1) {
|
||||
// given an iterable
|
||||
mp_obj_t iterable = mp_getiter(args[0]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
|
||||
mp_obj_t best_key = MP_OBJ_NULL;
|
||||
mp_obj_t best_obj = MP_OBJ_NULL;
|
||||
mp_obj_t item;
|
||||
@ -495,7 +498,8 @@ STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {
|
||||
case 1: value = MP_OBJ_NEW_SMALL_INT(0); break;
|
||||
default: value = args[1]; break;
|
||||
}
|
||||
mp_obj_t iterable = mp_getiter(args[0]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
value = mp_binary_op(MP_BINARY_OP_ADD, value, item);
|
||||
|
5
py/obj.c
5
py/obj.c
@ -481,6 +481,11 @@ mp_obj_t mp_identity(mp_obj_t self) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
|
||||
|
||||
mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) {
|
||||
(void)iter_buf;
|
||||
return self;
|
||||
}
|
||||
|
||||
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
mp_obj_type_t *type = mp_obj_get_type(obj);
|
||||
if (type->buffer_p.get_buffer == NULL) {
|
||||
|
15
py/obj.h
15
py/obj.h
@ -417,6 +417,11 @@ typedef enum {
|
||||
PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses
|
||||
} mp_print_kind_t;
|
||||
|
||||
typedef struct _mp_obj_iter_buf_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t buf[3];
|
||||
} mp_obj_iter_buf_t;
|
||||
|
||||
typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
|
||||
typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
@ -424,6 +429,7 @@ typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t);
|
||||
typedef mp_obj_t (*mp_binary_op_fun_t)(mp_uint_t op, mp_obj_t, mp_obj_t);
|
||||
typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
|
||||
typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
|
||||
typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);
|
||||
|
||||
// Buffer protocol
|
||||
typedef struct _mp_buffer_info_t {
|
||||
@ -486,7 +492,11 @@ struct _mp_obj_type_t {
|
||||
// value=MP_OBJ_NULL means delete, value=MP_OBJ_SENTINEL means load, else store
|
||||
// can return MP_OBJ_NULL if op not supported
|
||||
|
||||
mp_fun_1_t getiter; // corresponds to __iter__ special method
|
||||
// corresponds to __iter__ special method
|
||||
// can use given mp_obj_iter_buf_t to store iterator
|
||||
// otherwise can return a pointer to an object on the heap
|
||||
mp_getiter_fun_t getiter;
|
||||
|
||||
mp_fun_1_t iternext; // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() (with no args)
|
||||
|
||||
mp_buffer_p_t buffer_p;
|
||||
@ -637,7 +647,7 @@ mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);
|
||||
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
|
||||
mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj);
|
||||
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
|
||||
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args);
|
||||
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf);
|
||||
mp_obj_t mp_obj_new_module(qstr module_name);
|
||||
mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items);
|
||||
|
||||
@ -775,6 +785,7 @@ qstr mp_obj_code_get_name(const byte *code_info);
|
||||
|
||||
mp_obj_t mp_identity(mp_obj_t self);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj);
|
||||
mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf);
|
||||
|
||||
// module
|
||||
typedef struct _mp_obj_module_t {
|
||||
|
@ -59,7 +59,7 @@
|
||||
#define TYPECODE_MASK (~(size_t)0)
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in);
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf);
|
||||
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
|
||||
STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in);
|
||||
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
|
||||
@ -141,7 +141,8 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
|
||||
|
||||
mp_obj_array_t *array = array_new(typecode, len);
|
||||
|
||||
mp_obj_t iterable = mp_getiter(initializer);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(initializer, &iter_buf);
|
||||
mp_obj_t item;
|
||||
size_t i = 0;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
@ -608,15 +609,18 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
|
||||
STATIC const mp_obj_type_t array_it_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = array_it_iternext,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in);
|
||||
mp_obj_array_it_t *o = m_new0(mp_obj_array_it_t, 1);
|
||||
mp_obj_array_it_t *o = (mp_obj_array_it_t*)iter_buf;
|
||||
o->base.type = &array_it_type;
|
||||
o->array = array;
|
||||
o->offset = 0;
|
||||
o->cur = 0;
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (array->base.type == &mp_type_memoryview) {
|
||||
o->offset = array->free;
|
||||
|
24
py/objdict.c
24
py/objdict.c
@ -210,8 +210,9 @@ STATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t dict_getiter(mp_obj_t self_in) {
|
||||
mp_obj_dict_it_t *o = m_new_obj(mp_obj_dict_it_t);
|
||||
STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_dict_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_dict_it_t *o = (mp_obj_dict_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = dict_it_iternext;
|
||||
o->dict = self_in;
|
||||
@ -249,7 +250,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
|
||||
|
||||
// this is a classmethod
|
||||
STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_t iter = mp_getiter(args[1]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(args[1], &iter_buf);
|
||||
mp_obj_t value = mp_const_none;
|
||||
mp_obj_t next = MP_OBJ_NULL;
|
||||
|
||||
@ -375,10 +377,12 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
|
||||
}
|
||||
} else {
|
||||
// update from a generic iterable of pairs
|
||||
mp_obj_t iter = mp_getiter(args[1]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(args[1], &iter_buf);
|
||||
mp_obj_t next = MP_OBJ_NULL;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
mp_obj_t inneriter = mp_getiter(next);
|
||||
mp_obj_iter_buf_t inner_iter_buf;
|
||||
mp_obj_t inneriter = mp_getiter(next, &inner_iter_buf);
|
||||
mp_obj_t key = mp_iternext(inneriter);
|
||||
mp_obj_t value = mp_iternext(inneriter);
|
||||
mp_obj_t stop = mp_iternext(inneriter);
|
||||
@ -457,14 +461,15 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
|
||||
STATIC const mp_obj_type_t dict_view_it_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = dict_view_it_iternext,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
|
||||
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_check_self(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
|
||||
mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);
|
||||
mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
|
||||
mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf;
|
||||
o->base.type = &dict_view_it_type;
|
||||
o->kind = view->kind;
|
||||
o->dict = view->dict;
|
||||
@ -479,7 +484,8 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
|
||||
bool first = true;
|
||||
mp_print_str(print, mp_dict_view_names[self->kind]);
|
||||
mp_print_str(print, "([");
|
||||
mp_obj_t self_iter = dict_view_getiter(self_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t self_iter = dict_view_getiter(self_in, &iter_buf);
|
||||
mp_obj_t next = MP_OBJ_NULL;
|
||||
while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (!first) {
|
||||
|
@ -56,13 +56,13 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
||||
// create enumerate object
|
||||
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
|
||||
o->base.type = type;
|
||||
o->iter = mp_getiter(arg_vals.iterable.u_obj);
|
||||
o->iter = mp_getiter(arg_vals.iterable.u_obj, NULL);
|
||||
o->cur = arg_vals.start.u_int;
|
||||
#else
|
||||
(void)n_kw;
|
||||
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
|
||||
o->base.type = type;
|
||||
o->iter = mp_getiter(args[0]);
|
||||
o->iter = mp_getiter(args[0], NULL);
|
||||
o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0;
|
||||
#endif
|
||||
|
||||
@ -74,7 +74,7 @@ const mp_obj_type_t mp_type_enumerate = {
|
||||
.name = MP_QSTR_enumerate,
|
||||
.make_new = enumerate_make_new,
|
||||
.iternext = enumerate_iternext,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) {
|
||||
|
@ -39,7 +39,7 @@ STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
||||
mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);
|
||||
o->base.type = type;
|
||||
o->fun = args[0];
|
||||
o->iter = mp_getiter(args[1]);
|
||||
o->iter = mp_getiter(args[1], NULL);
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ const mp_obj_type_t mp_type_filter = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_filter,
|
||||
.make_new = filter_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = filter_iternext,
|
||||
};
|
||||
|
||||
|
@ -236,7 +236,7 @@ const mp_obj_type_t mp_type_gen_instance = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_generator,
|
||||
.print = gen_instance_print,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = gen_instance_iternext,
|
||||
.locals_dict = (mp_obj_dict_t*)&gen_instance_locals_dict,
|
||||
};
|
||||
|
@ -61,13 +61,14 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
|
||||
STATIC const mp_obj_type_t it_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = it_iternext,
|
||||
};
|
||||
|
||||
// args are those returned from mp_load_method_maybe (ie either an attribute or a method)
|
||||
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args) {
|
||||
mp_obj_getitem_iter_t *o = m_new_obj(mp_obj_getitem_iter_t);
|
||||
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_getitem_iter_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_getitem_iter_t *o = (mp_obj_getitem_iter_t*)iter_buf;
|
||||
o->base.type = &it_type;
|
||||
o->args[0] = args[0];
|
||||
o->args[1] = args[1];
|
||||
|
14
py/objlist.c
14
py/objlist.c
@ -33,7 +33,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/stackctrl.h"
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur);
|
||||
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf);
|
||||
STATIC mp_obj_list_t *list_new(size_t n);
|
||||
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);
|
||||
STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args);
|
||||
@ -60,7 +60,8 @@ STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k
|
||||
}
|
||||
|
||||
STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
|
||||
mp_obj_t iter = mp_getiter(iterable);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(iterable, &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
mp_obj_list_append(list, item);
|
||||
@ -225,8 +226,8 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
|
||||
return mp_obj_new_list_iterator(o_in, 0);
|
||||
STATIC mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
return mp_obj_new_list_iterator(o_in, 0, iter_buf);
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
|
||||
@ -516,8 +517,9 @@ STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur) {
|
||||
mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t);
|
||||
mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_list_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_list_it_t *o = (mp_obj_list_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = list_it_iternext;
|
||||
o->list = list;
|
||||
|
@ -43,7 +43,7 @@ STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
||||
o->n_iters = n_args - 1;
|
||||
o->fun = args[0];
|
||||
for (mp_uint_t i = 0; i < n_args - 1; i++) {
|
||||
o->iters[i] = mp_getiter(args[i + 1]);
|
||||
o->iters[i] = mp_getiter(args[i + 1], NULL);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
@ -68,6 +68,6 @@ const mp_obj_type_t mp_type_map = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_map,
|
||||
.make_new = map_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = map_iternext,
|
||||
};
|
||||
|
@ -49,6 +49,6 @@ STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) {
|
||||
const mp_obj_type_t mp_type_polymorph_iter = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = polymorph_it_iternext,
|
||||
};
|
||||
|
@ -55,12 +55,13 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
|
||||
STATIC const mp_obj_type_t range_it_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = range_it_iternext,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step) {
|
||||
mp_obj_range_it_t *o = m_new_obj(mp_obj_range_it_t);
|
||||
STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_range_it_t *o = (mp_obj_range_it_t*)iter_buf;
|
||||
o->base.type = &range_it_type;
|
||||
o->cur = cur;
|
||||
o->stop = stop;
|
||||
@ -161,9 +162,9 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t range_getiter(mp_obj_t o_in) {
|
||||
STATIC mp_obj_t range_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
return mp_obj_new_range_iterator(o->start, o->stop, o->step);
|
||||
return mp_obj_new_range_iterator(o->start, o->stop, o->step, iter_buf);
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,7 +74,7 @@ const mp_obj_type_t mp_type_reversed = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_reversed,
|
||||
.make_new = reversed_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = reversed_iternext,
|
||||
};
|
||||
|
||||
|
26
py/objset.c
26
py/objset.c
@ -129,7 +129,8 @@ STATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
||||
default: { // can only be 0 or 1 arg
|
||||
// 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 = mp_getiter(args[0]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
mp_obj_set_store(set, item);
|
||||
@ -156,8 +157,9 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
|
||||
mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t);
|
||||
STATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_set_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_set_it_t *o = (mp_obj_set_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = set_it_iternext;
|
||||
o->set = (mp_obj_set_t *)MP_OBJ_TO_PTR(set_in);
|
||||
@ -233,7 +235,8 @@ STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) {
|
||||
if (self == other) {
|
||||
set_clear(self);
|
||||
} else {
|
||||
mp_obj_t iter = mp_getiter(other);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(other, &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
set_discard(self, next);
|
||||
@ -270,7 +273,8 @@ STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update)
|
||||
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_set_t *out = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL));
|
||||
|
||||
mp_obj_t iter = mp_getiter(other);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(other, &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
|
||||
@ -302,7 +306,8 @@ STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
|
||||
check_set_or_frozenset(self_in);
|
||||
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
mp_obj_t iter = mp_getiter(other);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(other, &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
|
||||
@ -335,7 +340,8 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
|
||||
if (proper && self->set.used == other->set.used) {
|
||||
out = false;
|
||||
} else {
|
||||
mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self));
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self), &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
|
||||
@ -408,7 +414,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
|
||||
STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
|
||||
check_set(self_in);
|
||||
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t iter = mp_getiter(other_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(other_in, &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND);
|
||||
@ -427,7 +434,8 @@ STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
|
||||
|
||||
STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
|
||||
mp_obj_t iter = mp_getiter(other_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(other_in, &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
|
17
py/objstr.c
17
py/objstr.c
@ -38,7 +38,7 @@
|
||||
|
||||
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict);
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
|
||||
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
|
||||
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
|
||||
|
||||
/******************************************************************************/
|
||||
@ -231,7 +231,8 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
|
||||
vstr_init(&vstr, len);
|
||||
}
|
||||
|
||||
mp_obj_t iterable = mp_getiter(args[0]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
mp_int_t val = mp_obj_get_int(item);
|
||||
@ -1942,7 +1943,7 @@ STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = {
|
||||
STATIC MP_DEFINE_CONST_DICT(str8_locals_dict, str8_locals_dict_table);
|
||||
|
||||
#if !MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
|
||||
|
||||
const mp_obj_type_t mp_type_str = {
|
||||
{ &mp_type_type },
|
||||
@ -2142,8 +2143,9 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
|
||||
mp_obj_str8_it_t *o = m_new_obj(mp_obj_str8_it_t);
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = str_it_iternext;
|
||||
o->str = str;
|
||||
@ -2164,8 +2166,9 @@ STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str) {
|
||||
mp_obj_str8_it_t *o = m_new_obj(mp_obj_str8_it_t);
|
||||
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = bytes_it_iternext;
|
||||
o->str = str;
|
||||
|
@ -215,7 +215,7 @@ const mp_obj_type_t mp_type_stringio = {
|
||||
.name = MP_QSTR_StringIO,
|
||||
.print = stringio_print,
|
||||
.make_new = stringio_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &stringio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,
|
||||
@ -227,7 +227,7 @@ const mp_obj_type_t mp_type_bytesio = {
|
||||
.name = MP_QSTR_BytesIO,
|
||||
.print = stringio_print,
|
||||
.make_new = stringio_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &bytesio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
|
||||
|
||||
/******************************************************************************/
|
||||
/* str */
|
||||
@ -301,8 +301,9 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
|
||||
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_str_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_str_it_t *o = (mp_obj_str_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = str_it_iternext;
|
||||
o->str = str;
|
||||
|
@ -32,8 +32,6 @@
|
||||
#include "py/runtime0.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, size_t cur);
|
||||
|
||||
/******************************************************************************/
|
||||
/* tuple */
|
||||
|
||||
@ -84,7 +82,8 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg
|
||||
size_t len = 0;
|
||||
mp_obj_t *items = m_new(mp_obj_t, alloc);
|
||||
|
||||
mp_obj_t iterable = mp_getiter(args[0]);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (len >= alloc) {
|
||||
@ -195,10 +194,6 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in) {
|
||||
return mp_obj_new_tuple_iterator(MP_OBJ_TO_PTR(o_in), 0);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
|
||||
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
@ -284,11 +279,12 @@ STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, size_t cur) {
|
||||
mp_obj_tuple_it_t *o = m_new_obj(mp_obj_tuple_it_t);
|
||||
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(sizeof(mp_obj_tuple_it_t) <= sizeof(mp_obj_iter_buf_t));
|
||||
mp_obj_tuple_it_t *o = (mp_obj_tuple_it_t*)iter_buf;
|
||||
o->base.type = &mp_type_polymorph_iter;
|
||||
o->iternext = tuple_it_iternext;
|
||||
o->tuple = tuple;
|
||||
o->cur = cur;
|
||||
o->tuple = MP_OBJ_TO_PTR(o_in);
|
||||
o->cur = 0;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
|
||||
mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
|
||||
mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);
|
||||
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in);
|
||||
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf);
|
||||
|
||||
extern const mp_obj_type_t mp_type_attrtuple;
|
||||
|
||||
|
@ -758,7 +758,7 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons
|
||||
return mp_call_method_self_n_kw(member[0], member[1], n_args, n_kw, args);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t member[2] = {MP_OBJ_NULL};
|
||||
struct class_lookup_data lookup = {
|
||||
@ -773,7 +773,7 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
|
||||
return MP_OBJ_NULL;
|
||||
} else if (member[0] == MP_OBJ_SENTINEL) {
|
||||
mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);
|
||||
return type->getiter(self->subobj[0]);
|
||||
return type->getiter(self->subobj[0], iter_buf);
|
||||
} else {
|
||||
return mp_call_method_n_kw(0, 0, member);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
||||
o->base.type = type;
|
||||
o->n_iters = n_args;
|
||||
for (mp_uint_t i = 0; i < n_args; i++) {
|
||||
o->iters[i] = mp_getiter(args[i]);
|
||||
o->iters[i] = mp_getiter(args[i], NULL);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
@ -71,6 +71,6 @@ const mp_obj_type_t mp_type_zip = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_zip,
|
||||
.make_new = zip_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = zip_iternext,
|
||||
};
|
||||
|
26
py/runtime.c
26
py/runtime.c
@ -520,7 +520,8 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
}
|
||||
if (type->getiter != NULL) {
|
||||
/* second attempt, walk the iterator */
|
||||
mp_obj_t iter = mp_getiter(rhs);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iter = mp_getiter(rhs, &iter_buf);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (mp_obj_equal(next, lhs)) {
|
||||
@ -698,7 +699,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
|
||||
args2_len += n_args;
|
||||
|
||||
// extract the variable position args from the iterator
|
||||
mp_obj_t iterable = mp_getiter(pos_seq);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(pos_seq, &iter_buf);
|
||||
mp_obj_t item;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (args2_len >= args2_alloc) {
|
||||
@ -743,7 +745,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
|
||||
// get the keys iterable
|
||||
mp_obj_t dest[3];
|
||||
mp_load_method(kw_dict, MP_QSTR_keys, dest);
|
||||
mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest));
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest), &iter_buf);
|
||||
|
||||
mp_obj_t key;
|
||||
while ((key = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
@ -809,7 +812,8 @@ void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
|
||||
items[i] = seq_items[num - 1 - i];
|
||||
}
|
||||
} else {
|
||||
mp_obj_t iterable = mp_getiter(seq_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(seq_in, &iter_buf);
|
||||
|
||||
for (seq_len = 0; seq_len < num; seq_len++) {
|
||||
mp_obj_t el = mp_iternext(iterable);
|
||||
@ -873,7 +877,8 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
|
||||
// items destination array, then the rest to a dynamically created list. Once the
|
||||
// iterable is exhausted, we take from this list for the right part of the items.
|
||||
// TODO Improve to waste less memory in the dynamically created list.
|
||||
mp_obj_t iterable = mp_getiter(seq_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(seq_in, &iter_buf);
|
||||
mp_obj_t item;
|
||||
for (seq_len = 0; seq_len < num_left; seq_len++) {
|
||||
item = mp_iternext(iterable);
|
||||
@ -1096,13 +1101,18 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t mp_getiter(mp_obj_t o_in) {
|
||||
mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
assert(o_in);
|
||||
|
||||
// if caller did not provide a buffer then allocate one on the heap
|
||||
if (iter_buf == NULL) {
|
||||
iter_buf = m_new_obj(mp_obj_iter_buf_t);
|
||||
}
|
||||
|
||||
// check for native getiter (corresponds to __iter__)
|
||||
mp_obj_type_t *type = mp_obj_get_type(o_in);
|
||||
if (type->getiter != NULL) {
|
||||
mp_obj_t iter = type->getiter(o_in);
|
||||
mp_obj_t iter = type->getiter(o_in, iter_buf);
|
||||
if (iter != MP_OBJ_NULL) {
|
||||
return iter;
|
||||
}
|
||||
@ -1113,7 +1123,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in) {
|
||||
mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
|
||||
if (dest[0] != MP_OBJ_NULL) {
|
||||
// __getitem__ exists, create and return an iterator
|
||||
return mp_obj_new_getitem_iter(dest);
|
||||
return mp_obj_new_getitem_iter(dest, iter_buf);
|
||||
}
|
||||
|
||||
// object not iterable
|
||||
|
@ -123,7 +123,7 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
|
||||
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
|
||||
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
|
||||
|
||||
mp_obj_t mp_getiter(mp_obj_t o);
|
||||
mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf);
|
||||
mp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_STOP_ITERATION instead of raising StopIteration()
|
||||
mp_obj_t mp_iternext(mp_obj_t o); // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration(...)
|
||||
mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val);
|
||||
|
2
py/vm.c
2
py/vm.c
@ -723,7 +723,7 @@ unwind_jump:;
|
||||
|
||||
ENTRY(MP_BC_GET_ITER):
|
||||
MARK_EXC_IP_SELECTIVE();
|
||||
SET_TOP(mp_getiter(TOP()));
|
||||
SET_TOP(mp_getiter(TOP(), NULL));
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_FOR_ITER): {
|
||||
|
@ -120,7 +120,7 @@ STATIC const mp_obj_type_t stdio_obj_type = {
|
||||
.name = MP_QSTR_FileIO,
|
||||
// TODO .make_new?
|
||||
.print = stdio_obj_print,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &stdio_obj_stream_p,
|
||||
.locals_dict = (mp_obj_t)&stdio_locals_dict,
|
||||
@ -153,7 +153,7 @@ STATIC const mp_obj_type_t stdio_buffer_obj_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_FileIO,
|
||||
.print = stdio_obj_print,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &stdio_buffer_obj_stream_p,
|
||||
.locals_dict = (mp_obj_t)&stdio_locals_dict,
|
||||
|
@ -1037,7 +1037,7 @@ const mp_obj_type_t pyb_uart_type = {
|
||||
.name = MP_QSTR_UART,
|
||||
.print = pyb_uart_print,
|
||||
.make_new = pyb_uart_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &uart_stream_p,
|
||||
.locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
|
||||
|
@ -518,7 +518,7 @@ const mp_obj_type_t pyb_usb_vcp_type = {
|
||||
.name = MP_QSTR_USB_VCP,
|
||||
.print = pyb_usb_vcp_print,
|
||||
.make_new = pyb_usb_vcp_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &pyb_usb_vcp_stream_p,
|
||||
.locals_dict = (mp_obj_t)&pyb_usb_vcp_locals_dict,
|
||||
|
@ -244,7 +244,7 @@ const mp_obj_type_t mp_type_fileio = {
|
||||
.name = MP_QSTR_FileIO,
|
||||
.print = fdfile_print,
|
||||
.make_new = fdfile_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &fileio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
|
||||
@ -263,7 +263,7 @@ const mp_obj_type_t mp_type_textio = {
|
||||
.name = MP_QSTR_TextIOWrapper,
|
||||
.print = fdfile_print,
|
||||
.make_new = fdfile_make_new,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &textio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
|
||||
|
@ -194,7 +194,8 @@ STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in)
|
||||
o->rettype = *rettype;
|
||||
o->argtypes = argtypes;
|
||||
|
||||
mp_obj_t iterable = mp_getiter(argtypes_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(argtypes_in, &iter_buf);
|
||||
mp_obj_t item;
|
||||
int i = 0;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
@ -251,7 +252,8 @@ STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t
|
||||
|
||||
o->rettype = *rettype;
|
||||
|
||||
mp_obj_t iterable = mp_getiter(paramtypes_in);
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(paramtypes_in, &iter_buf);
|
||||
mp_obj_t item;
|
||||
int i = 0;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
|
@ -288,7 +288,7 @@ STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
|
||||
STATIC const mp_obj_type_t mp_type_poll = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_poll,
|
||||
.getiter = mp_identity,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = poll_iternext,
|
||||
.locals_dict = (void*)&poll_locals_dict,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user