Commit 23b7712d authored by Kevin Modzelewski's avatar Kevin Modzelewski

Implement basic old-style instance functionality

Not going to be very performant -- hopefully that won't matter.
parent d84100af
......@@ -50,8 +50,6 @@ def _g():
yield 1
GeneratorType = type(_g())
# Pyston change: we do not support old-style classes yet
"""
class _C:
def _m(self): pass
ClassType = type(_C)
......@@ -59,7 +57,6 @@ UnboundMethodType = type(_C._m) # Same as MethodType
_x = _C()
InstanceType = type(_x)
MethodType = type(_x._m)
"""
BuiltinFunctionType = type(len)
BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
......@@ -92,5 +89,4 @@ NotImplementedType = type(NotImplemented)
# GetSetDescriptorType = type(FunctionType.func_code)
# MemberDescriptorType = type(FunctionType.func_globals)
# Pyston change: had to change this to match above changes
del sys, _f, _g, #_C, _x # Not for export
del sys, _f, _g, _C, _x # Not for export
......@@ -60,6 +60,21 @@ public:
}
};
static Box* classLookup(BoxedClassobj* cls, const std::string& attr) {
Box* r = cls->getattr(attr);
if (r)
return r;
for (auto b : cls->bases->elts) {
RELEASE_ASSERT(b->cls == classobj_cls, "");
Box* r = classLookup(static_cast<BoxedClassobj*>(b), attr);
if (r)
return r;
}
return NULL;
}
Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "classobj.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
......@@ -101,12 +116,28 @@ Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) {
Box* classobjCall(Box* _cls, Box* _args, Box* _kwargs) {
assert(_cls->cls == classobj_cls);
BoxedClassobj* cls = static_cast<BoxedClassobj*>(_cls);
assert(_args->cls == tuple_cls);
BoxedTuple* args = static_cast<BoxedTuple*>(_args);
assert(_kwargs->cls == dict_cls);
BoxedDict* kwargs = static_cast<BoxedDict*>(_kwargs);
BoxedClassobj* cls = static_cast<BoxedClassobj*>(_cls);
BoxedInstance* made = new BoxedInstance(cls);
static const std::string init_str("__init__");
Box* init_func = classLookup(cls, init_str);
return new BoxedInstance(cls);
if (init_func) {
Box* init_rtn = runtimeCall(init_func, ArgPassSpec(1, 0, true, true), made, args, kwargs, NULL, NULL);
if (init_rtn != None)
raiseExcHelper(TypeError, "__init__() should return None");
} else {
if (args->elts.size() || kwargs->d.size())
raiseExcHelper(TypeError, "this constructor takes no arguments");
}
return made;
}
Box* classobjStr(Box* _obj) {
......@@ -123,6 +154,51 @@ Box* classobjStr(Box* _obj) {
return boxString(static_cast<BoxedString*>(_mod)->s + "." + cls->name->s);
}
Box* instanceGetattribute(Box* _inst, Box* _attr) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
RELEASE_ASSERT(_attr->cls == str_cls, "");
BoxedString* attr = static_cast<BoxedString*>(_attr);
// TODO: special handling for accessing __dict__ and __class__
Box* r = inst->getattr(attr->s);
if (r)
return r;
r = classLookup(inst->inst_cls, attr->s);
if (r) {
static const std::string get_str("__get__");
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, "");
static const std::string getattr_str("__getattr__");
Box* getattr = classLookup(inst->inst_cls, getattr_str);
RELEASE_ASSERT(getattr == NULL, "unimplemented");
raiseExcHelper(AttributeError, "%s instance has no attribute '%s'", inst->inst_cls->name->s.c_str(),
attr->s.c_str());
}
Box* instanceStr(Box* _inst) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
Box* str_func = instanceGetattribute(inst, boxStrConstant("__str__"));
if (str_func) {
return runtimeCall(str_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} else {
return objectStr(_inst);
}
}
void setupClassobj() {
classobj_cls = new BoxedClass(type_cls, object_cls, &BoxedClassobj::gcHandler, offsetof(BoxedClassobj, attrs),
sizeof(BoxedClassobj), false);
......@@ -144,6 +220,10 @@ void setupClassobj() {
instance_cls->giveAttr("__name__", boxStrConstant("instance"));
instance_cls->giveAttr("__getattribute__",
new BoxedFunction(boxRTFunction((void*)instanceGetattribute, UNKNOWN, 2)));
instance_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)instanceStr, UNKNOWN, 1)));
instance_cls->freeze();
}
}
......@@ -1942,7 +1942,7 @@ extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope
}
}
extern "C" Box* callattr(Box* obj, std::string* attr, bool clsonly, ArgPassSpec argspec, Box* arg1, Box* arg2,
extern "C" Box* callattr(Box* obj, const std::string* attr, bool clsonly, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) {
int npassed_args = argspec.totalPassed();
......
......@@ -50,7 +50,7 @@ extern "C" void setattr(Box* obj, const char* attr, Box* attr_val);
extern "C" void delattr(Box* obj, const char* attr);
extern "C" bool nonzero(Box* obj);
extern "C" Box* runtimeCall(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<const std::string*>*);
extern "C" Box* callattr(Box*, std::string*, bool, ArgPassSpec, Box*, Box*, Box*, Box**,
extern "C" Box* callattr(Box*, const std::string*, bool, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<const std::string*>*);
extern "C" BoxedString* str(Box* obj);
extern "C" BoxedString* repr(Box* obj);
......
......@@ -388,6 +388,14 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return new BoxedString("function");
}
static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == function_cls, "");
if (inst == None)
return boxUnboundInstanceMethod(self);
return boxInstanceMethod(inst, self);
}
extern "C" {
Box* None = NULL;
Box* NotImplemented = NULL;
......@@ -763,6 +771,7 @@ void setupRuntime() {
function_cls->giveAttr("__str__", function_cls->getattr("__repr__"));
function_cls->giveAttr("__module__",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedFunction, modname)));
function_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)functionGet, UNKNOWN, 3)));
function_cls->freeze();
instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod"));
......
......@@ -110,6 +110,8 @@ extern "C" Box* createSlice(Box* start, Box* stop, Box* step);
extern "C" Box* createTuple(int64_t nelts, Box** elts);
extern "C" void printFloat(double d);
Box* objectStr(Box*);
template <class T> class StlCompatAllocator {
public:
......
# allow-warning
# The __future__ module has an old-style class, so we allow warnings for now
"docstring"
from __future__ import division
......
......@@ -7,6 +7,11 @@ print C, type(C)
print map(str, C.__bases__), C.__name__
print type(C())
try:
C(1)
except TypeError, e:
print e
class D(C):
pass
......@@ -28,3 +33,23 @@ except TypeError, e:
print ClassType("test", (), {})
print ClassType("test", (), {"__module__":"fake"})
class E():
def __init__(self, n):
self.n = n
def foo(self):
print self.n
def __str__(self):
return "E(%d)" % self.n
e = E(1)
print e
print e.n
print e.foo()
def str2():
return "str2"
e.__str__ = str2
print e
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