@@ -71,7 +71,7 @@ STATIC int class_count_native_bases(const mp_obj_type_t *type, const mp_obj_type
7171// it was - because instance->subobj[0] is of that type. The only exception is when
7272// object is not yet constructed, then we need to know base native type to construct
7373// instance->subobj[0]. This case is handled via class_count_native_bases() though.
74- STATIC mp_obj_t mp_obj_class_lookup (const mp_obj_type_t * type , qstr attr , machine_uint_t meth_offset ) {
74+ STATIC mp_obj_t mp_obj_class_lookup (mp_obj_class_t * o , const mp_obj_type_t * type , qstr attr , machine_uint_t meth_offset ) {
7575 for (;;) {
7676 // Optimize special method lookup for native types
7777 // This avoids extra method_name => slot lookup. On the other hand,
@@ -94,6 +94,17 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr, machin
9494 }
9595 }
9696
97+ if (o != MP_OBJ_NULL && is_native_type (type )) {
98+ mp_obj_t dest [2 ];
99+ mp_load_method_maybe (o -> subobj [0 ], attr , dest );
100+ if (dest [0 ] != MP_OBJ_NULL ) {
101+ if (dest [1 ] == MP_OBJ_NULL ) {
102+ return dest [0 ];
103+ }
104+ assert (0 );
105+ }
106+ }
107+
97108 // attribute not found, keep searching base classes
98109
99110 // for a const struct, this entry might be NULL
@@ -109,7 +120,7 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr, machin
109120 }
110121 for (uint i = 0 ; i < len - 1 ; i ++ ) {
111122 assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
112- mp_obj_t obj = mp_obj_class_lookup ((mp_obj_type_t * )items [i ], attr , meth_offset );
123+ mp_obj_t obj = mp_obj_class_lookup (o , (mp_obj_type_t * )items [i ], attr , meth_offset );
113124 if (obj != MP_OBJ_NULL ) {
114125 return obj ;
115126 }
@@ -124,10 +135,10 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr, machin
124135STATIC void class_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in , mp_print_kind_t kind ) {
125136 mp_obj_class_t * self = self_in ;
126137 qstr meth = (kind == PRINT_STR ) ? MP_QSTR___str__ : MP_QSTR___repr__ ;
127- mp_obj_t member = mp_obj_class_lookup (self -> base .type , meth , offsetof(mp_obj_type_t , print ));
138+ mp_obj_t member = mp_obj_class_lookup (self , self -> base .type , meth , offsetof(mp_obj_type_t , print ));
128139 if (member == MP_OBJ_NULL && kind == PRINT_STR ) {
129140 // If there's no __str__, fall back to __repr__
130- member = mp_obj_class_lookup (self -> base .type , MP_QSTR___repr__ , 0 );
141+ member = mp_obj_class_lookup (self , self -> base .type , MP_QSTR___repr__ , 0 );
131142 }
132143
133144 if (member == MP_OBJ_SENTINEL ) {
@@ -156,7 +167,7 @@ STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m
156167 mp_obj_class_t * o = mp_obj_new_class (self_in , num_native_bases );
157168
158169 // look for __init__ function
159- mp_obj_t init_fn = mp_obj_class_lookup (self , MP_QSTR___init__ , offsetof(mp_obj_type_t , make_new ));
170+ mp_obj_t init_fn = mp_obj_class_lookup (NULL , self , MP_QSTR___init__ , offsetof(mp_obj_type_t , make_new ));
160171
161172 if (init_fn == MP_OBJ_SENTINEL ) {
162173 // Native type's constructor is what wins - it gets all our arguments,
@@ -208,7 +219,7 @@ STATIC mp_obj_t class_unary_op(int op, mp_obj_t self_in) {
208219 return MP_OBJ_NOT_SUPPORTED;
209220 }
210221 */
211- mp_obj_t member = mp_obj_class_lookup (self -> base .type , op_name , offsetof(mp_obj_type_t , unary_op ));
222+ mp_obj_t member = mp_obj_class_lookup (self , self -> base .type , op_name , offsetof(mp_obj_type_t , unary_op ));
212223 if (member == MP_OBJ_SENTINEL ) {
213224 return mp_unary_op (op , self -> subobj [0 ]);
214225 } else if (member != MP_OBJ_NULL ) {
@@ -290,7 +301,7 @@ STATIC mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
290301 return MP_OBJ_NOT_SUPPORTED;
291302 }
292303 */
293- mp_obj_t member = mp_obj_class_lookup (lhs -> base .type , op_name , offsetof(mp_obj_type_t , binary_op ));
304+ mp_obj_t member = mp_obj_class_lookup (lhs , lhs -> base .type , op_name , offsetof(mp_obj_type_t , binary_op ));
294305 if (member == MP_OBJ_SENTINEL ) {
295306 return mp_binary_op (op , lhs -> subobj [0 ], rhs_in );
296307 } else if (member != MP_OBJ_NULL ) {
@@ -316,7 +327,7 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
316327 return ;
317328 }
318329
319- mp_obj_t member = mp_obj_class_lookup (self -> base .type , attr , 0 );
330+ mp_obj_t member = mp_obj_class_lookup (self , self -> base .type , attr , 0 );
320331 if (member != MP_OBJ_NULL ) {
321332 if (0 ) {
322333#if MICROPY_ENABLE_PROPERTY
@@ -359,7 +370,7 @@ STATIC bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
359370#if MICROPY_ENABLE_PROPERTY
360371 // for property, we need to do a lookup first in the class dict
361372 // this makes all stores slow... how to fix?
362- mp_obj_t member = mp_obj_class_lookup (self -> base .type , attr , 0 );
373+ mp_obj_t member = mp_obj_class_lookup (self , self -> base .type , attr , 0 );
363374 if (member != MP_OBJ_NULL && MP_OBJ_IS_TYPE (member , & mp_type_property )) {
364375 // attribute already exists and is a property
365376 // delegate the store to the property
@@ -392,15 +403,15 @@ STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
392403 uint meth_args ;
393404 if (value == MP_OBJ_NULL ) {
394405 // delete item
395- member = mp_obj_class_lookup (self -> base .type , MP_QSTR___delitem__ , offsetof(mp_obj_type_t , subscr ));
406+ member = mp_obj_class_lookup (self , self -> base .type , MP_QSTR___delitem__ , offsetof(mp_obj_type_t , subscr ));
396407 meth_args = 2 ;
397408 } else if (value == MP_OBJ_SENTINEL ) {
398409 // load item
399- member = mp_obj_class_lookup (self -> base .type , MP_QSTR___getitem__ , offsetof(mp_obj_type_t , subscr ));
410+ member = mp_obj_class_lookup (self , self -> base .type , MP_QSTR___getitem__ , offsetof(mp_obj_type_t , subscr ));
400411 meth_args = 2 ;
401412 } else {
402413 // store item
403- member = mp_obj_class_lookup (self -> base .type , MP_QSTR___setitem__ , offsetof(mp_obj_type_t , subscr ));
414+ member = mp_obj_class_lookup (self , self -> base .type , MP_QSTR___setitem__ , offsetof(mp_obj_type_t , subscr ));
404415 meth_args = 3 ;
405416 }
406417 if (member == MP_OBJ_SENTINEL ) {
@@ -421,7 +432,7 @@ STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
421432
422433STATIC mp_obj_t class_call (mp_obj_t self_in , uint n_args , uint n_kw , const mp_obj_t * args ) {
423434 mp_obj_class_t * self = self_in ;
424- mp_obj_t member = mp_obj_class_lookup (self -> base .type , MP_QSTR___call__ , offsetof(mp_obj_type_t , call ));
435+ mp_obj_t member = mp_obj_class_lookup (self , self -> base .type , MP_QSTR___call__ , offsetof(mp_obj_type_t , call ));
425436 if (member == MP_OBJ_NULL ) {
426437 return member ;
427438 }
@@ -487,7 +498,7 @@ STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
487498 return ;
488499 }
489500#endif
490- mp_obj_t member = mp_obj_class_lookup (self , attr , 0 );
501+ mp_obj_t member = mp_obj_class_lookup (NULL , self , attr , 0 );
491502 if (member != MP_OBJ_NULL ) {
492503 // check if the methods are functions, static or class methods
493504 // see http://docs.python.org/3.3/howto/descriptor.html
@@ -641,7 +652,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
641652 mp_obj_tuple_get (type -> bases_tuple , & len , & items );
642653 for (uint i = 0 ; i < len ; i ++ ) {
643654 assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
644- mp_obj_t member = mp_obj_class_lookup ((mp_obj_type_t * )items [i ], attr , 0 );
655+ mp_obj_t member = mp_obj_class_lookup (self -> obj , (mp_obj_type_t * )items [i ], attr , 0 );
645656 if (member != MP_OBJ_NULL ) {
646657 class_convert_return_attr (self -> obj , member , dest );
647658 return ;
0 commit comments