py: Replace mp_const_stop_iteration object with MP_OBJ_NULL.
This commit is contained in:
parent
688e220d26
commit
66eaf84b8c
14
py/builtin.c
14
py/builtin.c
@ -103,7 +103,7 @@ 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 = rt_getiter(o_in);
|
||||
mp_obj_t item;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (!rt_is_true(item)) {
|
||||
return mp_const_false;
|
||||
}
|
||||
@ -116,7 +116,7 @@ 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 = rt_getiter(o_in);
|
||||
mp_obj_t item;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (rt_is_true(item)) {
|
||||
return mp_const_true;
|
||||
}
|
||||
@ -232,7 +232,7 @@ STATIC mp_obj_t mp_builtin_max(uint n_args, const mp_obj_t *args) {
|
||||
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) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (max_obj == NULL || mp_obj_less(max_obj, item)) {
|
||||
max_obj = item;
|
||||
}
|
||||
@ -261,7 +261,7 @@ STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) {
|
||||
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) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (min_obj == NULL || mp_obj_less(item, min_obj)) {
|
||||
min_obj = item;
|
||||
}
|
||||
@ -285,8 +285,8 @@ STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_min_obj, 1, mp_builtin_min);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_next(mp_obj_t o) {
|
||||
mp_obj_t ret = rt_iternext(o);
|
||||
if (ret == mp_const_stop_iteration) {
|
||||
mp_obj_t ret = rt_iternext_allow_raise(o);
|
||||
if (ret == MP_OBJ_NULL) {
|
||||
nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
|
||||
} else {
|
||||
return ret;
|
||||
@ -362,7 +362,7 @@ STATIC mp_obj_t mp_builtin_sum(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
mp_obj_t iterable = rt_getiter(args[0]);
|
||||
mp_obj_t item;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
value = rt_binary_op(RT_BINARY_OP_ADD, value, item);
|
||||
}
|
||||
return value;
|
||||
|
@ -987,7 +987,7 @@ STATIC void emit_native_for_iter(emit_t *emit, int label) {
|
||||
emit_access_stack(emit, 1, &vtype, REG_ARG_1);
|
||||
assert(vtype == VTYPE_PYOBJ);
|
||||
emit_call(emit, RT_F_ITERNEXT, rt_iternext);
|
||||
ASM_MOV_IMM_TO_REG((machine_uint_t)mp_const_stop_iteration, REG_TEMP1);
|
||||
ASM_MOV_IMM_TO_REG((machine_uint_t)MP_OBJ_NULL, REG_TEMP1);
|
||||
#if N_X64
|
||||
asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
|
||||
asm_x64_jcc_label(emit->as, JCC_JE, label);
|
||||
|
3
py/obj.h
3
py/obj.h
@ -152,7 +152,7 @@ struct _mp_obj_type_t {
|
||||
mp_store_item_fun_t store_item;
|
||||
|
||||
mp_fun_1_t getiter;
|
||||
mp_fun_1_t iternext;
|
||||
mp_fun_1_t iternext; // may return MP_OBJ_NULL as an optimisation instead of raising StopIteration() (with no args)
|
||||
|
||||
// Alternatively, pointer(s) to interfaces to save space
|
||||
// in mp_obj_type_t at the expense of extra pointer and extra dereference
|
||||
@ -221,7 +221,6 @@ extern const mp_obj_t mp_const_false;
|
||||
extern const mp_obj_t mp_const_true;
|
||||
extern const mp_obj_t mp_const_empty_tuple;
|
||||
extern const mp_obj_t mp_const_ellipsis;
|
||||
extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!)
|
||||
|
||||
// General API for objects
|
||||
|
||||
|
@ -64,7 +64,7 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
|
||||
mp_obj_t iterable = rt_getiter(initializer);
|
||||
mp_obj_t item;
|
||||
int i = 0;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (len == 0) {
|
||||
array_append(array, item);
|
||||
} else {
|
||||
@ -212,7 +212,7 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
|
||||
if (self->cur < self->array->len) {
|
||||
return mp_binary_get_val(self->array->typecode, self->array->items, self->cur++);
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
16
py/objdict.c
16
py/objdict.c
@ -106,7 +106,7 @@ mp_obj_t dict_it_iternext(mp_obj_t self_in) {
|
||||
if (next != NULL) {
|
||||
return next->key;
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ STATIC mp_obj_t dict_fromkeys(uint n_args, const mp_obj_t *args) {
|
||||
self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
|
||||
}
|
||||
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
}
|
||||
|
||||
@ -266,14 +266,14 @@ STATIC mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
|
||||
/* TODO: check for the "keys" method */
|
||||
mp_obj_t iter = rt_getiter(iterable);
|
||||
mp_obj_t next = NULL;
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
mp_obj_t inneriter = rt_getiter(next);
|
||||
mp_obj_t key = rt_iternext(inneriter);
|
||||
mp_obj_t value = rt_iternext(inneriter);
|
||||
mp_obj_t stop = rt_iternext(inneriter);
|
||||
if (key == mp_const_stop_iteration
|
||||
|| value == mp_const_stop_iteration
|
||||
|| stop != mp_const_stop_iteration) {
|
||||
if (key == MP_OBJ_NULL
|
||||
|| value == MP_OBJ_NULL
|
||||
|| stop != MP_OBJ_NULL) {
|
||||
nlr_jump(mp_obj_new_exception_msg(
|
||||
&mp_type_ValueError,
|
||||
"dictionary update sequence has the wrong length"));
|
||||
@ -335,7 +335,7 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
|
||||
return mp_const_none;
|
||||
}
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +364,7 @@ STATIC void dict_view_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
print(env, "([");
|
||||
mp_obj_t *self_iter = dict_view_getiter(self);
|
||||
mp_obj_t *next = NULL;
|
||||
while ((next = dict_view_it_iternext(self_iter)) != mp_const_stop_iteration) {
|
||||
while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_NULL) {
|
||||
if (!first) {
|
||||
print(env, ", ");
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
@ -37,8 +38,8 @@ STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &enumerate_type));
|
||||
mp_obj_enumerate_t *self = self_in;
|
||||
mp_obj_t next = rt_iternext(self->iter);
|
||||
if (next == mp_const_stop_iteration) {
|
||||
return mp_const_stop_iteration;
|
||||
if (next == MP_OBJ_NULL) {
|
||||
return MP_OBJ_NULL;
|
||||
} else {
|
||||
mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(self->cur++), next};
|
||||
return mp_obj_new_tuple(2, items);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nlr.h"
|
||||
@ -29,7 +30,7 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &filter_type));
|
||||
mp_obj_filter_t *self = self_in;
|
||||
mp_obj_t next;
|
||||
while ((next = rt_iternext(self->iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(self->iter)) != MP_OBJ_NULL) {
|
||||
mp_obj_t val;
|
||||
if (self->fun != mp_const_none) {
|
||||
val = rt_call_function_n_kw(self->fun, 1, 0, &next);
|
||||
@ -40,7 +41,7 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
const mp_obj_type_t filter_type = {
|
||||
|
@ -78,7 +78,7 @@ mp_obj_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw
|
||||
mp_obj_gen_instance_t *self = self_in;
|
||||
if (self->ip == 0) {
|
||||
*ret_kind = MP_VM_RETURN_NORMAL;
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
if (self->sp == self->state - 1) {
|
||||
if (send_value != mp_const_none) {
|
||||
@ -122,7 +122,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
|
||||
case MP_VM_RETURN_NORMAL:
|
||||
// Optimize return w/o value in case generator is used in for loop
|
||||
if (ret == mp_const_none) {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
} else {
|
||||
nlr_jump(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret));
|
||||
}
|
||||
@ -145,7 +145,7 @@ mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
|
||||
|
||||
STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) {
|
||||
mp_obj_t ret = gen_resume_and_raise(self_in, send_value, MP_OBJ_NULL);
|
||||
if (ret == mp_const_stop_iteration) {
|
||||
if (ret == MP_OBJ_NULL) {
|
||||
nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
|
||||
} else {
|
||||
return ret;
|
||||
@ -156,7 +156,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send);
|
||||
|
||||
STATIC mp_obj_t gen_instance_throw(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_t ret = gen_resume_and_raise(args[0], mp_const_none, n_args == 2 ? args[1] : args[2]);
|
||||
if (ret == mp_const_stop_iteration) {
|
||||
if (ret == MP_OBJ_NULL) {
|
||||
nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
|
||||
} else {
|
||||
return ret;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@ -25,8 +26,8 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
|
||||
} else {
|
||||
// an exception was raised
|
||||
if (mp_obj_get_type(nlr.ret_val) == &mp_type_StopIteration) {
|
||||
// return mp_const_stop_iteration instead of raising StopIteration
|
||||
return mp_const_stop_iteration;
|
||||
// return MP_OBJ_NULL instead of raising StopIteration
|
||||
return MP_OBJ_NULL;
|
||||
} else {
|
||||
// re-raise exception
|
||||
nlr_jump(nlr.ret_val);
|
||||
|
@ -53,7 +53,7 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
|
||||
mp_obj_t iterable = rt_getiter(args[0]);
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
mp_obj_t item;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
mp_obj_list_append(list, item);
|
||||
}
|
||||
return list;
|
||||
@ -401,7 +401,7 @@ mp_obj_t list_it_iternext(mp_obj_t self_in) {
|
||||
self->cur += 1;
|
||||
return o_out;
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nlr.h"
|
||||
@ -40,9 +41,9 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) {
|
||||
|
||||
for (int i = 0; i < self->n_iters; i++) {
|
||||
mp_obj_t next = rt_iternext(self->iters[i]);
|
||||
if (next == mp_const_stop_iteration) {
|
||||
if (next == MP_OBJ_NULL) {
|
||||
m_del(mp_obj_t, nextses, self->n_iters);
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
nextses[i] = next;
|
||||
}
|
||||
|
@ -31,8 +31,3 @@ const mp_obj_type_t none_type = {
|
||||
|
||||
STATIC const mp_obj_none_t none_obj = {{&none_type}};
|
||||
const mp_obj_t mp_const_none = (mp_obj_t)&none_obj;
|
||||
|
||||
// the stop-iteration object just needs to be something unique
|
||||
// it's not the StopIteration exception
|
||||
STATIC const mp_obj_none_t stop_it_obj = {{&none_type}};
|
||||
const mp_obj_t mp_const_stop_iteration = (mp_obj_t)&stop_it_obj;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@ -55,7 +56,7 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
|
||||
o->cur += o->step;
|
||||
return o_out;
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
16
py/objset.c
16
py/objset.c
@ -59,7 +59,7 @@ STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
|
||||
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) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
mp_obj_set_store(set, item);
|
||||
}
|
||||
return set;
|
||||
@ -89,7 +89,7 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
|
||||
@ -162,7 +162,7 @@ STATIC mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) {
|
||||
} else {
|
||||
mp_obj_t iter = rt_getiter(other);
|
||||
mp_obj_t next;
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
set_discard(self, next);
|
||||
}
|
||||
}
|
||||
@ -193,7 +193,7 @@ STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update)
|
||||
|
||||
mp_obj_t iter = rt_getiter(other);
|
||||
mp_obj_t next;
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
|
||||
set_add(out, next);
|
||||
}
|
||||
@ -225,7 +225,7 @@ STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
|
||||
|
||||
mp_obj_t iter = rt_getiter(other);
|
||||
mp_obj_t next;
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
|
||||
return mp_const_false;
|
||||
}
|
||||
@ -258,7 +258,7 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
|
||||
} else {
|
||||
mp_obj_t iter = set_getiter(self);
|
||||
mp_obj_t next;
|
||||
while ((next = set_it_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = set_it_iternext(iter)) != MP_OBJ_NULL) {
|
||||
if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
|
||||
out = false;
|
||||
break;
|
||||
@ -332,7 +332,7 @@ STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other
|
||||
mp_obj_set_t *self = self_in;
|
||||
mp_obj_t iter = rt_getiter(other_in);
|
||||
mp_obj_t next;
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
}
|
||||
return mp_const_none;
|
||||
@ -350,7 +350,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_dif
|
||||
STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
|
||||
mp_obj_t iter = rt_getiter(other_in);
|
||||
mp_obj_t next;
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
|
||||
|
||||
mp_obj_t iterable = rt_getiter(args[0]);
|
||||
mp_obj_t item;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (len == -1) {
|
||||
vstr_add_char(vstr, MP_OBJ_SMALL_INT_VALUE(item));
|
||||
} else {
|
||||
@ -877,7 +877,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
|
||||
self->cur += 1;
|
||||
return o_out;
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -895,7 +895,7 @@ STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
|
||||
self->cur += 1;
|
||||
return o_out;
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ STATIC mp_obj_t tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
|
||||
|
||||
mp_obj_t iterable = rt_getiter(args[0]);
|
||||
mp_obj_t item;
|
||||
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||
while ((item = rt_iternext(iterable)) != MP_OBJ_NULL) {
|
||||
if (len >= alloc) {
|
||||
items = m_renew(mp_obj_t, items, alloc, alloc * 2);
|
||||
alloc *= 2;
|
||||
@ -245,7 +245,7 @@ STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
|
||||
self->cur += 1;
|
||||
return o_out;
|
||||
} else {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,16 +34,16 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) {
|
||||
mp_obj_zip_t *self = self_in;
|
||||
mp_obj_t *items;
|
||||
if (self->n_iters == 0) {
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
mp_obj_t o = mp_obj_new_tuple(self->n_iters, NULL);
|
||||
mp_obj_tuple_get(o, NULL, &items);
|
||||
|
||||
for (int i = 0; i < self->n_iters; i++) {
|
||||
mp_obj_t next = rt_iternext(self->iters[i]);
|
||||
if (next == mp_const_stop_iteration) {
|
||||
if (next == MP_OBJ_NULL) {
|
||||
mp_obj_tuple_del(o);
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
items[i] = next;
|
||||
}
|
||||
|
40
py/runtime.c
40
py/runtime.c
@ -616,7 +616,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
/* second attempt, walk the iterator */
|
||||
mp_obj_t next = NULL;
|
||||
mp_obj_t iter = rt_getiter(rhs);
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
|
||||
if (mp_obj_equal(next, lhs)) {
|
||||
return mp_const_true;
|
||||
}
|
||||
@ -778,12 +778,12 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
|
||||
|
||||
for (seq_len = 0; seq_len < num; seq_len++) {
|
||||
mp_obj_t el = rt_iternext(iterable);
|
||||
if (el == mp_const_stop_iteration) {
|
||||
if (el == MP_OBJ_NULL) {
|
||||
goto too_short;
|
||||
}
|
||||
items[num - 1 - seq_len] = el;
|
||||
}
|
||||
if (rt_iternext(iterable) != mp_const_stop_iteration) {
|
||||
if (rt_iternext(iterable) != MP_OBJ_NULL) {
|
||||
goto too_long;
|
||||
}
|
||||
}
|
||||
@ -944,7 +944,9 @@ mp_obj_t rt_getiter(mp_obj_t o_in) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t rt_iternext(mp_obj_t o_in) {
|
||||
// may return MP_OBJ_NULL as an optimisation instead of raise StopIteration()
|
||||
// may also raise StopIteration()
|
||||
mp_obj_t rt_iternext_allow_raise(mp_obj_t o_in) {
|
||||
mp_obj_type_t *type = mp_obj_get_type(o_in);
|
||||
if (type->iternext != NULL) {
|
||||
return type->iternext(o_in);
|
||||
@ -961,6 +963,36 @@ mp_obj_t rt_iternext(mp_obj_t o_in) {
|
||||
}
|
||||
}
|
||||
|
||||
// will always return MP_OBJ_NULL instead of raising StopIteration() (or any subclass thereof)
|
||||
// may raise other exceptions
|
||||
mp_obj_t rt_iternext(mp_obj_t o_in) {
|
||||
mp_obj_type_t *type = mp_obj_get_type(o_in);
|
||||
if (type->iternext != NULL) {
|
||||
return type->iternext(o_in);
|
||||
} else {
|
||||
// check for __next__ method
|
||||
mp_obj_t dest[2];
|
||||
rt_load_method_maybe(o_in, MP_QSTR___next__, dest);
|
||||
if (dest[0] != MP_OBJ_NULL) {
|
||||
// __next__ exists, call it and return its result
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_obj_t ret = rt_call_method_n_kw(0, 0, dest);
|
||||
nlr_pop();
|
||||
return ret;
|
||||
} else {
|
||||
if (mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
|
||||
return MP_OBJ_NULL;
|
||||
} else {
|
||||
nlr_jump(nlr.ret_val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t rt_make_raise_obj(mp_obj_t o) {
|
||||
DEBUG_printf("raise %p\n", o);
|
||||
if (mp_obj_is_exception_type(o)) {
|
||||
|
@ -39,7 +39,8 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
|
||||
void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
|
||||
void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
|
||||
mp_obj_t rt_getiter(mp_obj_t o);
|
||||
mp_obj_t rt_iternext(mp_obj_t o);
|
||||
mp_obj_t rt_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_NULL instead of raising StopIteration()
|
||||
mp_obj_t rt_iternext(mp_obj_t o); // will always return MP_OBJ_NULL instead of raising StopIteration(...)
|
||||
mp_obj_t rt_make_raise_obj(mp_obj_t o);
|
||||
mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);
|
||||
mp_obj_t rt_import_from(mp_obj_t module, qstr name);
|
||||
|
@ -154,7 +154,7 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
|
||||
if (sz != 0) {
|
||||
return l_in;
|
||||
}
|
||||
return mp_const_stop_iteration;
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
|
||||
|
4
py/vm.c
4
py/vm.c
@ -430,8 +430,8 @@ unwind_jump:
|
||||
|
||||
case MP_BC_FOR_ITER:
|
||||
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
|
||||
obj1 = rt_iternext(TOP());
|
||||
if (obj1 == mp_const_stop_iteration) {
|
||||
obj1 = rt_iternext_allow_raise(TOP());
|
||||
if (obj1 == MP_OBJ_NULL) {
|
||||
--sp; // pop the exhausted iterator
|
||||
ip += unum; // jump to after for-block
|
||||
} else {
|
||||
|
52
tests/basics/iter1.py
Normal file
52
tests/basics/iter1.py
Normal file
@ -0,0 +1,52 @@
|
||||
# test user defined iterators
|
||||
|
||||
class MyStopIteration(StopIteration):
|
||||
pass
|
||||
|
||||
class myiter:
|
||||
def __init__(self, i):
|
||||
self.i = i
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.i <= 0:
|
||||
# stop in the usual way
|
||||
raise StopIteration
|
||||
elif self.i == 10:
|
||||
# stop with an argument
|
||||
raise StopIteration(42)
|
||||
elif self.i == 20:
|
||||
# raise a non-stop exception
|
||||
raise TypeError
|
||||
elif self.i == 30:
|
||||
# raise a user-defined stop iteration
|
||||
print('raising MyStopIteration')
|
||||
raise MyStopIteration
|
||||
else:
|
||||
# return the next value
|
||||
self.i -= 1
|
||||
return self.i
|
||||
|
||||
for i in myiter(5):
|
||||
print(i)
|
||||
|
||||
for i in myiter(12):
|
||||
print(i)
|
||||
|
||||
try:
|
||||
for i in myiter(22):
|
||||
print(i)
|
||||
except TypeError:
|
||||
print('raised TypeError')
|
||||
|
||||
try:
|
||||
for i in myiter(5):
|
||||
print(i)
|
||||
raise StopIteration
|
||||
except StopIteration:
|
||||
print('raised StopIteration')
|
||||
|
||||
for i in myiter(32):
|
||||
print(i)
|
23
tests/basics/iter2.py
Normal file
23
tests/basics/iter2.py
Normal file
@ -0,0 +1,23 @@
|
||||
# user defined iterator used in something other than a for loop
|
||||
|
||||
class MyStopIteration(StopIteration):
|
||||
pass
|
||||
|
||||
class myiter:
|
||||
def __init__(self, i):
|
||||
self.i = i
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.i == 0:
|
||||
raise StopIteration
|
||||
elif self.i == 1:
|
||||
raise StopIteration(1)
|
||||
elif self.i == 2:
|
||||
raise MyStopIteration
|
||||
|
||||
print(list(myiter(0)))
|
||||
print(list(myiter(1)))
|
||||
print(list(myiter(2)))
|
Loading…
Reference in New Issue
Block a user