Commit c3f1126e authored by Damien George's avatar Damien George
Browse files

py: Fix logic bugs in object attribute/method extraction.

parent 6022d9d4
...@@ -30,24 +30,13 @@ STATIC mp_obj_t mp_obj_new_class(mp_obj_t class) { ...@@ -30,24 +30,13 @@ STATIC mp_obj_t mp_obj_new_class(mp_obj_t class) {
STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) { STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) {
for (;;) { for (;;) {
if (type->locals_dict != NULL) { if (type->locals_dict != NULL) {
// search locals_dict (the dynamically created set of methods/attributes) // search locals_dict (the set of methods/attributes)
assert(MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)); // Micro Python restriction, for now assert(MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)); // Micro Python restriction, for now
mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict); mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) { if (elem != NULL) {
return elem->value; return elem->value;
} }
/*
} else if (type->methods != NULL) {
// search methods (the const set of methods)
for (const mp_method_t *meth = type->methods; meth->name != MP_QSTR_NULL; meth++) {
if (meth->name == attr) {
return (mp_obj_t)meth->fun;
}
}
*/
} }
// attribute not found, keep searching base classes // attribute not found, keep searching base classes
...@@ -220,24 +209,20 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { ...@@ -220,24 +209,20 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
} }
mp_obj_t member = mp_obj_class_lookup(self->base.type, attr); mp_obj_t member = mp_obj_class_lookup(self->base.type, attr);
if (member != MP_OBJ_NULL) { if (member != MP_OBJ_NULL) {
if (mp_obj_is_callable(member)) { // check if the methods are functions, static or class methods
// class member is callable so build a bound method // see http://docs.python.org/3.3/howto/descriptor.html
// check if the methods are functions, static or class methods // TODO check that this is the correct place to have this logic
// see http://docs.python.org/3.3/howto/descriptor.html if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
// TODO check that this is the correct place to have this logic // return just the function
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
// return just the function } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
dest[0] = ((mp_obj_static_class_method_t*)member)->fun; // return a bound method, with self being the type of this object
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
// return a bound method, with self being the type of this object dest[1] = mp_obj_get_type(self_in);
dest[0] = ((mp_obj_static_class_method_t*)member)->fun; } else if (mp_obj_is_callable(member)) {
dest[1] = mp_obj_get_type(self_in); // return a bound method, with self being this object
} else { dest[0] = member;
// return a bound method, with self being this object dest[1] = self_in;
dest[0] = member;
dest[1] = self_in;
}
return;
} else { } else {
// class member is a value, so just return that value // class member is a value, so just return that value
dest[0] = member; dest[0] = member;
...@@ -425,29 +410,25 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { ...@@ -425,29 +410,25 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_t member = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr); mp_obj_t member = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr);
if (member != MP_OBJ_NULL) { if (member != MP_OBJ_NULL) {
// XXX this and the code in class_load_attr need to be factored out // XXX this and the code in class_load_attr need to be factored out
if (mp_obj_is_callable(member)) { // check if the methods are functions, static or class methods
// class member is callable so build a bound method // see http://docs.python.org/3.3/howto/descriptor.html
// check if the methods are functions, static or class methods // TODO check that this is the correct place to have this logic
// see http://docs.python.org/3.3/howto/descriptor.html if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
// TODO check that this is the correct place to have this logic // return just the function
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
// return just the function } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
dest[0] = ((mp_obj_static_class_method_t*)member)->fun; // return a bound method, with self being the type of this object
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
// return a bound method, with self being the type of this object dest[1] = mp_obj_get_type(self->obj);
dest[0] = ((mp_obj_static_class_method_t*)member)->fun; } if (mp_obj_is_callable(member)) {
dest[1] = mp_obj_get_type(self->obj); // return a bound method, with self being this object
} else { dest[0] = member;
// return a bound method, with self being this object dest[1] = self->obj;
dest[0] = member;
dest[1] = self->obj;
}
return;
} else { } else {
// class member is a value, so just return that value // class member is a value, so just return that value
dest[0] = member; dest[0] = member;
return;
} }
return;
} }
} }
} }
......
...@@ -859,10 +859,13 @@ STATIC void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) { ...@@ -859,10 +859,13 @@ STATIC void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
// return a bound method, with self being the type of this object // return a bound method, with self being the type of this object
dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun; dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
dest[1] = mp_obj_get_type(base); dest[1] = mp_obj_get_type(base);
} else { } else if (mp_obj_is_callable(elem->value)) {
// return a bound method, with self being this object // return a bound method, with self being this object
dest[0] = (mp_obj_t)elem->value; dest[0] = elem->value;
dest[1] = base; dest[1] = base;
} else {
// class member is a value, so just return that value
dest[0] = elem->value;
} }
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment