summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/obj.h11
-rw-r--r--py/objmodule.c48
-rw-r--r--py/runtime.c16
3 files changed, 70 insertions, 5 deletions
diff --git a/py/obj.h b/py/obj.h
index 839209a405..6a0cefd915 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -87,9 +87,9 @@ struct _mp_obj_type_t {
dynamic_type instance
compare_op
- load_attr instance class list
+ load_attr module instance class list
load_method instance str gen list user
- store_attr instance class
+ store_attr module instance class
store_subscr list dict
len str tuple list map
@@ -147,6 +147,7 @@ mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth);
mp_obj_t mp_obj_new_class(struct _mp_map_t *class_locals);
mp_obj_t mp_obj_new_instance(mp_obj_t clas);
+mp_obj_t mp_obj_new_module(qstr module_name);
const char *mp_obj_get_type_str(mp_obj_t o_in);
@@ -238,5 +239,7 @@ mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr);
void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value);
-// temporary way of making C modules
-mp_obj_t mp_module_new(void);
+// module
+extern const mp_obj_type_t module_type;
+mp_obj_t mp_obj_new_module(qstr module_name);
+struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
diff --git a/py/objmodule.c b/py/objmodule.c
new file mode 100644
index 0000000000..addab14b75
--- /dev/null
+++ b/py/objmodule.c
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "obj.h"
+#include "runtime.h"
+#include "map.h"
+
+typedef struct _mp_obj_module_t {
+ mp_obj_base_t base;
+ qstr name;
+ mp_map_t *globals;
+} mp_obj_module_t;
+
+void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
+ mp_obj_module_t *self = self_in;
+ print(env, "<module '%s' from '-unknown-file-'>", qstr_str(self->name));
+}
+
+const mp_obj_type_t module_type = {
+ { &mp_const_type },
+ "module",
+ module_print, // print
+ NULL, // call_n
+ NULL, // unary_op
+ NULL, // binary_op
+ NULL, // getiter
+ NULL, // iternext
+ {{NULL, NULL},}, // method list
+};
+
+mp_obj_t mp_obj_new_module(qstr module_name) {
+ mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
+ o->base.type = &module_type;
+ o->name = module_name;
+ o->globals = mp_map_new(MP_MAP_QSTR, 0);
+ return o;
+}
+
+mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) {
+ assert(MP_OBJ_IS_TYPE(self_in, &module_type));
+ mp_obj_module_t *self = self_in;
+ return self->globals;
+}
diff --git a/py/runtime.c b/py/runtime.c
index c3b3d74259..3fae61f6fe 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -779,11 +779,19 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
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 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
}
}
}
+
+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 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
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)));
}