Commit 64131f32 authored by Damien George's avatar Damien George
Browse files

Add staticmethod and classmethod to builtin namespace.

parent ddaf6c11
......@@ -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);
......
......@@ -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)
......
......@@ -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) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment