Commit 0f43471c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add some more property methods, and fix up some exceptions handling

parent a9dba579
......@@ -473,7 +473,11 @@ public:
struct ExcInfo {
Box* type, *value, *traceback;
#ifndef NDEBUG
ExcInfo(Box* type, Box* value, Box* traceback);
#else
ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {}
#endif
bool matches(BoxedClass* cls) const;
};
......
......@@ -25,7 +25,10 @@ static Box* memberGet(BoxedMemberDescriptor* self, Box* inst, Box* owner) {
return self;
if (self->type == BoxedMemberDescriptor::OBJECT) {
return *(Box**)(((char*)inst) + self->offset);
Box* rtn = *(Box**)(((char*)inst) + self->offset);
if (!rtn)
rtn = None;
return rtn;
}
Py_FatalError("unimplemented");
......@@ -83,6 +86,43 @@ static Box* propertySet(Box* self, Box* obj, Box* val) {
return None;
}
static Box* propertyDel(Box* self, Box* obj) {
return propertySet(self, obj, NULL);
}
static Box* property_copy(BoxedProperty* old, Box* get, Box* set, Box* del) {
// In CPython, I think this can take a subclass of property, and will call the subclass's
// constructor... for now just enforce that it's a property object and inline the constructor:
RELEASE_ASSERT(old->cls == property_cls, "");
if (!get)
get = old->prop_get;
if (!set)
set = old->prop_set;
if (!del)
del = old->prop_del;
return new BoxedProperty(get, set, del, old->prop_doc);
}
static Box* propertyGetter(Box* self, Box* obj) {
RELEASE_ASSERT(self->cls == property_cls, "");
BoxedProperty* prop = static_cast<BoxedProperty*>(self);
return property_copy(prop, obj, NULL, NULL);
}
static Box* propertySetter(Box* self, Box* obj) {
RELEASE_ASSERT(self->cls == property_cls, "");
BoxedProperty* prop = static_cast<BoxedProperty*>(self);
return property_copy(prop, NULL, obj, NULL);
}
static Box* propertyDeleter(Box* self, Box* obj) {
RELEASE_ASSERT(self->cls == property_cls, "");
BoxedProperty* prop = static_cast<BoxedProperty*>(self);
return property_copy(prop, NULL, NULL, obj);
}
static Box* staticmethodInit(Box* _self, Box* f) {
RELEASE_ASSERT(_self->cls == staticmethod_cls, "");
BoxedStaticmethod* self = static_cast<BoxedStaticmethod*>(_self);
......@@ -135,11 +175,13 @@ void setupDescr() {
property_cls->giveAttr("__name__", boxStrConstant("property"));
property_cls->giveAttr(
"__init__",
new BoxedFunction(boxRTFunction((void*)propertyInit, UNKNOWN, 5, 4, false, false), { None, None, None, None }));
property_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)propertyGet, UNKNOWN, 3, 0, false, false)));
property_cls->giveAttr("__set__",
new BoxedFunction(boxRTFunction((void*)propertySet, UNKNOWN, 3, 0, false, false)));
new BoxedFunction(boxRTFunction((void*)propertyInit, UNKNOWN, 5, 4, false, false), { NULL, NULL, NULL, NULL }));
property_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)propertyGet, UNKNOWN, 3)));
property_cls->giveAttr("__set__", new BoxedFunction(boxRTFunction((void*)propertySet, UNKNOWN, 3)));
property_cls->giveAttr("__delete__", new BoxedFunction(boxRTFunction((void*)propertyDel, UNKNOWN, 2)));
property_cls->giveAttr("getter", new BoxedFunction(boxRTFunction((void*)propertyGetter, UNKNOWN, 2)));
property_cls->giveAttr("setter", new BoxedFunction(boxRTFunction((void*)propertySetter, UNKNOWN, 2)));
property_cls->giveAttr("deleter", new BoxedFunction(boxRTFunction((void*)propertyDeleter, UNKNOWN, 2)));
property_cls->giveAttr("fget",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedProperty, prop_get)));
property_cls->giveAttr("fset",
......
......@@ -229,19 +229,27 @@ void raise0() {
raiseRaw(*exc_info);
}
#ifndef NDEBUG
ExcInfo::ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {
if (this->type && this->type != None)
RELEASE_ASSERT(isSubclass(this->type->cls, type_cls), "throwing old-style objects not supported yet (%s)",
getTypeName(this->type)->c_str());
}
#endif
bool ExcInfo::matches(BoxedClass* cls) const {
RELEASE_ASSERT(isSubclass(this->type->cls, type_cls), "throwing old-style objects not supported yet");
assert(this->type);
RELEASE_ASSERT(isSubclass(this->type->cls, type_cls), "throwing old-style objects not supported yet (%s)",
getTypeName(this->type)->c_str());
return isSubclass(static_cast<BoxedClass*>(this->type), cls);
}
void raise3(Box* arg0, Box* arg1, Box* arg2) {
RELEASE_ASSERT(arg2 == None, "unsupported");
// TODO switch this to PyErr_Normalize
if (isSubclass(arg0->cls, type_cls)) {
BoxedClass* c = static_cast<BoxedClass*>(arg0);
if (isSubclass(c, Exception)) {
if (isSubclass(c, BaseException)) {
Box* exc_obj;
if (arg1 != None)
exc_obj = exceptionNew2(c, arg1);
......@@ -249,16 +257,17 @@ void raise3(Box* arg0, Box* arg1, Box* arg2) {
exc_obj = exceptionNew1(c);
raiseRaw(ExcInfo(c, exc_obj, arg2));
} else {
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s",
getTypeName(arg0)->c_str());
}
}
if (arg1 != None)
raiseExcHelper(TypeError, "instance exception may not have a separate value");
if (isSubclass(arg0->cls, BaseException)) {
if (arg1 != None)
raiseExcHelper(TypeError, "instance exception may not have a separate value");
raiseRaw(ExcInfo(arg0->cls, arg0, arg2));
}
raiseRaw(ExcInfo(arg0, arg1, arg2));
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s",
getTypeName(arg0)->c_str());
}
void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
......
......@@ -899,6 +899,14 @@ public:
}
return rtn;
}
static Box* len(Box* _self) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
HCAttrs* attrs = self->b->getHCAttrsPtr();
return boxInt(attrs->hcls->attr_offsets.size());
}
};
Box* makeAttrWrapper(Box* b) {
......@@ -1141,6 +1149,7 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("keys", new BoxedFunction(boxRTFunction((void*)AttrWrapper::keys, LIST, 1)));
attrwrapper_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)AttrWrapper::values, LIST, 1)));
attrwrapper_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)AttrWrapper::items, LIST, 1)));
attrwrapper_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::len, BOXED_INT, 1)));
attrwrapper_cls->freeze();
// sys is the first module that needs to be set up, due to modules
......
# expected: fail
# - working on it
import sys
def compact(s):
......@@ -13,7 +10,7 @@ def compact(s):
return s
# TODO This should be a subclass of Exception not object:
class NotPossible(object):
class NotPossible(Exception):
pass
P = 1000000007
......
# fail-if: '-x' in EXTRA_JIT_ARGS
# I think pypa has an issue parsing decorator expressions if they aren't simple names
# https://github.com/vinzenz/libpypa/issues/15
class C(object):
def fget(self):
return 5
......@@ -13,3 +17,50 @@ print C.x.__get__(c, C)
print type(C.x.__get__(None, C))
c.x = 7
print c.x
class C2(object):
@property
def x(self):
print "x1"
return 2
x1 = x
@x.setter
def x(self, value):
print "x2"
return 3
x2 = x
@x.deleter
def x(self):
print "x3"
c = C2()
print "These should all succeed:"
print c.x1
print c.x2
print c.x
try:
# This will fail since x1 is a copy that didn't have the setter set:
c.x1 = 1
except AttributeError, e:
print e
c.x2 = 1
c.x = 1
try:
# This will fail since x1 is a copy that didn't have the deleter set:
del c.x1
except AttributeError, e:
print e
try:
# This will fail since x1 is a copy that didn't have the deleter set:
del c.x2
except AttributeError, e:
print e
c.x = 1
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