diff options
Diffstat (limited to 'py/objclass.c')
-rw-r--r-- | py/objclass.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/py/objclass.c b/py/objclass.c new file mode 100644 index 0000000000..52e43724f7 --- /dev/null +++ b/py/objclass.c @@ -0,0 +1,85 @@ +#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_class_t { + mp_obj_base_t base; + mp_map_t *locals; +} mp_obj_class_t; + +// args are in reverse order in the array +mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + // instantiate an instance of a class + + mp_obj_class_t *self = self_in; + + // make instance + mp_obj_t o = mp_obj_new_instance(self_in); + + // look for __init__ function + mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, qstr_from_str_static("__init__"), false); + + if (init_fn != NULL) { + // call __init__ function + mp_obj_t init_ret; + if (n_args == 0) { + init_ret = rt_call_function_n(init_fn->value, 1, (mp_obj_t*)&o); + } else { + mp_obj_t *args2 = m_new(mp_obj_t, n_args + 1); + memcpy(args2, args, n_args * sizeof(mp_obj_t)); + args2[n_args] = o; + init_ret = rt_call_function_n(init_fn->value, n_args + 1, args2); + m_free(args2); + } + if (init_ret != mp_const_none) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); + } + + } else { + // TODO + if (n_args != 0) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args)); + } + } + + return o; +} + +mp_map_t *mp_obj_class_get_locals(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &class_type)); + mp_obj_class_t *self = self_in; + return self->locals; +} + +const mp_obj_type_t class_type = { + { &mp_const_type }, + "class", + NULL, // print + class_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_class(mp_map_t *class_locals) { + mp_obj_class_t *o = m_new_obj(mp_obj_class_t); + o->base.type = &class_type; + o->locals = class_locals; + return o; +} + +// temporary way of making C modules +// hack: use class to mimic a module +mp_obj_t mp_module_new(void) { + return mp_obj_new_class(mp_map_new(MP_MAP_QSTR, 0)); +} |