py/obj: Merge getiter and iternext mp_obj_type_t slots.

The goal here is to remove a slot (making way to turn make_new into a slot)
as well as reduce code size by the ~40 references to mp_identity_getiter
and mp_stream_unbuffered_iter.

This introduces two new type flags:
- MP_TYPE_FLAG_ITER_IS_ITERNEXT: This means that the "iter" slot in the
  type is "iternext", and should use the identity getiter.
- MP_TYPE_FLAG_ITER_IS_CUSTOM: This means that the "iter" slot is a pointer
  to a mp_getiter_iternext_custom_t instance, which then defines both
  getiter and iternext.

And a third flag that is the OR of both, MP_TYPE_FLAG_ITER_IS_STREAM: This
means that the type should use the identity getiter, and
mp_stream_unbuffered_iter as iternext.

Finally, MP_TYPE_FLAG_ITER_IS_GETITER is defined as a no-op flag to give
the default case where "iter" is "getiter".

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
Jim Mussared 2022-09-16 23:57:38 +10:00 committed by Damien George
parent 3c6127dfcf
commit 6da41b5900
54 changed files with 234 additions and 227 deletions

View File

@ -95,6 +95,7 @@ int mp_stream_posix_fsync(void *stream) {
}
mp_obj_full_type_t btree_type;
mp_getiter_iternext_custom_t btree_getiter_iternext;
#include "extmod/modbtree.c"
@ -122,13 +123,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
btree_getiter_iternext.getiter = btree_getiter;
btree_getiter_iternext.iternext = btree_iternext;
btree_type.base.type = (void*)&mp_fun_table.type_type;
btree_type.flags = MP_TYPE_FLAG_ITER_IS_CUSTOM;
btree_type.name = MP_QSTR_btree;
MP_OBJ_TYPE_SET_SLOT(&btree_type, print, btree_print, 0);
MP_OBJ_TYPE_SET_SLOT(&btree_type, getiter, btree_getiter, 1);
MP_OBJ_TYPE_SET_SLOT(&btree_type, iternext, btree_iternext, 2);
MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 3);
MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 4);
MP_OBJ_TYPE_SET_SLOT(&btree_type, iter, &btree_getiter_iternext, 1);
MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 2);
MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 3);
btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) };
btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) };
btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) };
@ -137,7 +141,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) };
btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) };
btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) };
MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 5);
MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 4);
mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj));
mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL));

View File

@ -319,15 +319,19 @@ STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
STATIC const mp_getiter_iternext_custom_t btree_getiter_iternext = {
.getiter = btree_getiter,
.iternext = btree_iternext,
};
STATIC MP_DEFINE_CONST_OBJ_TYPE(
btree_type,
MP_QSTR_btree,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_CUSTOM,
MP_TYPE_NULL_MAKE_NEW,
// Save on qstr's, reuse same as for module
print, btree_print,
getiter, btree_getiter,
iternext, btree_iternext,
iter, &btree_getiter_iternext,
binary_op, btree_binary_op,
subscr, btree_subscr,
locals_dict, &btree_locals_dict

View File

@ -287,14 +287,18 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
return mp_const_none;
}
STATIC const mp_getiter_iternext_custom_t task_getiter_iternext = {
.getiter = task_getiter,
.iternext = task_iternext,
};
STATIC MP_DEFINE_CONST_OBJ_TYPE(
task_type,
MP_QSTR_Task,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_CUSTOM,
task_make_new,
attr, task_attr,
getiter, task_getiter,
iternext, task_iternext
iter, &task_getiter_iternext
);
/******************************************************************************/

View File

@ -339,10 +339,9 @@ STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_poll,
MP_QSTR_poll,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
getiter, mp_identity_getiter,
iternext, poll_iternext,
iter, poll_iternext,
locals_dict, &poll_locals_dict
);

View File

@ -321,8 +321,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_NULL_MAKE_NEW,
// Save on qstr's, reuse same as for module
print, ussl_socket_print,
getiter, NULL,
iternext, NULL,
protocol, &ussl_socket_stream_p,
locals_dict, &ussl_socket_locals_dict
);

View File

@ -399,8 +399,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_NULL_MAKE_NEW,
// Save on qstr's, reuse same as for module
print, socket_print,
getiter, NULL,
iternext, NULL,
protocol, &ussl_socket_stream_p,
locals_dict, &ussl_socket_locals_dict
);

View File

@ -179,11 +179,9 @@ STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_vfs_fat_fileio,
MP_QSTR_FileIO,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, file_obj_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &vfs_fat_fileio_stream_p,
locals_dict, &vfs_fat_rawfile_locals_dict
);
@ -198,11 +196,9 @@ STATIC const mp_stream_p_t vfs_fat_textio_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_vfs_fat_textio,
MP_QSTR_TextIOWrapper,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, file_obj_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &vfs_fat_textio_stream_p,
locals_dict, &vfs_fat_rawfile_locals_dict
);

