summaryrefslogtreecommitdiff
path: root/py/objmodule.c
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-01-20 00:03:34 +0200
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-01-20 00:38:39 +0200
commitd720ab5236015124a13c09175ed674e565414faa (patch)
tree201a5cca563eaad2e76651add86b8dc4de923c1a /py/objmodule.c
parentf438b936e0edcbc3eab9af6cc3513db1f01ab17e (diff)
Implement modules as singletons Python semantics.
In Python, importing module several times returns same underlying module object. This also fixes import statement handling for builtin modules. There're still issues: 1. CPython exposes set of loaded modules as sys.modules, we may want to do that either. 2. Builtin modules are implicitly imported, which is not really correct. We should separate registering a (builtin) module and importing a module. CPython keeps builtin module names in sys.builtin_module_names .
Diffstat (limited to 'py/objmodule.c')
-rw-r--r--py/objmodule.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/py/objmodule.c b/py/objmodule.c
index e97e73192..fb7842e5a 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -17,6 +17,9 @@ typedef struct _mp_obj_module_t {
mp_map_t *globals;
} mp_obj_module_t;
+// TODO: expose as sys.modules
+static mp_map_t *loaded_modules;
+
static void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_module_t *self = self_in;
print(env, "<module '%s' from '-unknown-file-'>", qstr_str(self->name));
@@ -46,14 +49,33 @@ const mp_obj_type_t module_type = {
};
mp_obj_t mp_obj_new_module(qstr module_name) {
+ if (loaded_modules == NULL) {
+ loaded_modules = mp_map_new(1);
+ }
+ mp_map_elem_t *el = mp_map_lookup(loaded_modules, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
+ // We could error out if module already exists, but let C extensions
+ // add new members to existing modules.
+ if (el->value != MP_OBJ_NULL) {
+ return el->value;
+ }
+
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(1);
+ el->value = o;
mp_map_lookup(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = mp_obj_new_str(module_name);
return o;
}
+mp_obj_t mp_obj_module_get(qstr module_name) {
+ mp_map_elem_t *el = mp_map_lookup(loaded_modules, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
+ if (el == NULL) {
+ return NULL;
+ }
+ return el->value;
+}
+
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;