@@ -57,26 +57,34 @@ STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs)
5757}
5858
5959STATIC int instance_count_native_bases (const mp_obj_type_t * type , const mp_obj_type_t * * last_native_base ) {
60- size_t len = type -> bases_tuple -> len ;
61- mp_obj_t * items = type -> bases_tuple -> items ;
62-
6360 int count = 0 ;
64- for (size_t i = 0 ; i < len ; i ++ ) {
65- assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
66- const mp_obj_type_t * bt = (const mp_obj_type_t * )MP_OBJ_TO_PTR (items [i ]);
67- if (bt == & mp_type_object ) {
68- // Not a "real" type
69- continue ;
70- }
71- if (mp_obj_is_native_type (bt )) {
72- * last_native_base = bt ;
73- count ++ ;
61+ for (;;) {
62+ if (type == & mp_type_object ) {
63+ // Not a "real" type, end search here.
64+ return count ;
65+ } else if (mp_obj_is_native_type (type )) {
66+ // Native types don't have parents (at least not from our perspective) so end.
67+ * last_native_base = type ;
68+ return count + 1 ;
69+ } else if (type -> parent == NULL ) {
70+ // No parents so end search here.
71+ return count ;
72+ } else if (((mp_obj_base_t * )type -> parent )-> type == & mp_type_tuple ) {
73+ // Multiple parents, search through them all recursively.
74+ const mp_obj_tuple_t * parent_tuple = type -> parent ;
75+ const mp_obj_t * item = parent_tuple -> items ;
76+ const mp_obj_t * top = item + parent_tuple -> len ;
77+ for (; item < top ; ++ item ) {
78+ assert (MP_OBJ_IS_TYPE (* item , & mp_type_type ));
79+ const mp_obj_type_t * bt = (const mp_obj_type_t * )MP_OBJ_TO_PTR (* item );
80+ count += instance_count_native_bases (bt , last_native_base );
81+ }
82+ return count ;
7483 } else {
75- count += instance_count_native_bases (bt , last_native_base );
84+ // A single parent, use iteration to continue the search.
85+ type = type -> parent ;
7686 }
7787 }
78-
79- return count ;
8088}
8189
8290// TODO
@@ -160,32 +168,31 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
160168
161169 // attribute not found, keep searching base classes
162170
163- // for a const struct, this entry might be NULL
164- if (type -> bases_tuple == NULL ) {
165- return ;
166- }
167-
168- size_t len = type -> bases_tuple -> len ;
169- mp_obj_t * items = type -> bases_tuple -> items ;
170- if (len == 0 ) {
171+ if (type -> parent == NULL ) {
171172 return ;
172- }
173- for (size_t i = 0 ; i < len - 1 ; i ++ ) {
174- assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
175- mp_obj_type_t * bt = (mp_obj_type_t * )MP_OBJ_TO_PTR (items [i ]);
176- if (bt == & mp_type_object ) {
177- // Not a "real" type
178- continue ;
179- }
180- mp_obj_class_lookup (lookup , bt );
181- if (lookup -> dest [0 ] != MP_OBJ_NULL ) {
182- return ;
173+ } else if (((mp_obj_base_t * )type -> parent )-> type == & mp_type_tuple ) {
174+ const mp_obj_tuple_t * parent_tuple = type -> parent ;
175+ const mp_obj_t * item = parent_tuple -> items ;
176+ const mp_obj_t * top = item + parent_tuple -> len - 1 ;
177+ for (; item < top ; ++ item ) {
178+ assert (MP_OBJ_IS_TYPE (* item , & mp_type_type ));
179+ mp_obj_type_t * bt = (mp_obj_type_t * )MP_OBJ_TO_PTR (* item );
180+ if (bt == & mp_type_object ) {
181+ // Not a "real" type
182+ continue ;
183+ }
184+ mp_obj_class_lookup (lookup , bt );
185+ if (lookup -> dest [0 ] != MP_OBJ_NULL ) {
186+ return ;
187+ }
183188 }
184- }
185189
186- // search last base (simple tail recursion elimination)
187- assert (MP_OBJ_IS_TYPE (items [len - 1 ], & mp_type_type ));
188- type = (mp_obj_type_t * )MP_OBJ_TO_PTR (items [len - 1 ]);
190+ // search last base (simple tail recursion elimination)
191+ assert (MP_OBJ_IS_TYPE (* item , & mp_type_type ));
192+ type = (mp_obj_type_t * )MP_OBJ_TO_PTR (* item );
193+ } else {
194+ type = type -> parent ;
195+ }
189196 if (type == & mp_type_object ) {
190197 // Not a "real" type
191198 return ;
@@ -946,14 +953,21 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
946953 o -> getiter = instance_getiter ;
947954 //o->iternext = ; not implemented
948955 o -> buffer_p .get_buffer = instance_get_buffer ;
949- // Inherit protocol from a base class. This allows to define an
950- // abstract base class which would translate C-level protocol to
951- // Python method calls, and any subclass inheriting from it will
952- // support this feature.
956+
953957 if (len > 0 ) {
958+ // Inherit protocol from a base class. This allows to define an
959+ // abstract base class which would translate C-level protocol to
960+ // Python method calls, and any subclass inheriting from it will
961+ // support this feature.
954962 o -> protocol = ((mp_obj_type_t * )MP_OBJ_TO_PTR (items [0 ]))-> protocol ;
963+
964+ if (len >= 2 ) {
965+ o -> parent = MP_OBJ_TO_PTR (bases_tuple );
966+ } else {
967+ o -> parent = MP_OBJ_TO_PTR (items [0 ]);
968+ }
955969 }
956- o -> bases_tuple = MP_OBJ_TO_PTR ( bases_tuple );
970+
957971 o -> locals_dict = MP_OBJ_TO_PTR (locals_dict );
958972
959973 const mp_obj_type_t * native_base ;
@@ -1015,27 +1029,34 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
10151029
10161030 mp_obj_type_t * type = MP_OBJ_TO_PTR (self -> type );
10171031
1018- // for a const struct, this entry might be NULL
1019- if (type -> bases_tuple == NULL ) {
1020- return ;
1021- }
1022-
1023- size_t len = type -> bases_tuple -> len ;
1024- mp_obj_t * items = type -> bases_tuple -> items ;
10251032 struct class_lookup_data lookup = {
10261033 .obj = MP_OBJ_TO_PTR (self -> obj ),
10271034 .attr = attr ,
10281035 .meth_offset = 0 ,
10291036 .dest = dest ,
10301037 .is_type = false,
10311038 };
1032- for (size_t i = 0 ; i < len ; i ++ ) {
1033- assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
1034- mp_obj_class_lookup (& lookup , (mp_obj_type_t * )MP_OBJ_TO_PTR (items [i ]));
1039+
1040+ if (type -> parent == NULL ) {
1041+ // no parents, do nothing
1042+ } else if (((mp_obj_base_t * )type -> parent )-> type == & mp_type_tuple ) {
1043+ const mp_obj_tuple_t * parent_tuple = type -> parent ;
1044+ size_t len = parent_tuple -> len ;
1045+ const mp_obj_t * items = parent_tuple -> items ;
1046+ for (size_t i = 0 ; i < len ; i ++ ) {
1047+ assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
1048+ mp_obj_class_lookup (& lookup , (mp_obj_type_t * )MP_OBJ_TO_PTR (items [i ]));
1049+ if (dest [0 ] != MP_OBJ_NULL ) {
1050+ return ;
1051+ }
1052+ }
1053+ } else {
1054+ mp_obj_class_lookup (& lookup , type -> parent );
10351055 if (dest [0 ] != MP_OBJ_NULL ) {
10361056 return ;
10371057 }
10381058 }
1059+
10391060 mp_obj_class_lookup (& lookup , & mp_type_object );
10401061}
10411062
@@ -1073,27 +1094,28 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
10731094
10741095 const mp_obj_type_t * self = MP_OBJ_TO_PTR (object );
10751096
1076- // for a const struct, this entry might be NULL
1077- if (self -> bases_tuple == NULL ) {
1078- return false;
1079- }
1080-
1081- // get the base objects (they should be type objects)
1082- size_t len = self -> bases_tuple -> len ;
1083- mp_obj_t * items = self -> bases_tuple -> items ;
1084- if (len == 0 ) {
1097+ if (self -> parent == NULL ) {
1098+ // type has no parents
10851099 return false;
1086- }
1087-
1088- // iterate through the base objects
1089- for (size_t i = 0 ; i < len - 1 ; i ++ ) {
1090- if (mp_obj_is_subclass_fast (items [i ], classinfo )) {
1091- return true;
1100+ } else if (((mp_obj_base_t * )self -> parent )-> type == & mp_type_tuple ) {
1101+ // get the base objects (they should be type objects)
1102+ const mp_obj_tuple_t * parent_tuple = self -> parent ;
1103+ const mp_obj_t * item = parent_tuple -> items ;
1104+ const mp_obj_t * top = item + parent_tuple -> len - 1 ;
1105+
1106+ // iterate through the base objects
1107+ for (; item < top ; ++ item ) {
1108+ if (mp_obj_is_subclass_fast (* item , classinfo )) {
1109+ return true;
1110+ }
10921111 }
1093- }
10941112
1095- // search last base (simple tail recursion elimination)
1096- object = items [len - 1 ];
1113+ // search last base (simple tail recursion elimination)
1114+ object = * item ;
1115+ } else {
1116+ // type has 1 parent
1117+ object = MP_OBJ_FROM_PTR (self -> parent );
1118+ }
10971119 }
10981120}
10991121
0 commit comments