Skip to content

Commit 443857d

Browse files
committed
objtype: Add support for looking up non-method attrs in native base class.
1 parent 4f46c44 commit 443857d

1 file changed

Lines changed: 26 additions & 15 deletions

File tree

py/objtype.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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
124135
STATIC 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

422433
STATIC 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

Comments
 (0)