blob: 15ccd68ac2ff491a6ab96d5210a7b14a27582c11 [file] [log] [blame]
Damien George28708622014-01-02 21:30:26 +00001#include <stdlib.h>
Damien George28708622014-01-02 21:30:26 +00002#include <assert.h>
3
4#include "nlr.h"
5#include "misc.h"
6#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00007#include "qstr.h"
Damien George28708622014-01-02 21:30:26 +00008#include "obj.h"
Damien Georgecaac5422014-03-25 14:18:18 +00009#include "objmodule.h"
Damien George28708622014-01-02 21:30:26 +000010#include "runtime.h"
Damien Georgecaac5422014-03-25 14:18:18 +000011#include "builtintables.h"
12
13STATIC mp_map_t mp_loaded_modules_map; // TODO: expose as sys.modules
Damien George28708622014-01-02 21:30:26 +000014
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020015STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
Damien George28708622014-01-02 21:30:26 +000016 mp_obj_module_t *self = self_in;
17 print(env, "<module '%s' from '-unknown-file-'>", qstr_str(self->name));
18}
19
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020020STATIC void module_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
Damien George062478e2014-01-09 20:57:50 +000021 mp_obj_module_t *self = self_in;
Damien George8b0535e2014-04-05 21:53:54 +010022 mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
Damien George062478e2014-01-09 20:57:50 +000023 if (elem != NULL) {
Damien George20006db2014-01-18 14:10:48 +000024 dest[0] = elem->value;
Damien George062478e2014-01-09 20:57:50 +000025 }
26}
27
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020028STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
Damien George062478e2014-01-09 20:57:50 +000029 mp_obj_module_t *self = self_in;
Damien George1d24ea52014-04-08 21:11:49 +010030 if (value == MP_OBJ_NULL) {
31 // delete attribute
32 mp_obj_dict_delete(self->globals, MP_OBJ_NEW_QSTR(attr));
33 } else {
34 // store attribute
35 // TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
36 mp_obj_dict_store(self->globals, MP_OBJ_NEW_QSTR(attr), value);
37 }
Damien George062478e2014-01-09 20:57:50 +000038 return true;
39}
40
Damien George0c36da02014-03-08 15:24:39 +000041const mp_obj_type_t mp_type_module = {
Damien Georgec5966122014-02-15 16:10:44 +000042 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +000043 .name = MP_QSTR_module,
Damien George97209d32014-01-07 15:58:30 +000044 .print = module_print,
Damien George062478e2014-01-09 20:57:50 +000045 .load_attr = module_load_attr,
46 .store_attr = module_store_attr,
Damien George28708622014-01-02 21:30:26 +000047};
48
49mp_obj_t mp_obj_new_module(qstr module_name) {
Damien Georgecaac5422014-03-25 14:18:18 +000050 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);
Paul Sokolovskyd720ab52014-01-20 00:03:34 +020051 // We could error out if module already exists, but let C extensions
52 // add new members to existing modules.
53 if (el->value != MP_OBJ_NULL) {
54 return el->value;
55 }
56
Damien George0c36da02014-03-08 15:24:39 +000057 // create new module object
Damien George28708622014-01-02 21:30:26 +000058 mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
Damien George0c36da02014-03-08 15:24:39 +000059 o->base.type = &mp_type_module;
Damien George28708622014-01-02 21:30:26 +000060 o->name = module_name;
Damien George8b0535e2014-04-05 21:53:54 +010061 o->globals = mp_obj_new_dict(1);
Damien George0c36da02014-03-08 15:24:39 +000062
63 // store __name__ entry in the module
Damien George8b0535e2014-04-05 21:53:54 +010064 mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));
Damien George0c36da02014-03-08 15:24:39 +000065
66 // store the new module into the slot in the global dict holding all modules
67 el->value = o;
68
69 // return the new module
Damien George28708622014-01-02 21:30:26 +000070 return o;
71}
72
Damien George8b0535e2014-04-05 21:53:54 +010073mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in) {
Damien Georgecaac5422014-03-25 14:18:18 +000074 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));
75 mp_obj_module_t *self = self_in;
76 return self->globals;
77}
78
79/******************************************************************************/
80// Global module table and related functions
81
82void mp_module_init(void) {
83 mp_map_init(&mp_loaded_modules_map, 3);
84}
85
86void mp_module_deinit(void) {
87 mp_map_deinit(&mp_loaded_modules_map);
88}
89
90// returns MP_OBJ_NULL if not found
91mp_obj_t mp_module_get(qstr module_name) {
Damien George0c36da02014-03-08 15:24:39 +000092 // lookup module
Damien Georgecaac5422014-03-25 14:18:18 +000093 mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
Damien George0c36da02014-03-08 15:24:39 +000094
Damien George7efc5b32014-04-05 22:36:42 +010095 if (el == NULL) {
96 // module not found, look for builtin module names
97 el = mp_map_lookup((mp_map_t*)&mp_builtin_module_dict_obj.map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
98 if (el == NULL) {
99 return MP_OBJ_NULL;
100 }
Paul Sokolovskyd720ab52014-01-20 00:03:34 +0200101 }
Damien George0c36da02014-03-08 15:24:39 +0000102
Damien George7efc5b32014-04-05 22:36:42 +0100103 // module found, return it
104 return el->value;
Paul Sokolovskyd720ab52014-01-20 00:03:34 +0200105}
106
Damien Georgecaac5422014-03-25 14:18:18 +0000107void mp_module_register(qstr qstr, mp_obj_t module) {
108 mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
Damien George28708622014-01-02 21:30:26 +0000109}