Add module object, to be used eventually for import.
diff --git a/py/runtime.c b/py/runtime.c
index c3b3d74..3fae61f 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -779,11 +779,19 @@
if (MP_OBJ_IS_TYPE(base, &class_type)) {
mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(base), attr, false);
if (elem == NULL) {
- nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
+ // TODO what about generic method lookup?
+ goto no_attr;
}
return elem->value;
} else if (MP_OBJ_IS_TYPE(base, &instance_type)) {
return mp_obj_instance_load_attr(base, attr);
+ } else if (MP_OBJ_IS_TYPE(base, &module_type)) {
+ mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_module_get_globals(base), attr, false);
+ if (elem == NULL) {
+ // TODO what about generic method lookup?
+ goto no_attr;
+ }
+ return elem->value;
} else if (MP_OBJ_IS_OBJ(base)) {
// generic method lookup
mp_obj_base_t *o = base;
@@ -794,6 +802,8 @@
}
}
}
+
+no_attr:
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
@@ -832,6 +842,10 @@
mp_qstr_map_lookup(locals, attr, true)->value = value;
} else if (MP_OBJ_IS_TYPE(base, &instance_type)) {
mp_obj_instance_store_attr(base, attr, value);
+ } else if (MP_OBJ_IS_TYPE(base, &module_type)) {
+ // TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
+ mp_map_t *globals = mp_obj_module_get_globals(base);
+ mp_qstr_map_lookup(globals, attr, true)->value = value;
} else {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}