circuitpython/py/objmodule.c
Damien George df6567e634 Merge map.h into obj.h.
Pretty much everyone needs to include map.h, since it's such an integral
part of the Micro Python object implementation.  Thus, the definitions
are now in obj.h instead.  map.h is removed.
2014-03-30 13:54:02 +01:00

102 lines
3.2 KiB
C

#include <stdlib.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objmodule.h"
#include "runtime.h"
#include "builtintables.h"
STATIC mp_map_t mp_loaded_modules_map; // TODO: expose as sys.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));
}
STATIC void module_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_module_t *self = self_in;
mp_map_elem_t *elem = mp_map_lookup(self->globals, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) {
dest[0] = elem->value;
}
}
STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
mp_obj_module_t *self = self_in;
// TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
mp_map_lookup(self->globals, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
return true;
}
const mp_obj_type_t mp_type_module = {
{ &mp_type_type },
.name = MP_QSTR_module,
.print = module_print,
.load_attr = module_load_attr,
.store_attr = module_store_attr,
};
mp_obj_t mp_obj_new_module(qstr module_name) {
mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, 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;
}
// create new module object
mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
o->base.type = &mp_type_module;
o->name = module_name;
o->globals = mp_map_new(1);
// store __name__ entry in the module
mp_map_lookup(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = MP_OBJ_NEW_QSTR(module_name);
// store the new module into the slot in the global dict holding all modules
el->value = o;
// return the new module
return o;
}
mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));
mp_obj_module_t *self = self_in;
return self->globals;
}
/******************************************************************************/
// Global module table and related functions
void mp_module_init(void) {
mp_map_init(&mp_loaded_modules_map, 3);
}
void mp_module_deinit(void) {
mp_map_deinit(&mp_loaded_modules_map);
}
// returns MP_OBJ_NULL if not found
mp_obj_t mp_module_get(qstr module_name) {
// lookup module
mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
// module found, return it
if (el != NULL) {
return el->value;
}
// module not found, look for builtin module names
// it will return MP_OBJ_NULL if nothing found
return mp_builtin_tables_lookup_module(module_name);
}
void mp_module_register(qstr qstr, mp_obj_t module) {
mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
}