summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/obj.c8
-rw-r--r--py/obj.h56
-rw-r--r--py/objarray.c17
-rw-r--r--py/objattrtuple.c4
-rw-r--r--py/objdict.c17
-rw-r--r--py/objenumerate.c5
-rw-r--r--py/objfilter.c5
-rw-r--r--py/objgenerator.c5
-rw-r--r--py/objgetitemiter.c5
-rw-r--r--py/objlist.c4
-rw-r--r--py/objmap.c5
-rw-r--r--py/objnamedtuple.c2
-rw-r--r--py/objpolyiter.c10
-rw-r--r--py/objrange.c7
-rw-r--r--py/objreversed.c5
-rw-r--r--py/objset.c8
-rw-r--r--py/objstr.c4
-rw-r--r--py/objstringio.c8
-rw-r--r--py/objstrunicode.c4
-rw-r--r--py/objtuple.c8
-rw-r--r--py/objtype.c23
-rw-r--r--py/objzip.c5
-rw-r--r--py/runtime.c52
23 files changed, 149 insertions, 118 deletions
diff --git a/py/obj.c b/py/obj.c
index 359c73b9c2..eb17308fed 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -572,10 +572,10 @@ 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;
-}
+// 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) {
const mp_obj_type_t *type = mp_obj_get_type(obj);
diff --git a/py/obj.h b/py/obj.h
index 878fa67348..b1d722080c 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -507,12 +507,20 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *);
// Flags for type behaviour (mp_obj_type_t.flags)
// If MP_TYPE_FLAG_EQ_NOT_REFLEXIVE is clear then __eq__ is reflexive (A==A returns True).
// If MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE is clear then the type can't be equal to an
-// instance of any different class that also clears this flag. If this flag is set
-// then the type may check for equality against a different type.
+// instance of any different class that also clears this flag. If this flag is set
+// then the type may check for equality against a different type.
// If MP_TYPE_FLAG_EQ_HAS_NEQ_TEST is clear then the type only implements the __eq__
-// operator and not the __ne__ operator. If it's set then __ne__ may be implemented.
+// operator and not the __ne__ operator. If it's set then __ne__ may be implemented.
// If MP_TYPE_FLAG_BINDS_SELF is set then the type as a method binds self as the first arg.
// If MP_TYPE_FLAG_BUILTIN_FUN is set then the type is a built-in function type.
+// MP_TYPE_FLAG_ITER_IS_GETITER is a no-op flag that means the default behaviour for the
+// iter slot and it's the getiter function.
+// If MP_TYPE_FLAG_ITER_IS_ITERNEXT is set then the "iter" slot is the iternext
+// function and getiter will be automatically implemented as "return self".
+// If MP_TYPE_FLAG_ITER_IS_CUSTOM is set then the "iter" slot is a pointer to a
+// mp_getiter_iternext_custom_t struct instance (with both .getiter and .iternext set).
+// If MP_TYPE_FLAG_ITER_IS_STREAM is set then the type implicitly gets a "return self"
+// getiter, and mp_stream_unbuffered_iter for iternext.
#define MP_TYPE_FLAG_NONE (0x0000)
#define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001)
#define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002)
@@ -521,6 +529,10 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *);
#define MP_TYPE_FLAG_EQ_HAS_NEQ_TEST (0x0010)
#define MP_TYPE_FLAG_BINDS_SELF (0x0020)
#define MP_TYPE_FLAG_BUILTIN_FUN (0x0040)
+#define MP_TYPE_FLAG_ITER_IS_GETITER (0x0000)
+#define MP_TYPE_FLAG_ITER_IS_ITERNEXT (0x0080)
+#define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100)
+#define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM)
typedef enum {
PRINT_STR = 0,
@@ -548,6 +560,13 @@ typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_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);
+typedef mp_fun_1_t mp_iternext_fun_t;
+
+// For MP_TYPE_FLAG_ITER_IS_CUSTOM, the "getiter" slot points to an instance of this type.
+typedef struct _mp_getiter_iternext_custom_t {
+ mp_getiter_fun_t getiter;
+ mp_iternext_fun_t iternext;
+} mp_getiter_iternext_custom_t;
// Buffer protocol
typedef struct _mp_buffer_info_t {
@@ -616,14 +635,17 @@ struct _mp_obj_type_t {
// Can return MP_OBJ_NULL if operation not supported.
uint8_t slot_index_subscr;
- // Corresponds to __iter__ special method.
- // Can use the given mp_obj_iter_buf_t to store iterator object,
- // otherwise can return a pointer to an object on the heap.
- uint8_t slot_index_getiter;
-
- // Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION
- // as an optimisation instead of raising StopIteration() with no args.
- uint8_t slot_index_iternext;
+ // This slot's behaviour depends on the MP_TYPE_FLAG_ITER_IS_* flags above.
+ // - If MP_TYPE_FLAG_ITER_IS_GETITER flag is set, then this corresponds to the __iter__
+ // special method (of type mp_getiter_fun_t). Can use the given mp_obj_iter_buf_t
+ // to store the iterator object, otherwise can return a pointer to an object on the heap.
+ // - If MP_TYPE_FLAG_ITER_IS_ITERNEXT is set, then this corresponds to __next__ special method.
+ // May return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration()
+ // with no args. The type will implicitly implement getiter as "return self".
+ // - If MP_TYPE_FLAG_ITER_IS_CUSTOM is set, then this slot must point to an
+ // mp_getiter_iternext_custom_t instance with both the getiter and iternext fields set.
+ // - If MP_TYPE_FLAG_ITER_IS_STREAM is set, this this slot should be unset.
+ uint8_t slot_index_iter;
// Implements the buffer protocol if supported by this type.
uint8_t slot_index_buffer;
@@ -659,8 +681,7 @@ typedef struct _mp_obj_empty_type_t {
uint8_t slot_index_binary_op;
uint8_t slot_index_attr;
uint8_t slot_index_subscr;
- uint8_t slot_index_getiter;
- uint8_t slot_index_iternext;
+ uint8_t slot_index_iter;
uint8_t slot_index_buffer;
uint8_t slot_index_protocol;
uint8_t slot_index_parent;
@@ -681,15 +702,14 @@ typedef struct _mp_obj_full_type_t {
uint8_t slot_index_binary_op;
uint8_t slot_index_attr;
uint8_t slot_index_subscr;
- uint8_t slot_index_getiter;
- uint8_t slot_index_iternext;
+ uint8_t slot_index_iter;
uint8_t slot_index_buffer;
uint8_t slot_index_protocol;
uint8_t slot_index_parent;
uint8_t slot_index_locals_dict;
// Explicitly add 12 slots.
- const void *slots[12];
+ const void *slots[11];
} mp_obj_full_type_t;
#define MP_TYPE_NULL_MAKE_NEW (NULL)
@@ -700,8 +720,7 @@ typedef struct _mp_obj_full_type_t {
#define _MP_OBJ_TYPE_SLOT_TYPE_binary_op (mp_binary_op_fun_t)
#define _MP_OBJ_TYPE_SLOT_TYPE_attr (mp_attr_fun_t)
#define _MP_OBJ_TYPE_SLOT_TYPE_subscr (mp_subscr_fun_t)
-#define _MP_OBJ_TYPE_SLOT_TYPE_getiter (mp_getiter_fun_t)
-#define _MP_OBJ_TYPE_SLOT_TYPE_iternext (mp_fun_1_t)
+#define _MP_OBJ_TYPE_SLOT_TYPE_iter (const void *)
#define _MP_OBJ_TYPE_SLOT_TYPE_buffer (mp_buffer_fun_t)
#define _MP_OBJ_TYPE_SLOT_TYPE_protocol (const void *)
#define _MP_OBJ_TYPE_SLOT_TYPE_parent (const void *)
@@ -1162,7 +1181,6 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun);
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 {
diff --git a/py/objarray.c b/py/objarray.c
index 762a4105c5..0d1032929f 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -574,10 +574,10 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_array,
MP_QSTR_array,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
array_make_new,
print, array_print,
- getiter, array_iterator_new,
+ iter, array_iterator_new,
unary_op, array_unary_op,
binary_op, array_binary_op,
subscr, array_subscr,
@@ -590,10 +590,10 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_bytearray,
MP_QSTR_bytearray,
- MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE,
+ MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER,
bytearray_make_new,
print, array_print,
- getiter, array_iterator_new,
+ iter, array_iterator_new,
unary_op, array_unary_op,
binary_op, array_binary_op,
subscr, array_subscr,
@@ -618,9 +618,9 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_memoryview,
MP_QSTR_memoryview,
- MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE,
+ MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER,
memoryview_make_new,
- getiter, array_iterator_new,
+ iter, array_iterator_new,
unary_op, array_unary_op,
binary_op, array_binary_op,
MEMORYVIEW_TYPE_LOCALS_DICT
@@ -676,10 +676,9 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_array_it,
MP_QSTR_iterator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
- getiter, mp_identity_getiter,
- iternext, array_it_iternext
+ iter, array_it_iternext
);
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) {
diff --git a/py/objattrtuple.c b/py/objattrtuple.c
index 0d41ee5235..2e207f4cf0 100644
--- a/py/objattrtuple.c
+++ b/py/objattrtuple.c
@@ -83,7 +83,7 @@ mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *item
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_attrtuple,
MP_QSTR_tuple,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_NULL_MAKE_NEW,
// reuse tuple to save on a qstr
print, mp_obj_attrtuple_print,
@@ -91,7 +91,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
binary_op, mp_obj_tuple_binary_op,
attr, mp_obj_attrtuple_attr,
subscr, mp_obj_tuple_subscr,
- getiter, mp_obj_tuple_getiter
+ iter, mp_obj_tuple_getiter
);
#endif // MICROPY_PY_ATTRTUPLE
diff --git a/py/objdict.c b/py/objdict.c
index c65b14caad..7755d7b786 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -464,10 +464,9 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_dict_view_it,
MP_QSTR_iterator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
- getiter, mp_identity_getiter,
- iternext, dict_view_it_iternext
+ iter, dict_view_it_iternext
);
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) {
@@ -517,11 +516,11 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_dict_view,
MP_QSTR_dict_view,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_NULL_MAKE_NEW,
print, dict_view_print,
binary_op, dict_view_binary_op,
- getiter, dict_view_getiter
+ iter, dict_view_getiter
);
STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) {
@@ -592,13 +591,13 @@ STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_dict,
MP_QSTR_dict,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
mp_obj_dict_make_new,
print, dict_print,
unary_op, dict_unary_op,
binary_op, dict_binary_op,
subscr, dict_subscr,
- getiter, dict_getiter,
+ iter, dict_getiter,
locals_dict, &dict_locals_dict
);
@@ -606,13 +605,13 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_ordereddict,
MP_QSTR_OrderedDict,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
mp_obj_dict_make_new,
print, dict_print,
unary_op, dict_unary_op,
binary_op, dict_binary_op,
subscr, dict_subscr,
- getiter, dict_getiter,
+ iter, dict_getiter,
parent, &mp_type_dict,
locals_dict, &dict_locals_dict
);
diff --git a/py/objenumerate.c b/py/objenumerate.c
index f4f4ff6ae1..eea9e3e381 100644
--- a/py/objenumerate.c
+++ b/py/objenumerate.c
@@ -70,10 +70,9 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_enumerate,
MP_QSTR_enumerate,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
enumerate_make_new,
- iternext, enumerate_iternext,
- getiter, mp_identity_getiter
+ iter, enumerate_iternext
);
STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) {
diff --git a/py/objfilter.c b/py/objfilter.c
index 2b57300af3..bfe651f40d 100644
--- a/py/objfilter.c
+++ b/py/objfilter.c
@@ -63,10 +63,9 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_filter,
MP_QSTR_filter,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
filter_make_new,
- getiter, mp_identity_getiter,
- iternext, filter_iternext
+ iter, filter_iternext
);
#endif // MICROPY_PY_BUILTINS_FILTER
diff --git a/py/objgenerator.c b/py/objgenerator.c
index a960c23700..d8515c13ce 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -370,11 +370,10 @@ STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_t
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_gen_instance,
MP_QSTR_generator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
print, gen_instance_print,
unary_op, mp_generic_unary_op,
- getiter, mp_identity_getiter,
- iternext, gen_instance_iternext,
+ iter, gen_instance_iternext,
locals_dict, &gen_instance_locals_dict
);
diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c
index ed2dfbbe1f..134cbcd629 100644
--- a/py/objgetitemiter.c
+++ b/py/objgetitemiter.c
@@ -59,10 +59,9 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_it,
MP_QSTR_iterator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
- getiter, mp_identity_getiter,
- iternext, it_iternext
+ iter, it_iternext
);
// args are those returned from mp_load_method_maybe (ie either an attribute or a method)
diff --git a/py/objlist.c b/py/objlist.c
index 5f9e99cc79..8d18344ea8 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -455,13 +455,13 @@ STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_list,
MP_QSTR_list,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
list_make_new,
print, list_print,
unary_op, list_unary_op,
binary_op, list_binary_op,
subscr, list_subscr,
- getiter, list_getiter,
+ iter, list_getiter,
locals_dict, &list_locals_dict
);
diff --git a/py/objmap.c b/py/objmap.c
index dc305e21b5..115832e387 100644
--- a/py/objmap.c
+++ b/py/objmap.c
@@ -66,8 +66,7 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_map,
MP_QSTR_map,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
map_make_new,
- getiter, mp_identity_getiter,
- iternext, map_iternext
+ iter, map_iternext
);
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 52536be8b4..3b45d8f76f 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -163,7 +163,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t
MP_OBJ_TYPE_SET_SLOT(type, binary_op, mp_obj_tuple_binary_op, 2);
MP_OBJ_TYPE_SET_SLOT(type, attr, namedtuple_attr, 3);
MP_OBJ_TYPE_SET_SLOT(type, subscr, mp_obj_tuple_subscr, 4);
- MP_OBJ_TYPE_SET_SLOT(type, getiter, mp_obj_tuple_getiter, 5);
+ MP_OBJ_TYPE_SET_SLOT(type, iter, mp_obj_tuple_getiter, 5);
MP_OBJ_TYPE_SET_SLOT(type, parent, &mp_type_tuple, 6);
return MP_OBJ_FROM_PTR(o);
}
diff --git a/py/objpolyiter.c b/py/objpolyiter.c
index 5bc397f6ec..7a45b6b73f 100644
--- a/py/objpolyiter.c
+++ b/py/objpolyiter.c
@@ -48,10 +48,9 @@ STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_polymorph_iter,
MP_QSTR_iterator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
- getiter, mp_identity_getiter,
- iternext, polymorph_it_iternext
+ iter, polymorph_it_iternext
);
#if MICROPY_ENABLE_FINALISER
@@ -81,10 +80,9 @@ STATIC MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_polymorph_iter_with_finaliser,
MP_QSTR_iterator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
- getiter, mp_identity_getiter,
- iternext, polymorph_it_iternext,
+ iter, polymorph_it_iternext,
locals_dict, &mp_obj_polymorph_iter_locals_dict
);
#endif
diff --git a/py/objrange.c b/py/objrange.c
index 3140504b2b..1ad8f6031f 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -53,10 +53,9 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_range_it,
MP_QSTR_iterator,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
- getiter, mp_identity_getiter,
- iternext, range_it_iternext
+ iter, 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_iter_buf_t *iter_buf) {
@@ -232,5 +231,5 @@ MP_DEFINE_CONST_OBJ_TYPE(
print, range_print,
unary_op, range_unary_op,
subscr, range_subscr,
- getiter, range_getiter
+ iter, range_getiter
);
diff --git a/py/objreversed.c b/py/objreversed.c
index bc1f07ddec..e265266d3f 100644
--- a/py/objreversed.c
+++ b/py/objreversed.c
@@ -71,10 +71,9 @@ STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_reversed,
MP_QSTR_reversed,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
reversed_make_new,
- getiter, mp_identity_getiter,
- iternext, reversed_iternext
+ iter, reversed_iternext
);
#endif // MICROPY_PY_BUILTINS_REVERSED
diff --git a/py/objset.c b/py/objset.c
index 6f21bf15df..b827f49f40 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -542,12 +542,12 @@ STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_set,
MP_QSTR_set,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
set_make_new,
print, set_print,
unary_op, set_unary_op,
binary_op, set_binary_op,
- getiter, set_getiter,
+ iter, set_getiter,
locals_dict, &set_locals_dict
);
@@ -568,12 +568,12 @@ STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_frozenset,
MP_QSTR_frozenset,
- MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE,
+ MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER,
set_make_new,
print, set_print,
unary_op, set_unary_op,
binary_op, set_binary_op,
- getiter, set_getiter,
+ iter, set_getiter,
locals_dict, &frozenset_locals_dict
);
#endif
diff --git a/py/objstr.c b/py/objstr.c
index d425055559..12f6e15d04 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -2151,7 +2151,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
print, str_print,
binary_op, mp_obj_str_binary_op,
subscr, bytes_subscr,
- getiter, mp_obj_new_str_iterator,
+ iter, mp_obj_new_str_iterator,
buffer, mp_obj_str_get_buffer,
locals_dict, &mp_obj_str_locals_dict
);
@@ -2166,7 +2166,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
print, str_print,
binary_op, mp_obj_str_binary_op,
subscr, bytes_subscr,
- getiter, mp_obj_new_bytes_iterator,
+ iter, mp_obj_new_bytes_iterator,
buffer, mp_obj_str_get_buffer,
locals_dict, &mp_obj_bytes_locals_dict
);
diff --git a/py/objstringio.c b/py/objstringio.c
index 77547f88cf..4e19b83999 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -247,11 +247,9 @@ STATIC const mp_stream_p_t stringio_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_stringio,
MP_QSTR_StringIO,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
stringio_make_new,
print, stringio_print,
- getiter, mp_identity_getiter,
- iternext, mp_stream_unbuffered_iter,
protocol, &stringio_stream_p,
locals_dict, &stringio_locals_dict
);
@@ -266,11 +264,9 @@ STATIC const mp_stream_p_t bytesio_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_bytesio,
MP_QSTR_BytesIO,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
stringio_make_new,
print, stringio_print,
- getiter, mp_identity_getiter,
- iternext, mp_stream_unbuffered_iter,
protocol, &bytesio_stream_p,
locals_dict, &stringio_locals_dict
);
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 15c59e4e95..9b28841ecd 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -232,13 +232,13 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_str,
MP_QSTR_str,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
mp_obj_str_make_new,
print, uni_print,
unary_op, uni_unary_op,
binary_op, mp_obj_str_binary_op,
subscr, str_subscr,
- getiter, mp_obj_new_str_iterator,
+ iter, mp_obj_new_str_iterator,
buffer, mp_obj_str_get_buffer,
locals_dict, &mp_obj_str_locals_dict
);
diff --git a/py/objtuple.c b/py/objtuple.c
index 01b2fa1488..485d44c52a 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -32,7 +32,7 @@
#include "py/runtime.h"
// type check is done on getiter method to allow tuple, namedtuple, attrtuple
-#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), getiter) == mp_obj_tuple_getiter)
+#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter)
/******************************************************************************/
/* tuple */
@@ -111,7 +111,7 @@ STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t anothe
mp_check_self(mp_obj_is_tuple_compatible(self_in));
const mp_obj_type_t *another_type = mp_obj_get_type(another_in);
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
- if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(another_type, getiter) != mp_obj_tuple_getiter) {
+ if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(another_type, iter) != mp_obj_tuple_getiter) {
// Slow path for user subclasses
another_in = mp_obj_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple));
if (another_in == MP_OBJ_NULL) {
@@ -227,13 +227,13 @@ STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_tuple,
MP_QSTR_tuple,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
mp_obj_tuple_make_new,
print, mp_obj_tuple_print,
unary_op, mp_obj_tuple_unary_op,
binary_op, mp_obj_tuple_binary_op,
subscr, mp_obj_tuple_subscr,
- getiter, mp_obj_tuple_getiter,
+ iter, mp_obj_tuple_getiter,
locals_dict, &tuple_locals_dict
);
diff --git a/py/objtype.c b/py/objtype.c
index 5b4e375bcc..183dce071e 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -142,7 +142,10 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t
// this should not be applied to class types, as will result in extra
// lookup either.
if (lookup->slot_offset != 0 && mp_obj_is_native_type(type)) {
- if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset)) {
+ // Check if there is a non-zero value in the specified slot index,
+ // with a special case for getiter where the slot won't be set
+ // for MP_TYPE_FLAG_ITER_IS_STREAM.
+ if (MP_OBJ_TYPE_HAS_SLOT_BY_OFFSET(type, lookup->slot_offset) || (lookup->slot_offset == MP_OBJ_TYPE_OFFSETOF_SLOT(iter) && type->flags & MP_TYPE_FLAG_ITER_IS_STREAM)) {
DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n",
lookup->slot_offset, qstr_str(lookup->attr));
lookup->dest[0] = MP_OBJ_SENTINEL;
@@ -889,7 +892,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf)
struct class_lookup_data lookup = {
.obj = self,
.attr = MP_QSTR___iter__,
- .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(getiter),
+ .slot_offset = MP_OBJ_TYPE_OFFSETOF_SLOT(iter),
.dest = member,
.is_type = false,
};
@@ -898,10 +901,14 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf)
return MP_OBJ_NULL;
} else if (member[0] == MP_OBJ_SENTINEL) {
const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);
- if (iter_buf == NULL) {
- iter_buf = m_new_obj(mp_obj_iter_buf_t);
+ if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) {
+ return self->subobj[0];
+ } else {
+ if (iter_buf == NULL) {
+ iter_buf = m_new_obj(mp_obj_iter_buf_t);
+ }
+ return ((mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter))(self->subobj[0], iter_buf);
}
- return MP_OBJ_TYPE_GET_SLOT(type, getiter)(self->subobj[0], iter_buf);
} else {
return mp_call_method_n_kw(0, 0, member);
}
@@ -1122,7 +1129,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
// Basic validation of base classes
uint16_t base_flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE
- | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST;
+ | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE
+ | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST
+ | MP_TYPE_FLAG_ITER_IS_GETITER;
size_t bases_len;
mp_obj_t *bases_items;
mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items);
@@ -1167,7 +1176,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
MP_OBJ_TYPE_SET_SLOT(o, binary_op, instance_binary_op, 3);
MP_OBJ_TYPE_SET_SLOT(o, attr, mp_obj_instance_attr, 4);
MP_OBJ_TYPE_SET_SLOT(o, subscr, instance_subscr, 5);
- MP_OBJ_TYPE_SET_SLOT(o, getiter, mp_obj_instance_getiter, 6);
+ MP_OBJ_TYPE_SET_SLOT(o, iter, mp_obj_instance_getiter, 6);
// MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented)
MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7);
diff --git a/py/objzip.c b/py/objzip.c
index 0ceafd97f2..34d73465ef 100644
--- a/py/objzip.c
+++ b/py/objzip.c
@@ -69,8 +69,7 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_zip,
MP_QSTR_zip,
- MP_TYPE_FLAG_NONE,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
zip_make_new,
- getiter, mp_identity_getiter,
- iternext, zip_iternext
+ iter, zip_iternext
);
diff --git a/py/runtime.c b/py/runtime.c
index d0e504a3d0..ec628bfe14 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -61,6 +61,8 @@ const mp_obj_module_t mp_module___main__ = {
MP_REGISTER_MODULE(MP_QSTR___main__, mp_module___main__);
+#define TYPE_HAS_ITERNEXT(type) (type->flags & (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM | MP_TYPE_FLAG_ITER_IS_STREAM))
+
void mp_init(void) {
qstr_init();
@@ -1167,7 +1169,7 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
}
#endif
- if (attr == MP_QSTR___next__ && MP_OBJ_TYPE_HAS_SLOT(type, iternext)) {
+ if (attr == MP_QSTR___next__ && TYPE_HAS_ITERNEXT(type)) {
dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj);
dest[1] = obj;
return;
@@ -1260,21 +1262,26 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
assert(o_in);
const mp_obj_type_t *type = mp_obj_get_type(o_in);
+ // Most types that use iternext just use the identity getiter. We handle this case explicitly
+ // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used.
+ if ((type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) == MP_TYPE_FLAG_ITER_IS_ITERNEXT || (type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) {
+ return o_in;
+ }
- if (MP_OBJ_TYPE_HAS_SLOT(type, getiter)) {
- // Check for native getiter which is the identity. We handle this case explicitly
- // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used.
- if (MP_OBJ_TYPE_GET_SLOT(type, getiter) == mp_identity_getiter) {
- return o_in;
- }
-
+ if (MP_OBJ_TYPE_HAS_SLOT(type, iter)) {
// check for native getiter (corresponds to __iter__)
- if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, getiter) != mp_obj_instance_getiter) {
+ if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, iter) != mp_obj_instance_getiter) {
// if caller did not provide a buffer then allocate one on the heap
// mp_obj_instance_getiter is special, it will allocate only if needed
iter_buf = m_new_obj(mp_obj_iter_buf_t);
}
- mp_obj_t iter = MP_OBJ_TYPE_GET_SLOT(type, getiter)(o_in, iter_buf);
+ mp_getiter_fun_t getiter;
+ if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) {
+ getiter = ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->getiter;
+ } else {
+ getiter = (mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter);
+ }
+ mp_obj_t iter = getiter(o_in, iter_buf);
if (iter != MP_OBJ_NULL) {
return iter;
}
@@ -1302,13 +1309,26 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
}
+STATIC mp_fun_1_t type_get_iternext(const mp_obj_type_t *type) {
+ if ((type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) {
+ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);
+ return mp_stream_unbuffered_iter;
+ } else if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) {
+ return (mp_fun_1_t)MP_OBJ_TYPE_GET_SLOT(type, iter);
+ } else if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) {
+ return ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->iternext;
+ } else {
+ return NULL;
+ }
+}
+
// may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration()
// may also raise StopIteration()
mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
const mp_obj_type_t *type = mp_obj_get_type(o_in);
- if (MP_OBJ_TYPE_HAS_SLOT(type, iternext)) {
+ if (TYPE_HAS_ITERNEXT(type)) {
MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL;
- return MP_OBJ_TYPE_GET_SLOT(type, iternext)(o_in);
+ return type_get_iternext(type)(o_in);
} else {
// check for __next__ method
mp_obj_t dest[2];
@@ -1332,9 +1352,9 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
mp_obj_t mp_iternext(mp_obj_t o_in) {
MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext
const mp_obj_type_t *type = mp_obj_get_type(o_in);
- if (MP_OBJ_TYPE_HAS_SLOT(type, iternext)) {
+ if (TYPE_HAS_ITERNEXT(type)) {
MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL;
- return MP_OBJ_TYPE_GET_SLOT(type, iternext)(o_in);
+ return type_get_iternext(type)(o_in);
} else {
// check for __next__ method
mp_obj_t dest[2];
@@ -1372,9 +1392,9 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val);
}
- if (MP_OBJ_TYPE_HAS_SLOT(type, iternext) && send_value == mp_const_none) {
+ if (TYPE_HAS_ITERNEXT(type) && send_value == mp_const_none) {
MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL;
- mp_obj_t ret = MP_OBJ_TYPE_GET_SLOT(type, iternext)(self_in);
+ mp_obj_t ret = type_get_iternext(type)(self_in);
*ret_val = ret;
if (ret != MP_OBJ_STOP_ITERATION) {
return MP_VM_RETURN_YIELD;