Add staticmethod and classmethod to builtin namespace.
This commit is contained in:
parent
ddaf6c112c
commit
64131f3215
19
py/obj.h
19
py/obj.h
@ -66,11 +66,11 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
|
||||
// These macros are used to declare and define constant staticmethond and classmethod objects
|
||||
// You can put "static" in front of the definitions to make them local
|
||||
|
||||
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_staticmethod_t obj_name
|
||||
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_classmethod_t obj_name
|
||||
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_static_class_method_t obj_name
|
||||
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_static_class_method_t obj_name
|
||||
|
||||
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_staticmethod_t obj_name = {{&mp_type_staticmethod}, fun_name}
|
||||
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_classmethod_t obj_name = {{&mp_type_classmethod}, fun_name}
|
||||
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_static_class_method_t obj_name = {{&mp_type_staticmethod}, fun_name}
|
||||
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_static_class_method_t obj_name = {{&mp_type_classmethod}, fun_name}
|
||||
|
||||
// Need to declare this here so we are not dependent on map.h
|
||||
struct _mp_map_t;
|
||||
@ -180,7 +180,6 @@ struct _mp_obj_type_t {
|
||||
abs float complex
|
||||
hash bool int none str
|
||||
equal int str
|
||||
less int
|
||||
get_array_n tuple list
|
||||
|
||||
unpack seq list tuple
|
||||
@ -389,15 +388,11 @@ struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
|
||||
extern const mp_obj_type_t mp_type_staticmethod;
|
||||
extern const mp_obj_type_t mp_type_classmethod;
|
||||
|
||||
typedef struct _mp_obj_staticmethod_t {
|
||||
// this structure is used for instances of both staticmethod and classmethod
|
||||
typedef struct _mp_obj_static_class_method_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t fun;
|
||||
} mp_obj_staticmethod_t;
|
||||
|
||||
typedef struct _mp_obj_classmethod_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t fun;
|
||||
} mp_obj_classmethod_t;
|
||||
} mp_obj_static_class_method_t;
|
||||
|
||||
// sequence helpers
|
||||
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);
|
||||
|
26
py/objtype.c
26
py/objtype.c
@ -212,10 +212,10 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
// TODO check that this is the correct place to have this logic
|
||||
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
|
||||
// return just the function
|
||||
dest[0] = ((mp_obj_staticmethod_t*)member)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_classmethod_t*)member)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
dest[1] = mp_obj_get_type(self_in);
|
||||
} else {
|
||||
// return a bound method, with self being this object
|
||||
@ -304,10 +304,10 @@ static void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
// see http://docs.python.org/3.3/howto/descriptor.html
|
||||
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
|
||||
// return just the function
|
||||
dest[0] = ((mp_obj_staticmethod_t*)member)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
|
||||
// return a bound method, with self being this class
|
||||
dest[0] = ((mp_obj_classmethod_t*)member)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
dest[1] = self_in;
|
||||
} else {
|
||||
// return just the function
|
||||
@ -417,10 +417,10 @@ static void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
// TODO check that this is the correct place to have this logic
|
||||
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
|
||||
// return just the function
|
||||
dest[0] = ((mp_obj_staticmethod_t*)member)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_classmethod_t*)member)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
|
||||
dest[1] = mp_obj_get_type(self->obj);
|
||||
} else {
|
||||
// return a bound method, with self being this object
|
||||
@ -507,12 +507,26 @@ MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
|
||||
/******************************************************************************/
|
||||
// staticmethod and classmethod types (probably should go in a different file)
|
||||
|
||||
static mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);
|
||||
|
||||
if (n_args != 1 || n_kw != 0) {
|
||||
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "function takes 1 positional argument but %d were given", (void*)(machine_int_t)n_args));
|
||||
}
|
||||
|
||||
mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
|
||||
*o = (mp_obj_static_class_method_t){{(mp_obj_type_t*)self_in}, args[0]};
|
||||
return o;
|
||||
}
|
||||
|
||||
const mp_obj_type_t mp_type_staticmethod = {
|
||||
{ &mp_const_type },
|
||||
"staticmethod",
|
||||
.make_new = static_class_method_make_new
|
||||
};
|
||||
|
||||
const mp_obj_type_t mp_type_classmethod = {
|
||||
{ &mp_const_type },
|
||||
"classmethod",
|
||||
.make_new = static_class_method_make_new
|
||||
};
|
||||
|
@ -51,6 +51,7 @@ Q(bytearray)
|
||||
Q(bytes)
|
||||
Q(callable)
|
||||
Q(chr)
|
||||
Q(classmethod)
|
||||
Q(complex)
|
||||
Q(dict)
|
||||
Q(dir)
|
||||
@ -80,6 +81,7 @@ Q(range)
|
||||
Q(repr)
|
||||
Q(set)
|
||||
Q(sorted)
|
||||
Q(staticmethod)
|
||||
Q(sum)
|
||||
Q(super)
|
||||
Q(str)
|
||||
|
11
py/runtime.c
11
py/runtime.c
@ -134,6 +134,9 @@ void rt_init(void) {
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_type, (mp_obj_t)&mp_const_type);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_zip, (mp_obj_t)&zip_type);
|
||||
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_staticmethod, (mp_obj_t)&mp_type_staticmethod);
|
||||
|
||||
mp_obj_t m_array = mp_obj_new_module(MP_QSTR_array);
|
||||
rt_store_attr(m_array, MP_QSTR_array, (mp_obj_t)&array_type);
|
||||
|
||||
@ -876,10 +879,10 @@ static void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
|
||||
// see http://docs.python.org/3.3/howto/descriptor.html
|
||||
if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_staticmethod)) {
|
||||
// return just the function
|
||||
dest[0] = ((mp_obj_staticmethod_t*)meth->fun)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
|
||||
} else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) {
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_classmethod_t*)meth->fun)->fun;
|
||||
dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
|
||||
dest[1] = mp_obj_get_type(base);
|
||||
} else {
|
||||
// return a bound method, with self being this object
|
||||
@ -970,6 +973,8 @@ mp_obj_t rt_iternext(mp_obj_t o_in) {
|
||||
}
|
||||
|
||||
mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
|
||||
DEBUG_printf("import name %s\n", qstr_str(name));
|
||||
|
||||
// build args array
|
||||
mp_obj_t args[5];
|
||||
args[0] = MP_OBJ_NEW_QSTR(name);
|
||||
@ -983,6 +988,8 @@ mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
|
||||
}
|
||||
|
||||
mp_obj_t rt_import_from(mp_obj_t module, qstr name) {
|
||||
DEBUG_printf("import from %p %s\n", module, qstr_str(name));
|
||||
|
||||
mp_obj_t x = rt_load_attr(module, name);
|
||||
/* TODO convert AttributeError to ImportError
|
||||
if (fail) {
|
||||
|
Loading…
Reference in New Issue
Block a user