STATIC mp_obj_t dict_update(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { assert(MP_OBJ_IS_TYPE(args[0], &mp_type_dict)); mp_obj_dict_t *self = args[0]; mp_arg_check_num(n_args, kwargs->used, 1, 2, true); if (n_args == 2) { // given a positional argument if (MP_OBJ_IS_TYPE(args[1], &mp_type_dict)) { // update from other dictionary (make sure other is not self) if (args[1] != self) { // TODO don't allocate heap object for this iterator mp_obj_t *dict_iter = mp_obj_new_dict_iterator(args[1], 0); mp_map_elem_t *elem = NULL; while ((elem = dict_it_iternext_elem(dict_iter)) != MP_OBJ_STOP_ITERATION) { mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value; } } } else { // update from a generic iterable of pairs mp_obj_t iter = mp_getiter(args[1]); mp_obj_t next = NULL; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t inneriter = mp_getiter(next); mp_obj_t key = mp_iternext(inneriter); mp_obj_t value = mp_iternext(inneriter); mp_obj_t stop = mp_iternext(inneriter); if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception_msg( &mp_type_ValueError, "dictionary update sequence has the wrong length")); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } } } } // update the dict with any keyword args for (mp_uint_t i = 0; i < kwargs->alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value; } } return mp_const_none; }
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_check_self(mp_obj_is_dict_type(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); mp_ensure_not_fixed(self); mp_arg_check_num(n_args, kwargs->used, 1, 2, true); if (n_args == 2) { // given a positional argument if (mp_obj_is_dict_type(args[1])) { // update from other dictionary (make sure other is not self) if (args[1] != args[0]) { size_t cur = 0; mp_map_elem_t *elem = NULL; while ((elem = dict_iter_next((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) { mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value; } } } else { // update from a generic iterable of pairs mp_obj_t iter = mp_getiter(args[1], NULL); mp_obj_t next = MP_OBJ_NULL; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t inneriter = mp_getiter(next, NULL); mp_obj_t key = mp_iternext(inneriter); mp_obj_t value = mp_iternext(inneriter); mp_obj_t stop = mp_iternext(inneriter); if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { mp_raise_ValueError("dict update sequence has wrong length"); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } } } } // update the dict with any keyword args for (size_t i = 0; i < kwargs->alloc; i++) { if (mp_map_slot_is_filled(kwargs, i)) { mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value; } } return mp_const_none; }
STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) { if (update) { check_set(self_in); } else { check_set_or_frozenset(self_in); } if (self_in == other) { return update ? mp_const_none : set_copy(self_in); } 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, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { set_add(MP_OBJ_FROM_PTR(out), next); } } if (update) { m_del(mp_obj_t, self->set.table, self->set.alloc); self->set.alloc = out->set.alloc; self->set.used = out->set.used; self->set.table = out->set.table; } return update ? mp_const_none : MP_OBJ_FROM_PTR(out); }
STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { mp_obj_t self; if (update) { check_set(args[0]); self = args[0]; } else { self = set_copy(args[0]); } for (size_t i = 1; i < n_args; i++) { mp_obj_t other = args[i]; if (self == other) { set_clear(self); } else { mp_set_t *self_set = &((mp_obj_set_t*)MP_OBJ_TO_PTR(self))->set; mp_obj_t iter = mp_getiter(other, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_set_lookup(self_set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND); } } } return self; }
STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) { if (n_args == 1) { // given an iterable mp_obj_t iterable = mp_getiter(args[0]); mp_obj_t min_obj = NULL; mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (min_obj == NULL || (mp_binary_op(MP_BINARY_OP_LESS, item, min_obj) == mp_const_true)) { min_obj = item; } } if (min_obj == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "min() arg is an empty sequence")); } return min_obj; } else { // given many args mp_obj_t min_obj = args[0]; for (int i = 1; i < n_args; i++) { if (mp_binary_op(MP_BINARY_OP_LESS, args[i], min_obj) == mp_const_true) { min_obj = args[i]; } } return min_obj; } }
// this is a classmethod STATIC mp_obj_t dict_fromkeys(uint n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 3); mp_obj_t iter = mp_getiter(args[1]); mp_obj_t len = mp_obj_len_maybe(iter); mp_obj_t value = mp_const_none; mp_obj_t next = NULL; mp_obj_dict_t *self = NULL; if (n_args > 2) { value = args[2]; } if (len == MP_OBJ_NULL) { /* object's type doesn't have a __len__ slot */ self = mp_obj_new_dict(0); } else { self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len)); } while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } return self; }
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_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } }
// 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], NULL); mp_obj_t value = mp_const_none; mp_obj_t next = MP_OBJ_NULL; if (n_args > 2) { value = args[2]; } // optimisation to allocate result based on len of argument mp_obj_t self_out; mp_obj_t len = mp_obj_len_maybe(args[1]); if (len == MP_OBJ_NULL) { /* object's type doesn't have a __len__ slot */ self_out = mp_obj_new_dict(0); } else { self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len)); } mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out); while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } return self_out; }
STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t paramtypes_in) { const char *rettype = mp_obj_str_get_str(rettype_in); int nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(paramtypes_in)); mp_obj_fficallback_t *o = m_new_obj_var(mp_obj_fficallback_t, ffi_type*, nparams); o->base.type = &fficallback_type; o->clo = ffi_closure_alloc(sizeof(ffi_closure), &o->func); o->rettype = *rettype; mp_obj_t iterable = mp_getiter(paramtypes_in); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { o->params[i++] = get_ffi_type(item); } int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Error in ffi_prep_cif")); } res = ffi_prep_closure_loc(o->clo, &o->cif, call_py_func, func_in, o->func); if (res != FFI_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ffi_prep_closure_loc")); } return o; }
STATIC mp_obj_t ffimod_func(mp_uint_t n_args, const mp_obj_t *args) { mp_obj_ffimod_t *self = args[0]; const char *rettype = mp_obj_str_get_str(args[1]); const char *symname = mp_obj_str_get_str(args[2]); void *sym = dlsym(self->handle, symname); if (sym == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno))); } int nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(args[3])); mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type*, nparams); o->base.type = &ffifunc_type; o->func = sym; o->rettype = *rettype; mp_obj_t iterable = mp_getiter(args[3]); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { o->params[i++] = get_ffi_type(item); } int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Error in ffi_prep_cif")); } return o; }
STATIC mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) { assert(n_args > 0); assert(MP_OBJ_IS_TYPE(args[0], &mp_type_set)); mp_obj_set_t *self; if (update) { self = args[0]; } else { self = set_copy(args[0]); } for (int i = 1; i < n_args; i++) { mp_obj_t other = args[i]; if (self == other) { set_clear(self); } else { mp_obj_t iter = mp_getiter(other); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { set_discard(self, next); } } } return self; }
STATIC mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) { assert(n_args > 0); mp_obj_set_t *self; if (update) { check_set(args[0]); self = args[0]; } else { check_set_or_frozenset(args[0]); self = set_copy_as_mutable(args[0]); } for (int i = 1; i < n_args; i++) { mp_obj_t other = args[i]; if (self == other) { set_clear(self); } else { mp_obj_t iter = mp_getiter(other); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { set_discard(self, next); } } } self->base.type = ((mp_obj_set_t*)args[0])->base.type; return self; }
STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) { const char *rettype = mp_obj_str_get_str(rettype_in); const char *argtypes = mp_obj_str_get_str(argtypes_in); mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(argtypes_in)); mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type*, nparams); o->base.type = &ffifunc_type; o->func = func; o->rettype = *rettype; o->argtypes = argtypes; 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) { o->params[i++] = get_ffi_type(item); } int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Error in ffi_prep_cif")); } return MP_OBJ_FROM_PTR(o); }
STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: { // create a new, empty set mp_obj_set_t *set = mp_obj_new_set(0, NULL); // set actual set/frozenset type set->base.type = type_in; return set; } case 1: default: { // can only be 0 or 1 arg // 1 argument, an iterable from which we make a new set mp_obj_set_t *set = mp_obj_new_set(0, NULL); mp_obj_t iterable = mp_getiter(args[0]); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { mp_obj_set_store(set, item); } // Set actual set/frozenset type set->base.type = type_in; return set; } } }
STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { uint len; // Try to create array of exact len if initializer len is known mp_obj_t len_in = mp_obj_len_maybe(initializer); if (len_in == MP_OBJ_NULL) { len = 0; } else { len = MP_OBJ_SMALL_INT_VALUE(len_in); } mp_obj_array_t *array = array_new(typecode, len); mp_obj_t iterable = mp_getiter(initializer); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (len == 0) { array_append(array, item); } else { mp_binary_set_val_array(typecode, array->items, i++, item); } } return array; }
STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // TODO check n_kw == 0 switch (n_args) { case 0: // return a new, empty list return mp_obj_new_list(0, NULL); case 1: { // make list from iterable mp_obj_t iterable = mp_getiter(args[0]); mp_obj_t list = mp_obj_new_list(0, NULL); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) { mp_obj_list_append(list, item); } return list; } default: nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "list takes at most 1 argument, %d given", n_args)); } return NULL; }
STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set)); if (self_in == other) { return update ? mp_const_none : set_copy(self_in); } mp_obj_set_t *self = self_in; mp_obj_set_t *out = mp_obj_new_set(0, NULL); mp_obj_t iter = mp_getiter(other); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { set_add(out, next); } } if (update) { m_del(mp_obj_t, self->set.table, self->set.alloc); self->set.alloc = out->set.alloc; self->set.used = out->set.used; self->set.table = out->set.table; } return update ? mp_const_none : out; }
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_t item; while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_list_append(list, item); } return list; }
// wrapper that handles iterator buffer STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { mp_obj_t obj; if (iter->base.type == MP_OBJ_NULL) { obj = iter->buf[0]; } else { obj = MP_OBJ_FROM_PTR(iter); } return mp_iternext(obj); }
STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { check_set_or_frozenset(self_in); // can be frozenset due to call from set_symmetric_difference mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t iter = mp_getiter(other_in, NULL); 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); } return mp_const_none; }
STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) { mp_obj_t iterable = mp_getiter(o_in); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) { if (!mp_obj_is_true(item)) { return mp_const_false; } } return mp_const_true; }
STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) { mp_obj_t iterable = mp_getiter(o_in); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (mp_obj_is_true(item)) { return mp_const_true; } } return mp_const_false; }
STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set)); mp_obj_set_t *self = self_in; mp_obj_t iter = mp_getiter(other_in); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } return mp_const_none; }
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 = self_in; mp_obj_t iter = mp_getiter(other); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { return mp_const_false; } } return mp_const_true; }
STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set)); mp_obj_set_t *self = self_in; mp_obj_t iter = mp_getiter(other); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { return mp_const_false; } } return mp_const_true; }
STATIC mp_obj_t mp_builtin_sum(uint n_args, const mp_obj_t *args) { assert(1 <= n_args && n_args <= 2); mp_obj_t value; switch (n_args) { case 1: value = mp_obj_new_int(0); break; default: value = args[1]; break; } mp_obj_t iterable = mp_getiter(args[0]); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { value = mp_binary_op(MP_BINARY_OP_ADD, value, item); } return value; }
STATIC mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict)); mp_obj_dict_t *self = self_in; /* TODO: check for the "keys" method */ mp_obj_t iter = mp_getiter(iterable); mp_obj_t next = NULL; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t inneriter = mp_getiter(next); mp_obj_t key = mp_iternext(inneriter); mp_obj_t value = mp_iternext(inneriter); mp_obj_t stop = mp_iternext(inneriter); if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception_msg( &mp_type_ValueError, "dictionary update sequence has the wrong length")); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } } return mp_const_none; }
static void microbit_display_update(void) { async_tick += FIBER_TICK_PERIOD_MS; if (async_tick < async_delay) { return; } async_tick = 0; switch (async_mode) { case ASYNC_MODE_ANIMATION: { if (MP_STATE_PORT(async_data)[0] == NULL || MP_STATE_PORT(async_data)[1] == NULL) { async_stop(); break; } microbit_display_obj_t *display = (microbit_display_obj_t*)MP_STATE_PORT(async_data)[0]; /* WARNING: We are executing in an interrupt handler. * If an exception is raised here, then a reset is the only way to recover. */ mp_obj_t obj = mp_iternext(async_iterator); if (obj == MP_OBJ_STOP_ITERATION) { if (async_repeat_iterable) { async_iterator = mp_getiter(async_repeat_iterable); } else { microbit_display_show(display, BLANK_IMAGE); async_stop(); } } else if (mp_obj_get_type(obj) == µbit_image_type) { microbit_display_show(display, (microbit_image_obj_t *)obj); } else if (MP_OBJ_IS_STR(obj)) { mp_uint_t len; const char *str = mp_obj_str_get_data(obj, &len); if (len == 1) { microbit_display_show(display, microbit_image_for_char(str[0])); } else { async_error = true; async_stop(); } } else { async_error = true; async_stop(); } break; } case ASYNC_MODE_CLEAR: microbit_display_show(µbit_display_obj, BLANK_IMAGE); async_stop(); break; } }
STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_filter)); mp_obj_filter_t *self = self_in; mp_obj_t next; while ((next = mp_iternext(self->iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t val; if (self->fun != mp_const_none) { val = mp_call_function_n_kw(self->fun, 1, 0, &next); } else { val = next; } if (mp_obj_is_true(val)) { return next; } } return MP_OBJ_STOP_ITERATION; }
STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_zip)); mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in); if (self->n_iters == 0) { return MP_OBJ_STOP_ITERATION; } mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->n_iters, NULL)); for (mp_uint_t i = 0; i < self->n_iters; i++) { mp_obj_t next = mp_iternext(self->iters[i]); if (next == MP_OBJ_STOP_ITERATION) { mp_obj_tuple_del(MP_OBJ_FROM_PTR(tuple)); return MP_OBJ_STOP_ITERATION; } tuple->items[i] = next; } return MP_OBJ_FROM_PTR(tuple); }