Commit fd353841 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Basic super() implementation

parent 009e735d
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "runtime/long.h" #include "runtime/long.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
#include "runtime/super.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -699,5 +700,6 @@ void setupBuiltins() { ...@@ -699,5 +700,6 @@ void setupBuiltins() {
builtins_module->giveAttr("tuple", tuple_cls); builtins_module->giveAttr("tuple", tuple_cls);
builtins_module->giveAttr("instancemethod", instancemethod_cls); builtins_module->giveAttr("instancemethod", instancemethod_cls);
builtins_module->giveAttr("complex", complex_cls); builtins_module->giveAttr("complex", complex_cls);
builtins_module->giveAttr("super", super_cls);
} }
} }
...@@ -169,12 +169,7 @@ Box* instanceGetattribute(Box* _inst, Box* _attr) { ...@@ -169,12 +169,7 @@ Box* instanceGetattribute(Box* _inst, Box* _attr) {
r = classLookup(inst->inst_cls, attr->s); r = classLookup(inst->inst_cls, attr->s);
if (r) { if (r) {
static const std::string get_str("__get__"); return processDescriptor(r, inst, inst->inst_cls);
Box* descr_r = callattrInternal(r, &get_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(2), inst,
inst->inst_cls, NULL, NULL, NULL);
if (descr_r)
return descr_r;
return r;
} }
RELEASE_ASSERT(!r, ""); RELEASE_ASSERT(!r, "");
......
...@@ -901,6 +901,20 @@ RELEASE_ASSERT(gotten, "%s:%s", getTypeName(obj)->c_str(), attr); ...@@ -901,6 +901,20 @@ RELEASE_ASSERT(gotten, "%s:%s", getTypeName(obj)->c_str(), attr);
return gotten; return gotten;
} }
// Does a simple call of the descriptor's __get__ if it exists;
// this function is useful for custom getattribute implementations that already know whether the descriptor
// came from the class or not.
Box* processDescriptor(Box* obj, Box* inst, Box* owner) {
static const std::string get_str("__get__");
Box* descr_r
= callattrInternal(obj, &get_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(2), inst, owner, NULL, NULL, NULL);
if (descr_r)
return descr_r;
return obj;
}
static Box* (*runtimeCall0)(Box*, ArgPassSpec) = (Box * (*)(Box*, ArgPassSpec))runtimeCall; static Box* (*runtimeCall0)(Box*, ArgPassSpec) = (Box * (*)(Box*, ArgPassSpec))runtimeCall;
static Box* (*runtimeCall1)(Box*, ArgPassSpec, Box*) = (Box * (*)(Box*, ArgPassSpec, Box*))runtimeCall; static Box* (*runtimeCall1)(Box*, ArgPassSpec, Box*) = (Box * (*)(Box*, ArgPassSpec, Box*))runtimeCall;
static Box* (*runtimeCall2)(Box*, ArgPassSpec, Box*, Box*) = (Box * (*)(Box*, ArgPassSpec, Box*, Box*))runtimeCall; static Box* (*runtimeCall2)(Box*, ArgPassSpec, Box*, Box*) = (Box * (*)(Box*, ArgPassSpec, Box*, Box*))runtimeCall;
......
...@@ -121,6 +121,8 @@ Box* typeCall(Box*, BoxedList*); ...@@ -121,6 +121,8 @@ Box* typeCall(Box*, BoxedList*);
Box* typeNew(Box* cls, Box* arg1, Box* arg2, Box** _args); Box* typeNew(Box* cls, Box* arg1, Box* arg2, Box** _args);
bool isUserDefined(BoxedClass* cls); bool isUserDefined(BoxedClass* cls);
Box* processDescriptor(Box* obj, Box* inst, Box* owner);
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure, Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
BoxedGenerator* generator, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs); BoxedGenerator* generator, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs);
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "runtime/super.h"
#include <sstream>
#include "codegen/compvars.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
namespace pyston {
BoxedClass* super_cls;
class BoxedSuper : public Box {
public:
// These definitions+names are taken from CPython; not sure I understand it well enough yet
BoxedClass* type; // "the class invoking super()"
Box* obj; // "the instance invoking super(); make be None"
BoxedClass* obj_type; // "the type of the instance invoking super(); may be None"
BoxedSuper(BoxedClass* type, Box* obj, BoxedClass* obj_type)
: Box(super_cls), type(type), obj(obj), obj_type(obj_type) {}
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == super_cls);
BoxedSuper* o = static_cast<BoxedSuper*>(_o);
boxGCHandler(v, o);
v->visit(o->type);
if (o->obj)
v->visit(o->obj);
if (o->obj_type)
v->visit(o->obj_type);
}
};
Box* superGetattribute(Box* _s, Box* _attr) {
RELEASE_ASSERT(_s->cls == super_cls, "");
BoxedSuper* s = static_cast<BoxedSuper*>(_s);
RELEASE_ASSERT(_attr->cls == str_cls, "");
BoxedString* attr = static_cast<BoxedString*>(_attr);
bool skip = s->obj_type == NULL;
if (!skip) {
// Looks like __class__ is supposed to be "super", not the class of the the proxied object.
skip = (attr->s == "__class__");
}
if (!skip) {
// We don't support multiple inheritance yet, so the lookup order is simple:
Box* r = typeLookup(s->type->base, attr->s, NULL);
if (r) {
return processDescriptor(r, s->obj, s->obj_type);
}
}
RELEASE_ASSERT(0, "should call the equivalent of objectGetattr here");
}
// TODO I think this functionality is supposed to be in the __init__ function:
Box* superNew(Box* _cls, Box* _type, Box* inst) {
RELEASE_ASSERT(_cls == super_cls, "");
if (!isSubclass(_type->cls, type_cls))
raiseExcHelper(TypeError, "must be type, not %s", getTypeName(_type)->c_str());
BoxedClass* type = static_cast<BoxedClass*>(_type);
BoxedClass* ob_type = NULL;
if (inst != NULL) {
if (!isSubclass(inst->cls, type)) {
// The "inst" object can be a subtype of "type"/
RELEASE_ASSERT(isSubclass(inst->cls, type_cls) && isSubclass(static_cast<BoxedClass*>(inst), type),
"unimplemented");
raiseExcHelper(TypeError, "super(type, obj): obj must be an instance or subtype of type");
}
ob_type = inst->cls;
}
// TODO the actual behavior for ob_type looks more complex
return new BoxedSuper(type, inst, ob_type);
}
void setupSuper() {
super_cls = new BoxedClass(type_cls, object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false);
super_cls->giveAttr("__name__", boxStrConstant("super"));
super_cls->giveAttr("__getattribute__", new BoxedFunction(boxRTFunction((void*)superGetattribute, UNKNOWN, 2)));
super_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)superNew, UNKNOWN, 3, 1, false, false), { NULL }));
super_cls->freeze();
}
}
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_SUPER_H
#define PYSTON_RUNTIME_SUPER_H
namespace pyston {
void setupSuper();
class BoxedClass;
extern BoxedClass* super_cls;
}
#endif
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "runtime/long.h" #include "runtime/long.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
#include "runtime/super.h"
extern "C" void initerrno(); extern "C" void initerrno();
extern "C" void init_sha(); extern "C" void init_sha();
...@@ -765,6 +766,7 @@ void setupRuntime() { ...@@ -765,6 +766,7 @@ void setupRuntime() {
setupGenerator(); setupGenerator();
setupIter(); setupIter();
setupClassobj(); setupClassobj();
setupSuper();
function_cls->giveAttr("__name__", boxStrConstant("function")); function_cls->giveAttr("__name__", boxStrConstant("function"));
function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, STR, 1))); function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, STR, 1)));
......
...@@ -62,6 +62,41 @@ def f3(): ...@@ -62,6 +62,41 @@ def f3():
print a.foo() print a.foo()
f3() f3()
def f4():
print
print "f4"
class C(object):
A = 1
def __init__(self, n):
super(C, self).__init__()
self.n = n
def foo(self):
print "C.foo()", self.n
class D(C):
A = 2
def __init__(self, n, m):
super(D, self).__init__(n)
self.m = m
def foo(self):
super(D, self).foo()
print "D.foo()", self.m
c = C(1)
d = D(1, 2)
c.foo()
d.foo()
C.foo(c)
C.foo(d)
print c.A
print d.A
print super(D, d).A
f4()
print isinstance(1, int) print isinstance(1, int)
print isinstance(1, object) print isinstance(1, object)
print isinstance(1, float) print isinstance(1, float)
......
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