Commit b2f7eddc authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make int more subclass-friendly

parent fd8ea7ce
......@@ -323,7 +323,7 @@ public:
Box(const ObjectFlavor* flavor, BoxedClass* cls);
HCAttrs* getAttrs();
HCAttrs* getAttrsPtr();
void setattr(const std::string& attr, Box* val, SetattrRewriteArgs2* rewrite_args2);
void giveAttr(const std::string& attr, Box* val) {
......
......@@ -56,7 +56,7 @@ Box* boxInt(int64_t n) {
if (0 <= n && n < NUM_INTERNED_INTS) {
return interned_ints[n];
}
return new BoxedInt(n);
return new BoxedInt(int_cls, n);
}
// BoxedInt::BoxedInt(int64_t n) : Box(int_cls), n(n) {}
......
......@@ -120,8 +120,10 @@ extern "C" Box* intAddFloat(BoxedInt* lhs, BoxedFloat* rhs) {
}
extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__add__' requires a 'int' object but received a '%s'", getTypeName(rhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n + rhs_int->n);
} else if (rhs->cls == float_cls) {
......@@ -410,8 +412,12 @@ extern "C" Box* intInvert(BoxedInt* v) {
}
extern "C" Box* intPos(BoxedInt* v) {
assert(v->cls == int_cls);
return v;
if (!isSubclass(v->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__pos__' requires a 'int' object but received a '%s'", getTypeName(rhs)->c_str());
if (v->cls == int_cls)
return v;
return boxInt(v->n);
}
extern "C" Box* intNeg(BoxedInt* v) {
......@@ -425,7 +431,9 @@ extern "C" Box* intNonzero(BoxedInt* v) {
}
extern "C" BoxedString* intRepr(BoxedInt* v) {
assert(v->cls == int_cls);
if (!isSubclass(v->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'int' object but received a '%s'", getTypeName(rhs)->c_str());
char buf[80];
int len = snprintf(buf, 80, "%ld", v->n);
return new BoxedString(std::string(buf, len));
......@@ -437,42 +445,53 @@ extern "C" Box* intHash(BoxedInt* self) {
}
extern "C" Box* intNew1(Box* cls) {
assert(cls == int_cls);
return new BoxedInt(0);
if (!is_subclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
return boxInt(0);
}
extern "C" Box* intNew2(Box* cls, Box* val) {
assert(cls == int_cls);
extern "C" Box* intNew2(Box* _cls, Box* val) {
if (!is_subclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, int_cls))
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls)->c_str(), getNameOfClass(cls)->c_str());
assert(cls->instance_size >= sizeof(BoxedInt));
void* mem = rt_alloc(cls->instance_size);
BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0);
initUserAttrs(rtn, cls);
if (val->cls == int_cls) {
return val;
rtn->n = static_cast<BoxedInt*>(val)->n;
} else if (val->cls == str_cls) {
BoxedString* s = static_cast<BoxedString*>(val);
std::istringstream ss(s->s);
int64_t n;
ss >> n;
return boxInt(n);
rtn->n = n;
} else if (val->cls == float_cls) {
double d = static_cast<BoxedFloat*>(val)->d;
return boxInt(d);
rtn->n = d;
} else {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n",
getTypeName(val)->c_str());
raiseExcHelper(TypeError, "");
}
return rtn;
}
extern "C" Box* intInit1(BoxedInt* self) {
assert(self->cls == int_cls);
extern "C" Box* intInit1(Box* self) {
// int.__init__ will actually let you call it with anything
return None;
}
extern "C" Box* intInit2(BoxedInt* self, Box* val) {
assert(self->cls == int_cls);
// int.__init__ will actually let you call it with anything
return None;
}
......@@ -483,8 +502,9 @@ static void _addFuncIntFloatUnknown(const char* name, void* int_func, void* floa
v_ii.push_back(BOXED_INT);
v_if.push_back(BOXED_INT);
v_if.push_back(BOXED_FLOAT);
v_iu.push_back(BOXED_INT);
v_iu.push_back(NULL);
// Only the unknown version can accept non-ints (ex if you access the function directly ex via int.__add__)
v_iu.push_back(UNKNOWN);
v_iu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction();
addRTFunction(cl, int_func, BOXED_INT, v_ii, false);
......@@ -548,7 +568,7 @@ void setupInt() {
int_cls->freeze();
for (int i = 0; i < NUM_INTERNED_INTS; i++) {
interned_ints[i] = new BoxedInt(i);
interned_ints[i] = new BoxedInt(int_cls, i);
gc::registerStaticRootObj(interned_ints[i]);
}
}
......
......@@ -85,7 +85,7 @@ extern "C" Box* listPop2(BoxedList* self, Box* idx) {
}
extern "C" Box* listLen(BoxedList* self) {
return new BoxedInt(self->size);
return boxInt(self->size);
}
Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step) {
......@@ -361,7 +361,7 @@ Box* listCount(BoxedList* self, Box* elt) {
if (b)
count++;
}
return new BoxedInt(count);
return boxInt(count);
}
Box* listIndex(BoxedList* self, Box* elt) {
......@@ -372,7 +372,7 @@ Box* listIndex(BoxedList* self, Box* elt) {
Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL);
bool b = nonzero(cmp);
if (b)
return new BoxedInt(i);
return boxInt(i);
}
BoxedString* tostr = static_cast<BoxedString*>(repr(elt));
......
......@@ -346,7 +346,7 @@ Box::Box(const ObjectFlavor* flavor, BoxedClass* cls) : GCObject(flavor), cls(cl
}
HCAttrs* Box::getAttrs() {
HCAttrs* Box::getAttrsPtr() {
assert(cls->instancesHaveAttrs());
char* p = reinterpret_cast<char*>(this);
......@@ -376,7 +376,7 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, Get
if (!cls->instancesHaveAttrs())
return NULL;
HCAttrs* attrs = getAttrs();
HCAttrs* attrs = getAttrsPtr();
HiddenClass* hcls = attrs->hcls;
if (rewrite_args) {
......@@ -464,7 +464,7 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs2* rewrit
}
}
HCAttrs* attrs = getAttrs();
HCAttrs* attrs = getAttrsPtr();
HiddenClass* hcls = attrs->hcls;
int numattrs = hcls->attr_offsets.size();
......
......@@ -105,7 +105,7 @@ extern "C" void boxGCHandler(GCVisitor* v, void* p) {
v->visit(b->cls);
if (b->cls->instancesHaveAttrs()) {
HCAttrs* attrs = b->getAttrs();
HCAttrs* attrs = b->getAttrsPtr();
v->visit(attrs->hcls);
int nattrs = attrs->hcls->attr_offsets.size();
......@@ -388,10 +388,7 @@ Box* objectNew1(BoxedClass* cls) {
void* mem = rt_alloc(cls->instance_size);
Box* rtn = ::new (mem) Box(&object_flavor, cls);
if (cls->attrs_offset) {
HCAttrs* attrs = rtn->getAttrs();
attrs = new ((void*)attrs) HCAttrs();
}
initUserAttrs(rtn, cls);
return rtn;
}
......
......@@ -163,7 +163,7 @@ class BoxedInt : public Box {
public:
int64_t n;
BoxedInt(int64_t n) __attribute__((visibility("default"))) : Box(&int_flavor, int_cls), n(n) {}
BoxedInt(BoxedClass* cls, int64_t n) __attribute__((visibility("default"))) : Box(&int_flavor, cls), n(n) {}
};
class BoxedFloat : public Box {
......@@ -300,5 +300,16 @@ Box* exceptionNew2(BoxedClass* cls, Box* message);
extern BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError,
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError;
// cls should be obj->cls.
// Added as parameter because it should typically be available
inline void initUserAttrs(Box* obj, BoxedClass* cls) {
assert(obj->cls == cls);
if (cls->attrs_offset) {
HCAttrs* attrs = obj->getAttrsPtr();
attrs = new ((void*)attrs) HCAttrs();
}
}
}
#endif
......@@ -42,7 +42,7 @@ def f2():
f2()
def f3():
class I(object):
class I(int):
def foo(self):
print self + 1
......@@ -56,6 +56,8 @@ def f3():
e = a + c
print d, type(d)
print e, type(e)
f = +a
print f, type(f)
print a.foo()
f3()
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