Browse Source

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 .
pull/197/head
Paul Sokolovsky 11 years ago
parent
commit
d720ab5236
  1. 7
      py/builtinimport.c
  2. 1
      py/obj.h
  3. 22
      py/objmodule.c

7
py/builtinimport.c

@ -28,8 +28,13 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
}
*/
// find the file to import
qstr mod_name = mp_obj_get_qstr(args[0]);
mp_obj_t loaded = mp_obj_module_get(mod_name);
if (loaded != MP_OBJ_NULL) {
return loaded;
}
// find the file to import
mp_lexer_t *lex = mp_import_open_file(mod_name);
if (lex == NULL) {
// TODO handle lexer error correctly

1
py/obj.h

@ -356,6 +356,7 @@ extern const mp_obj_type_t gen_instance_type;
// module
extern const mp_obj_type_t module_type;
mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_t mp_obj_module_get(qstr module_name);
struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
// staticmethod and classmethod types; defined here so we can make const versions

22
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;

Loading…
Cancel
Save