Commit 6d873adb authored by Travis Hance's avatar Travis Hance Committed by Travis Hance

staticmethod and classmethod

parent 2f4b5238
......@@ -827,5 +827,7 @@ void setupBuiltins() {
builtins_module->giveAttr("complex", complex_cls);
builtins_module->giveAttr("super", super_cls);
builtins_module->giveAttr("property", property_cls);
builtins_module->giveAttr("staticmethod", staticmethod_cls);
builtins_module->giveAttr("classmethod", classmethod_cls);
}
}
......@@ -70,6 +70,44 @@ static Box* propertySet(Box* self, Box* obj, Box* val) {
return None;
}
static Box* staticmethodNew(Box* cls, Box* f) {
RELEASE_ASSERT(cls == staticmethod_cls, "");
return new BoxedStaticmethod(f);
}
static Box* staticmethodGet(Box* self, Box* obj, Box* type) {
RELEASE_ASSERT(self->cls == staticmethod_cls, "");
BoxedStaticmethod* sm = static_cast<BoxedStaticmethod*>(self);
if (sm->sm_callable == NULL) {
raiseExcHelper(RuntimeError, "uninitialized staticmethod object");
}
return sm->sm_callable;
}
static Box* classmethodNew(Box* cls, Box* f) {
RELEASE_ASSERT(cls == classmethod_cls, "");
return new BoxedClassmethod(f);
}
static Box* classmethodGet(Box* self, Box* obj, Box* type) {
RELEASE_ASSERT(self->cls == classmethod_cls, "");
BoxedClassmethod* cm = static_cast<BoxedClassmethod*>(self);
if (cm->cm_callable == NULL) {
raiseExcHelper(RuntimeError, "uninitialized classmethod object");
}
if (type == NULL) {
type = obj->cls;
}
return new BoxedInstanceMethod(type, cm->cm_callable);
}
void setupDescr() {
member_cls->giveAttr("__name__", boxStrConstant("member"));
member_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)memberGet, UNKNOWN, 3)));
......@@ -83,6 +121,21 @@ void setupDescr() {
property_cls->giveAttr("__set__",
new BoxedFunction(boxRTFunction((void*)propertySet, UNKNOWN, 3, 0, false, false)));
property_cls->freeze();
staticmethod_cls->giveAttr("__name__", boxStrConstant("staticmethod"));
staticmethod_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)staticmethodNew, UNKNOWN, 5, 4, false, false),
{ None, None, None, None }));
staticmethod_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)staticmethodGet, UNKNOWN, 3, 0, false, false)));
classmethod_cls->giveAttr("__name__", boxStrConstant("classmethod"));
classmethod_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)classmethodNew, UNKNOWN, 5, 4, false, false),
{ None, None, None, None }));
classmethod_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)classmethodGet, UNKNOWN, 3, 0, false, false)));
}
void teardownDescr() {
......
......@@ -291,7 +291,8 @@ extern "C" void closureGCHandler(GCVisitor* v, Box* b) {
extern "C" {
BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls,
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *member_cls,
*closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *property_cls;
*closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *property_cls, *staticmethod_cls,
*classmethod_cls;
BoxedTuple* EmptyTuple;
......@@ -701,6 +702,8 @@ void setupRuntime() {
closure_cls = new BoxedClass(type_cls, object_cls, &closureGCHandler, offsetof(BoxedClosure, attrs),
sizeof(BoxedClosure), false);
property_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedProperty), false);
staticmethod_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedStaticmethod), false);
classmethod_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedClassmethod), false);
attrwrapper_cls = new BoxedClass(type_cls, object_cls, &AttrWrapper::gcHandler, 0, sizeof(AttrWrapper), false);
STR = typeFromClass(str_cls);
......
......@@ -80,7 +80,8 @@ Box* getSysStdout();
extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls,
*member_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *property_cls;
*member_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *property_cls,
*staticmethod_cls, *classmethod_cls;
}
extern "C" { extern Box* None, *NotImplemented, *True, *False; }
extern "C" {
......@@ -404,6 +405,20 @@ public:
: Box(property_cls), prop_get(get), prop_set(set), prop_del(del), prop_doc(doc) {}
};
class BoxedStaticmethod : public Box {
public:
Box* sm_callable;
BoxedStaticmethod(Box* callable) : Box(staticmethod_cls), sm_callable(callable){};
};
class BoxedClassmethod : public Box {
public:
Box* cm_callable;
BoxedClassmethod(Box* callable) : Box(classmethod_cls), cm_callable(callable){};
};
// TODO is there any particular reason to make this a Box, ie a python-level object?
class BoxedClosure : public Box {
public:
......
class C(object):
@staticmethod
def f(a, b, c, d):
print a, b, c, d
@classmethod
def g(cls, a, b, c, d):
print cls, a, b, c, d
c = C()
c.f(1, 2, 3, 4)
c.g(5, 6, 7, 8)
C.f(9, 10, 11, 12)
C.f(13, 14, 15, 16)
@staticmethod
def f(a, b, c, d):
print a, b, c, d
@classmethod
def g(cls, a, b, c, d):
print cls, a, b, c, d
f.__get__(c, C)(17, 18, 19, 20)
g.__get__(c, C)(21, 22, 23, 24)
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