diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/obj.h | 11 | ||||
-rw-r--r-- | py/objmodule.c | 48 | ||||
-rw-r--r-- | py/runtime.c | 16 |
3 files changed, 70 insertions, 5 deletions
@@ -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))); } |