View File

@ -223,11 +223,9 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = {
MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_VFS_LFSx_(_fileio),
MP_QSTR_FileIO,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, MP_VFS_LFSx(file_print),
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &MP_VFS_LFSx(fileio_stream_p),
locals_dict, &MP_VFS_LFSx(file_locals_dict)
);
@ -242,11 +240,9 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = {
MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_VFS_LFSx_(_textio),
MP_QSTR_TextIOWrapper,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, MP_VFS_LFSx(file_print),
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &MP_VFS_LFSx(textio_stream_p),
locals_dict, &MP_VFS_LFSx(file_locals_dict)
);

View File

@ -252,11 +252,9 @@ STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_vfs_posix_fileio,
MP_QSTR_FileIO,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, vfs_posix_file_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &vfs_posix_fileio_stream_p,
locals_dict, &vfs_posix_rawfile_locals_dict
);
@ -271,11 +269,9 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
mp_type_vfs_posix_textio,
MP_QSTR_TextIOWrapper,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, vfs_posix_file_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &vfs_posix_textio_stream_p,
locals_dict, &vfs_posix_rawfile_locals_dict
);

View File

@ -64,9 +64,6 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
ssl_socket_type,
MP_QSTR_ussl,
MP_TYPE_FLAG_NONE,
MP_TYPE_NULL_MAKE_NEW,
getiter, NULL,
iternext, NULL,
protocol, &socket_stream_p,
locals_dict, &socket_locals_dict
);

View File

@ -688,11 +688,9 @@ STATIC const mp_irq_methods_t uart_irq_methods = {
MP_DEFINE_CONST_OBJ_TYPE(
pyb_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
pyb_uart_make_new,
print, pyb_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &pyb_uart_locals_dict
);

View File

@ -832,11 +832,9 @@ STATIC const mp_stream_p_t i2s_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_i2s_type,
MP_QSTR_I2S,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_i2s_make_new,
print, machine_i2s_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &i2s_stream_p,
locals_dict, &machine_i2s_locals_dict
);

View File

@ -533,11 +533,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_uart_make_new,
print, machine_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &machine_uart_locals_dict
);

View File

@ -346,11 +346,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
pyb_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
pyb_uart_make_new,
print, pyb_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &pyb_uart_locals_dict
);

View File

@ -1216,11 +1216,9 @@ STATIC const mp_stream_p_t i2s_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_i2s_type,
MP_QSTR_I2S,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_i2s_make_new,
print, machine_i2s_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &i2s_stream_p,
locals_dict, &machine_i2s_locals_dict
);

View File

@ -472,11 +472,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_uart_make_new,
print, machine_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &machine_uart_locals_dict
);

View File

