diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2019-01-14 15:14:40 -0800 |
|---|---|---|
| committer | Scott Shawcroft <scott@tannewt.org> | 2019-01-14 17:29:19 -0800 |
| commit | 72d993d60c5e5238942491df00776ca31f9758a1 (patch) | |
| tree | 7dc8ff9548dc5c5fe4286414eb361c61b0774306 /py/objtype.c | |
| parent | 619bc4caae15ceb7b6de547a5264c9eca9086fe9 (diff) | |
py changes for supporting superclass constructors that take kwargs
Diffstat (limited to 'py/objtype.c')
| -rw-r--r-- | py/objtype.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/py/objtype.c b/py/objtype.c index 95dfc2a15..f7fe3b3f6 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -50,7 +50,7 @@ #define TYPE_FLAG_IS_SUBCLASSED (0x0001) #define TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) -STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); +STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); /******************************************************************************/ // instance object @@ -90,14 +90,14 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t // This wrapper function is allows a subclass of a native type to call the // __init__() method (corresponding to type->make_new) of the native type. -STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) { - mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]); +STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_obj_instance_t *self = MP_OBJ_TO_PTR(pos_args[0]); const mp_obj_type_t *native_base = NULL; instance_count_native_bases(self->base.type, &native_base); - self->subobj[0] = native_base->make_new(native_base, n_args - 1, 0, args + 1); + self->subobj[0] = native_base->make_new(native_base, n_args - 1, pos_args + 1, kw_args); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(native_base_init_wrapper_obj, 1, native_base_init_wrapper); #if !MICROPY_CPYTHON_COMPAT STATIC @@ -281,7 +281,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self); } -mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { +mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { assert(mp_obj_is_instance_type(self)); // look for __new__ function @@ -297,6 +297,10 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size const mp_obj_type_t *native_base = NULL; mp_obj_instance_t *o; + size_t n_kw = 0; + if (kw_args != 0) { + n_kw = kw_args->used; + } if (init_fn[0] == MP_OBJ_NULL || init_fn[0] == MP_OBJ_SENTINEL) { // Either there is no __new__() method defined or there is a native // constructor. In both cases create a blank instance. @@ -315,9 +319,12 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)}; new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2); } else { + // TODO(tannewt): Could this be on the stack? It's deleted below. mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw); args2[0] = MP_OBJ_FROM_PTR(self); - memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); + memcpy(args2 + 1, args, n_args * sizeof(mp_obj_t)); + // copy in kwargs + memcpy(args2 + 1 + n_args, kw_args->table, 2 * n_kw * sizeof(mp_obj_t)); new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2); m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw); } @@ -343,13 +350,16 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size mp_obj_class_lookup(&lookup, self); if (init_fn[0] != MP_OBJ_NULL) { mp_obj_t init_ret; - if (n_args == 0 && n_kw == 0) { + if (n_args == 0 && kw_args == NULL) { init_ret = mp_call_method_n_kw(0, 0, init_fn); } else { + // TODO(tannewt): Could this be on the stack? It's deleted below. mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw); args2[0] = init_fn[0]; args2[1] = init_fn[1]; - memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); + // copy in kwargs + memcpy(args2 + 2, args, n_args * sizeof(mp_obj_t)); + memcpy(args2 + 2 + n_args, kw_args->table, 2 * n_kw * sizeof(mp_obj_t)); init_ret = mp_call_method_n_kw(n_args, n_kw, args2); m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw); } @@ -367,7 +377,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size // If the type had a native base that was not explicitly initialised // (constructed) by the Python __init__() method then construct it now. if (native_base != NULL && o->subobj[0] == MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj)) { - o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args); + o->subobj[0] = native_base->make_new(native_base, n_args, args, kw_args); } return MP_OBJ_FROM_PTR(o); @@ -959,10 +969,10 @@ STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ mp_printf(print, "<class '%q'>", self->name); } -STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { (void)type_in; - mp_arg_check_num(n_args, n_kw, 1, 3, false); + mp_arg_check_num(n_args, kw_args, 1, 3, false); switch (n_args) { case 1: @@ -992,8 +1002,10 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp } } - // make new instance - mp_obj_t o = self->make_new(self, n_args, n_kw, args); + // create a map directly from the given args array and make a new instance + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + mp_obj_t o = self->make_new(self, n_args, args, &kw_args); // return new instance return o; @@ -1170,7 +1182,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // __new__ slot exists; check if it is a function if (MP_OBJ_IS_FUN(elem->value)) { // __new__ is a function, wrap it in a staticmethod decorator - elem->value = static_class_method_make_new(&mp_type_staticmethod, 1, 0, &elem->value); + elem->value = static_class_method_make_new(&mp_type_staticmethod, 1, &elem->value, NULL); } } @@ -1196,11 +1208,11 @@ STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind mp_print_str(print, ">"); } -STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { (void)type_in; // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented - mp_arg_check_num(n_args, n_kw, 2, 2, false); + mp_arg_check_num(n_args, kw_args, 2, 2, false); if(!MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { mp_raise_TypeError(translate("first argument to super() must be type")); } @@ -1394,11 +1406,14 @@ STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) { MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance); -mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type) { +mp_obj_t mp_instance_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type) { mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self_type), native_type)) { return MP_OBJ_NULL; } + if (MP_OBJ_FROM_PTR(self_type) == native_type) { + return self_in; + } mp_obj_instance_t *self = (mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in); return self->subobj[0]; } @@ -1406,10 +1421,10 @@ mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t /******************************************************************************/ // staticmethod and classmethod types (probably should go in a different file) -STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { assert(self == &mp_type_staticmethod || self == &mp_type_classmethod); - mp_arg_check_num(n_args, n_kw, 1, 1, false); + mp_arg_check_num(n_args, kw_args, 1, 1, false); mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t); *o = (mp_obj_static_class_method_t){{self}, args[0]}; |