@ -46,10 +46,9 @@ static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) {
MP_DEFINE_CONST_OBJ_TYPE(
microbit_repeat_iterator_type,
MP_QSTR_iterator,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
getiter, mp_identity_getiter,
iternext, microbit_repeat_iter_next
iter, microbit_repeat_iter_next
);
mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) {

View File

@ -824,18 +824,16 @@ STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) {
MP_DEFINE_CONST_OBJ_TYPE(
microbit_scrolling_string_type,
MP_QSTR_ScrollingString,
MP_TYPE_FLAG_NONE,
MP_TYPE_NULL_MAKE_NEW,
getiter, get_microbit_scrolling_string_iter
MP_TYPE_FLAG_ITER_IS_GETITER,
iter, get_microbit_scrolling_string_iter
);
MP_DEFINE_CONST_OBJ_TYPE(
microbit_scrolling_string_iterator_type,
MP_QSTR_iterator,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
getiter, mp_identity_getiter,
iternext, microbit_scrolling_string_iter_next
iter, microbit_scrolling_string_iter_next
);
/** Facade types to present a string as a sequence of images.
@ -877,11 +875,10 @@ static mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t
MP_DEFINE_CONST_OBJ_TYPE(
string_image_facade_type,
MP_QSTR_Facade,
MP_TYPE_FLAG_NONE,
MP_TYPE_NULL_MAKE_NEW,
MP_TYPE_FLAG_ITER_IS_GETITER,
unary_op, facade_unary_op,
subscr, string_image_facade_subscr,
getiter, microbit_facade_iterator
iter, microbit_facade_iterator
);
@ -914,10 +911,9 @@ static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) {
MP_DEFINE_CONST_OBJ_TYPE(
microbit_facade_iterator_type,
MP_QSTR_iterator,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
getiter, mp_identity_getiter,
iternext, microbit_facade_iter_next
iter, microbit_facade_iter_next
);
mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) {

View File

@ -373,11 +373,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_hard_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_hard_uart_make_new,
print, machine_hard_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &machine_hard_uart_locals_dict
);

View File

@ -574,12 +574,10 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_uart_make_new,
locals_dict, &machine_uart_locals_dict,
print, machine_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p
);

View File

@ -1140,11 +1140,9 @@ STATIC const mp_stream_p_t i2s_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_i2s_type,
MP_QSTR_I2S,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_i2s_make_new,
print, machine_i2s_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &i2s_stream_p,
locals_dict, &machine_i2s_locals_dict
);

View File

@ -582,11 +582,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_uart_make_new,
print, machine_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &machine_uart_locals_dict
);

View File

@ -1117,11 +1117,9 @@ STATIC const mp_stream_p_t i2s_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_i2s_type,
MP_QSTR_I2S,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_i2s_make_new,
print, machine_i2s_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &i2s_stream_p,
locals_dict, &machine_i2s_locals_dict
);

View File

@ -663,11 +663,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
pyb_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
pyb_uart_make_new,
print, pyb_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &pyb_uart_locals_dict
);

View File

@ -939,11 +939,9 @@ STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
pyb_usb_vcp_type,
MP_QSTR_USB_VCP,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
pyb_usb_vcp_make_new,
print, pyb_usb_vcp_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &pyb_usb_vcp_stream_p,
locals_dict, &pyb_usb_vcp_locals_dict
);

View File

@ -325,13 +325,13 @@ STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
STATIC MP_DEFINE_CONST_OBJ_TYPE(
jobject_type,
MP_QSTR_jobject,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_GETITER,
MP_TYPE_NULL_MAKE_NEW,
print, jobject_print,
unary_op, jobject_unary_op,
attr, jobject_attr,
subscr, jobject_subscr,
getiter, subscr_getiter,
iter, subscr_getiter,
// .locals_dict = &jobject_locals_dict,
);

View File

@ -314,10 +314,9 @@ STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_poll,
MP_QSTR_poll,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
MP_TYPE_NULL_MAKE_NEW,
getiter, mp_identity_getiter,
iternext, poll_iternext,
iter, poll_iternext,
locals_dict, &poll_locals_dict
);

View File

@ -522,8 +522,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_FLAG_NONE,
socket_make_new,
print, socket_print,
getiter, NULL,
iternext, NULL,
protocol, &usocket_stream_p,
locals_dict, &usocket_locals_dict
);

View File

@ -157,11 +157,9 @@ STATIC const mp_stream_p_t uart_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
machine_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
machine_uart_make_new,
print, machine_uart_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &uart_stream_p,
locals_dict, &machine_uart_locals_dict
);

View File

@ -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);

View File

@ -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 {

View File

@ -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) {

View File

@ -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

View File

@ -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
);

View File

@ -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) {

View File

@ -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

View File

@ -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
);

View File

@ -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)

View File

@ -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
);

View File

@ -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
);

View File

@ -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);
}

View File

@ -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

View File

@ -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
);

View File

@ -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

View File

@ -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

View File

@ -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
);

View File

@ -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
);

View File

@ -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
);

View File

@ -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
);

View File

@ -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);

View File

@ -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
);

View File

@ -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;

View File

@ -126,11 +126,9 @@ STATIC const mp_stream_p_t stdio_obj_stream_p = {
MP_DEFINE_CONST_OBJ_TYPE(
stdio_obj_type,
MP_QSTR_FileIO,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, stdio_obj_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &stdio_obj_stream_p,
locals_dict, &stdio_locals_dict
);
@ -162,11 +160,9 @@ STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = {
STATIC MP_DEFINE_CONST_OBJ_TYPE(
stdio_buffer_obj_type,
MP_QSTR_FileIO,
MP_TYPE_FLAG_NONE,
MP_TYPE_FLAG_ITER_IS_STREAM,
MP_TYPE_NULL_MAKE_NEW,
print, stdio_obj_print,
getiter, mp_identity_getiter,
iternext, mp_stream_unbuffered_iter,
protocol, &stdio_buffer_obj_stream_p,
locals_dict, &stdio_locals_dict
);

View File

@ -0,0 +1,24 @@
# Checks that an instance type inheriting from a native base that uses
# MP_TYPE_FLAG_ITER_IS_STREAM will still have a getiter.
try:
import uio as io
except ImportError:
import io
a = io.StringIO()
a.write("hello\nworld\nmicro\npython\n")
a.seek(0)
for line in a:
print(line)
class X(io.StringIO):
pass
b = X()
b.write("hello\nworld\nmicro\npython\n")
b.seek(0)
for line in b:
print(line)