Commit da9f8db9 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make bool a proper subclass of int

Required a small amount of object changes, and then a large
number of replacements where we directly compared the class
to int_cls.  We now check that it's a subclass, since you
are allowed to use True/False anywhere that you could use
an int.  ex "xrange(0, n, step=True)"
parent 68af64c1
......@@ -1269,7 +1269,10 @@ public:
void drop(IREmitter& emitter, VAR* var) override { emitter.getGC()->dropPointer(emitter, var->getValue()); }
void grab(IREmitter& emitter, VAR* var) override { emitter.getGC()->grabPointer(emitter, var->getValue()); }
bool isFitBy(BoxedClass* c) override { return c == cls; }
bool isFitBy(BoxedClass* c) override {
// I don't think it's ok to accept subclasses
return c == cls;
}
CompilerType* getattrType(const std::string* attr, bool cls_only) override {
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) {
......
......@@ -26,24 +26,12 @@ extern "C" PyObject* PyBool_FromLong(long n) {
return boxBool(n != 0);
}
extern "C" Box* boolInvert(BoxedBool* v) {
return boxInt(~v->b);
}
extern "C" Box* boolPos(BoxedBool* v) {
return boxInt(v->b ? 1 : 0);
}
extern "C" Box* boolNeg(BoxedBool* v) {
return boxInt(v->b ? -1 : 0);
}
extern "C" Box* boolNonzero(BoxedBool* v) {
return v;
}
extern "C" Box* boolRepr(BoxedBool* v) {
if (v->b)
if (v == True)
return boxStrConstant("True");
return boxStrConstant("False");
}
......@@ -62,9 +50,6 @@ extern "C" Box* boolNew(Box* cls, Box* val) {
void setupBool() {
bool_cls->giveAttr("__name__", boxStrConstant("bool"));
bool_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)boolInvert, BOXED_INT, 1)));
bool_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)boolPos, BOXED_INT, 1)));
bool_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)boolNeg, BOXED_INT, 1)));
bool_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)boolNonzero, BOXED_BOOL, 1)));
bool_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)boolRepr, STR, 1)));
bool_cls->giveAttr("__str__", bool_cls->getattr("__repr__"));
......
......@@ -106,7 +106,7 @@ extern "C" Box* vars(Box* obj) {
}
extern "C" Box* abs_(Box* x) {
if (x->cls == int_cls) {
if (isSubclass(x->cls, int_cls)) {
i64 n = static_cast<BoxedInt*>(x)->n;
return boxInt(n >= 0 ? n : -n);
} else if (x->cls == float_cls) {
......@@ -267,22 +267,22 @@ extern "C" Box* ord(Box* arg) {
Box* range(Box* start, Box* stop, Box* step) {
i64 istart, istop, istep;
if (stop == NULL) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start)->c_str());
istart = 0;
istop = static_cast<BoxedInt*>(start)->n;
istep = 1;
} else if (step == NULL) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(isSubclass(stop->cls, int_cls), "%s", getTypeName(stop)->c_str());
istart = static_cast<BoxedInt*>(start)->n;
istop = static_cast<BoxedInt*>(stop)->n;
istep = 1;
} else {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(step->cls == int_cls, "%s", getTypeName(step)->c_str());
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(isSubclass(stop->cls, int_cls), "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(isSubclass(step->cls, int_cls), "%s", getTypeName(step)->c_str());
istart = static_cast<BoxedInt*>(start)->n;
istop = static_cast<BoxedInt*>(stop)->n;
......@@ -607,7 +607,7 @@ public:
static Box* new_(Box* cls, Box* obj, Box* start) {
RELEASE_ASSERT(cls == enumerate_cls, "");
RELEASE_ASSERT(start->cls == int_cls, "");
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "");
int64_t idx = static_cast<BoxedInt*>(start)->n;
llvm::iterator_range<BoxIterator> range = obj->pyElements();
......
......@@ -35,7 +35,7 @@ Box* timeTime() {
Box* timeSleep(Box* arg) {
double secs;
if (arg->cls == int_cls)
if (isSubclass(arg->cls, int_cls))
secs = static_cast<BoxedInt*>(arg)->n;
else if (arg->cls == float_cls)
secs = static_cast<BoxedFloat*>(arg)->d;
......
......@@ -283,7 +283,8 @@ extern "C" PyObject* PyObject_GetItem(PyObject* o, PyObject* key) {
try {
return getitem(o, key);
} catch (Box* b) {
Py_FatalError("unimplemented");
PyErr_SetObject(b->cls, b);
return NULL;
}
}
......@@ -488,13 +489,16 @@ void checkAndThrowCAPIException() {
RELEASE_ASSERT(threading::cur_thread_state.curexc_traceback == NULL, "unsupported");
// This doesn't seem like the right behavior...
if (value->cls == tuple_cls) {
BoxedTuple* args = static_cast<BoxedTuple*>(value);
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(0, 0, true, false), args, NULL,
NULL, NULL, NULL);
if (value->cls != threading::cur_thread_state.curexc_type) {
if (value->cls == tuple_cls)
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(0, 0, true, false), value,
NULL, NULL, NULL, NULL);
else
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(1), value, NULL, NULL, NULL,
NULL);
}
RELEASE_ASSERT(value->cls == threading::cur_thread_state.curexc_type, "unsupported");
RELEASE_ASSERT(value->cls == threading::cur_thread_state.curexc_type, "unsupported");
PyErr_Clear();
throw value;
}
......@@ -766,7 +770,7 @@ extern "C" PyObject* PyNumber_ToBase(PyObject* n, int base) {
extern "C" Py_ssize_t PyNumber_AsSsize_t(PyObject* o, PyObject* exc) {
RELEASE_ASSERT(o->cls != long_cls, "unhandled");
RELEASE_ASSERT(o->cls == int_cls, "??");
RELEASE_ASSERT(isSubclass(o->cls, int_cls), "??");
int64_t n = static_cast<BoxedInt*>(o)->n;
static_assert(sizeof(n) == sizeof(Py_ssize_t), "");
return n;
......
......@@ -50,13 +50,13 @@ extern "C" Box* complexAddFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
extern "C" Box* complexAddInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxComplex(lhs->real + (double)rhs->n, lhs->imag);
}
extern "C" Box* complexAdd(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return complexAddInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexAddFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -83,13 +83,13 @@ extern "C" Box* complexSubFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
extern "C" Box* complexSubInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxComplex(lhs->real - (double)rhs->n, lhs->imag);
}
extern "C" Box* complexSub(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return complexSubInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -116,13 +116,13 @@ extern "C" Box* complexMulFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
extern "C" Box* complexMulInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxComplex(lhs->real * (double)rhs->n, lhs->imag * (double)rhs->n);
}
extern "C" Box* complexMul(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return complexMulInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexMulFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -153,7 +153,7 @@ extern "C" Box* complexDivFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
if (rhs->n == 0) {
raiseDivZeroExc();
}
......@@ -162,7 +162,7 @@ extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) {
extern "C" Box* complexDiv(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return complexDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -212,7 +212,7 @@ Box* complexNew(Box* _cls, Box* real, Box* imag) {
RELEASE_ASSERT(_cls == complex_cls, "");
double real_f;
if (real->cls == int_cls) {
if (isSubclass(real->cls, int_cls)) {
real_f = static_cast<BoxedInt*>(real)->n;
} else if (real->cls == float_cls) {
real_f = static_cast<BoxedFloat*>(real)->d;
......@@ -222,7 +222,7 @@ Box* complexNew(Box* _cls, Box* real, Box* imag) {
}
double imag_f;
if (imag->cls == int_cls) {
if (isSubclass(imag->cls, int_cls)) {
imag_f = static_cast<BoxedInt*>(imag)->n;
} else if (imag->cls == float_cls) {
imag_f = static_cast<BoxedFloat*>(imag)->d;
......
......@@ -30,7 +30,7 @@ extern "C" PyObject* PyFloat_FromDouble(double d) {
extern "C" double PyFloat_AsDouble(PyObject* o) {
if (o->cls == float_cls)
return static_cast<BoxedFloat*>(o)->d;
else if (o->cls == int_cls)
else if (isSubclass(o->cls, int_cls))
return static_cast<BoxedInt*>(o)->n;
Py_FatalError("unimplemented");
return 0.0;
......@@ -77,13 +77,13 @@ extern "C" Box* floatAddFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatAddInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(lhs->d + rhs->n);
}
extern "C" Box* floatAdd(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatAddInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatAddFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -101,14 +101,14 @@ extern "C" Box* floatDivFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatDivInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
raiseDivZeroExcIfZero(rhs->n);
return boxFloat(lhs->d / rhs->n);
}
extern "C" Box* floatDiv(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -119,7 +119,7 @@ extern "C" Box* floatDiv(BoxedFloat* lhs, Box* rhs) {
extern "C" Box* floatTruediv(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -137,14 +137,14 @@ extern "C" Box* floatRDivFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatRDivInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
raiseDivZeroExcIfZero(lhs->d);
return boxFloat(rhs->n / lhs->d);
}
extern "C" Box* floatRDiv(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatRDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatRDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -162,14 +162,14 @@ extern "C" Box* floatFloorDivFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatFloorDivInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
raiseDivZeroExcIfZero(rhs->n);
return boxFloat(floor(lhs->d / rhs->n));
}
extern "C" Box* floatFloorDiv(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatFloorDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatFloorDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -186,13 +186,13 @@ extern "C" Box* floatEqFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatEqInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->d == rhs->n);
}
extern "C" Box* floatEq(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatEqInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatEqFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -209,13 +209,13 @@ extern "C" Box* floatNeFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatNeInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->d != rhs->n);
}
extern "C" Box* floatNe(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatNeInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatNeFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -232,13 +232,13 @@ extern "C" Box* floatLtFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatLtInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->d < rhs->n);
}
extern "C" Box* floatLt(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatLtInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatLtFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -255,13 +255,13 @@ extern "C" Box* floatLeFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatLeInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->d <= rhs->n);
}
extern "C" Box* floatLe(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatLeInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatLeFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -278,13 +278,13 @@ extern "C" Box* floatGtFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatGtInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->d > rhs->n);
}
extern "C" Box* floatGt(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatGtInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatGtFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -301,13 +301,13 @@ extern "C" Box* floatGeFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatGeInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->d >= rhs->n);
}
extern "C" Box* floatGe(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatGeInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatGeFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -324,13 +324,13 @@ extern "C" Box* floatModFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatModInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(mod_float_float(lhs->d, rhs->n));
}
extern "C" Box* floatMod(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatModInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatModFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -347,13 +347,13 @@ extern "C" Box* floatRModFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatRModInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(mod_float_float(rhs->n, lhs->d));
}
extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatRModInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatRModFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -370,13 +370,13 @@ extern "C" Box* floatPowFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(pow(lhs->d, rhs->n));
}
extern "C" Box* floatPow(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatPowInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatPowFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -393,13 +393,13 @@ extern "C" Box* floatMulFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatMulInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(lhs->d * rhs->n);
}
extern "C" Box* floatMul(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatMulInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatMulFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -416,13 +416,13 @@ extern "C" Box* floatSubFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatSubInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(lhs->d - rhs->n);
}
extern "C" Box* floatSub(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatSubInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -439,13 +439,13 @@ extern "C" Box* floatRSubFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatRSubInt(BoxedFloat* lhs, BoxedInt* rhs) {
assert(lhs->cls == float_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(rhs->cls, int_cls));
return boxFloat(rhs->n - lhs->d);
}
extern "C" Box* floatRSub(BoxedFloat* lhs, Box* rhs) {
assert(lhs->cls == float_cls);
if (rhs->cls == int_cls) {
if (isSubclass(rhs->cls, int_cls)) {
return floatRSubInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return floatRSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -549,7 +549,7 @@ Box* floatNew(BoxedClass* cls, Box* a) {
if (a->cls == float_cls) {
return a;
} else if (a->cls == int_cls) {
} else if (isSubclass(a->cls, int_cls)) {
return boxFloat(static_cast<BoxedInt*>(a)->n);
} else if (a->cls == str_cls) {
const std::string& s = static_cast<BoxedString*>(a)->s;
......
......@@ -81,21 +81,21 @@ Box* xrange(Box* cls, Box* start, Box* stop, Box** args) {
Box* step = args[0];
if (stop == NULL) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start)->c_str());
i64 istop = static_cast<BoxedInt*>(start)->n;
return new BoxedXrange(0, istop, 1);
} else if (step == NULL) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(isSubclass(stop->cls, int_cls), "%s", getTypeName(stop)->c_str());
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 istop = static_cast<BoxedInt*>(stop)->n;
return new BoxedXrange(istart, istop, 1);
} else {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(step->cls == int_cls, "%s", getTypeName(step)->c_str());
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(isSubclass(stop->cls, int_cls), "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(isSubclass(step->cls, int_cls), "%s", getTypeName(step)->c_str());
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 istop = static_cast<BoxedInt*>(stop)->n;
......
......@@ -36,12 +36,12 @@ extern "C" unsigned long PyInt_AsUnsignedLongMask(PyObject* op) {
}
extern "C" long PyInt_AsLong(PyObject* op) {
RELEASE_ASSERT(op->cls == int_cls, "");
RELEASE_ASSERT(isSubclass(op->cls, int_cls), "");
return static_cast<BoxedInt*>(op)->n;
}
extern "C" Py_ssize_t PyInt_AsSsize_t(PyObject* op) {
RELEASE_ASSERT(op->cls == int_cls, "");
RELEASE_ASSERT(isSubclass(op->cls, int_cls), "");
return static_cast<BoxedInt*>(op)->n;
}
......@@ -207,13 +207,13 @@ extern "C" i1 ge_i64_i64(i64 lhs, i64 rhs) {
extern "C" Box* intAddInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return add_i64_i64(lhs->n, rhs->n);
}
extern "C" Box* intAddFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
return boxFloat(lhs->n + rhs->d);
}
......@@ -221,7 +221,7 @@ extern "C" Box* intAddFloat(BoxedInt* lhs, BoxedFloat* rhs) {
extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__add__' requires a 'int' object but received a '%s'",
getTypeName(rhs)->c_str());
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
......@@ -235,13 +235,16 @@ extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intAndInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxInt(lhs->n & rhs->n);
}
extern "C" Box* intAnd(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__and__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -250,13 +253,16 @@ extern "C" Box* intAnd(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intOrInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxInt(lhs->n | rhs->n);
}
extern "C" Box* intOr(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__or__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -265,13 +271,16 @@ extern "C" Box* intOr(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intXorInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxInt(lhs->n ^ rhs->n);
}
extern "C" Box* intXor(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__xor__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -280,13 +289,13 @@ extern "C" Box* intXor(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intDivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return div_i64_i64(lhs->n, rhs->n);
}
extern "C" Box* intDivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
if (rhs->d == 0) {
......@@ -296,8 +305,11 @@ extern "C" Box* intDivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
}
extern "C" Box* intDiv(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
return intDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return intDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -307,13 +319,13 @@ extern "C" Box* intDiv(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intFloordivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return div_i64_i64(lhs->n, rhs->n);
}
extern "C" Box* intFloordivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
if (rhs->d == 0) {
......@@ -323,8 +335,11 @@ extern "C" Box* intFloordivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
}
extern "C" Box* intFloordiv(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__floordiv__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
return intFloordivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return intFloordivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -334,8 +349,8 @@ extern "C" Box* intFloordiv(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
if (rhs->n == 0) {
raiseExcHelper(ZeroDivisionError, "division by zero");
......@@ -344,7 +359,7 @@ extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) {
}
extern "C" Box* intTruedivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
if (rhs->d == 0) {
......@@ -354,8 +369,11 @@ extern "C" Box* intTruedivFloat(BoxedInt* lhs, BoxedFloat* rhs) {
}
extern "C" Box* intTruediv(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__truediv__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
return intTruedivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return intTruedivFloat(lhs, static_cast<BoxedFloat*>(rhs));
......@@ -365,28 +383,35 @@ extern "C" Box* intTruediv(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intEqInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->n == rhs->n);
}
extern "C" Box* intEq(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls != int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__eq__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxBool(lhs->n == rhs_int->n);
} else {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxBool(lhs->n == rhs_int->n);
}
extern "C" Box* intNeInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->n != rhs->n);
}
extern "C" Box* intNe(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__ne__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -395,13 +420,16 @@ extern "C" Box* intNe(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intLtInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->n < rhs->n);
}
extern "C" Box* intLt(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__lt__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -410,13 +438,16 @@ extern "C" Box* intLt(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intLeInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->n <= rhs->n);
}
extern "C" Box* intLe(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__le__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -425,13 +456,16 @@ extern "C" Box* intLe(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intGtInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->n > rhs->n);
}
extern "C" Box* intGt(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__gt__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -440,13 +474,16 @@ extern "C" Box* intGt(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intGeInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxBool(lhs->n >= rhs->n);
}
extern "C" Box* intGe(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__ge__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -455,8 +492,8 @@ extern "C" Box* intGe(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
if (rhs->n < 0)
raiseExcHelper(ValueError, "negative shift count");
......@@ -466,7 +503,10 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
}
extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__lshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -475,13 +515,16 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intModInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return boxInt(mod_i64_i64(lhs->n, rhs->n));
}
extern "C" Box* intMod(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__mod__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -490,7 +533,10 @@ extern "C" Box* intMod(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
Box* divResult = intDiv(lhs, rhs);
if (divResult == NotImplemented) {
......@@ -509,20 +555,23 @@ extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
extern "C" Box* intMulInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return mul_i64_i64(lhs->n, rhs->n);
}
extern "C" Box* intMulFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
return boxFloat(lhs->n * rhs->d);
}
extern "C" Box* intMul(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__mul__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intMulInt(lhs, rhs_int);
} else if (rhs->cls == float_cls) {
......@@ -534,21 +583,24 @@ extern "C" Box* intMul(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intPowInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return pow_i64_i64(lhs->n, rhs_int->n);
}
extern "C" Box* intPowFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
return boxFloat(pow(lhs->n, rhs->d));
}
extern "C" Box* intPow(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__pow__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intPowInt(lhs, rhs_int);
} else if (rhs->cls == float_cls) {
......@@ -560,8 +612,8 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
if (rhs->n < 0)
raiseExcHelper(ValueError, "negative shift count");
......@@ -570,7 +622,10 @@ extern "C" Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
}
extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__rshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (rhs->cls != int_cls) {
return NotImplemented;
}
......@@ -579,20 +634,23 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intSubInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(lhs->cls == int_cls);
assert(rhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(isSubclass(rhs->cls, int_cls));
return sub_i64_i64(lhs->n, rhs->n);
}
extern "C" Box* intSubFloat(BoxedInt* lhs, BoxedFloat* rhs) {
assert(lhs->cls == int_cls);
assert(isSubclass(lhs->cls, int_cls));
assert(rhs->cls == float_cls);
return boxFloat(lhs->n - rhs->d);
}
extern "C" Box* intSub(BoxedInt* lhs, Box* rhs) {
assert(lhs->cls == int_cls);
if (rhs->cls == int_cls) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__sub__' requires a 'int' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intSubInt(lhs, rhs_int);
} else if (rhs->cls == float_cls) {
......@@ -604,7 +662,10 @@ extern "C" Box* intSub(BoxedInt* lhs, Box* rhs) {
}
extern "C" Box* intInvert(BoxedInt* v) {
assert(v->cls == int_cls);
if (!isSubclass(v->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__invert__' requires a 'int' object but received a '%s'",
getTypeName(v)->c_str());
return boxInt(~v->n);
}
......@@ -619,7 +680,10 @@ extern "C" Box* intPos(BoxedInt* v) {
}
extern "C" Box* intNeg(BoxedInt* v) {
assert(v->cls == int_cls);
if (!isSubclass(v->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__neg__' requires a 'int' object but received a '%s'",
getTypeName(v)->c_str());
// It's possible for this to overflow:
#if PYSTON_INT_MIN < -PYSTON_INT_MAX
......@@ -634,7 +698,10 @@ extern "C" Box* intNeg(BoxedInt* v) {
}
extern "C" Box* intNonzero(BoxedInt* v) {
assert(v->cls == int_cls);
if (!isSubclass(v->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__nonzer__' requires a 'int' object but received a '%s'",
getTypeName(v)->c_str());
return boxBool(v->n != 0);
}
......@@ -649,8 +716,13 @@ extern "C" BoxedString* intRepr(BoxedInt* v) {
}
extern "C" Box* intHash(BoxedInt* self) {
assert(self->cls == int_cls);
return self;
if (!isSubclass(self->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'int' object but received a '%s'",
getTypeName(self)->c_str());
if (self->cls == int_cls)
return self;
return boxInt(self->n);
}
extern "C" Box* intNew(Box* _cls, Box* val) {
......@@ -667,7 +739,7 @@ extern "C" Box* intNew(Box* _cls, Box* val) {
BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0);
initUserAttrs(rtn, cls);
if (val->cls == int_cls) {
if (isSubclass(val->cls, int_cls)) {
rtn->n = static_cast<BoxedInt*>(val)->n;
} else if (val->cls == str_cls) {
BoxedString* s = static_cast<BoxedString*>(val);
......@@ -680,8 +752,6 @@ extern "C" Box* intNew(Box* _cls, Box* val) {
double d = static_cast<BoxedFloat*>(val)->d;
rtn->n = d;
} else if (val->cls == bool_cls) {
rtn->n = (val == True);
} else {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n",
getTypeName(val)->c_str());
......@@ -698,9 +768,9 @@ extern "C" Box* intInit(BoxedInt* self, Box* val, Box* args) {
static void _addFuncIntFloatUnknown(const char* name, void* int_func, void* float_func, void* boxed_func) {
std::vector<ConcreteCompilerType*> v_ii, v_if, v_iu;
assert(BOXED_INT);
v_ii.push_back(UNKNOWN);
v_ii.push_back(BOXED_INT);
v_ii.push_back(BOXED_INT);
v_if.push_back(BOXED_INT);
v_if.push_back(UNKNOWN);
v_if.push_back(BOXED_FLOAT);
// Only the unknown version can accept non-ints (ex if you access the function directly ex via int.__add__)
v_iu.push_back(UNKNOWN);
......@@ -716,9 +786,9 @@ static void _addFuncIntFloatUnknown(const char* name, void* int_func, void* floa
static void _addFuncIntUnknown(const char* name, ConcreteCompilerType* rtn_type, void* int_func, void* boxed_func) {
std::vector<ConcreteCompilerType*> v_ii, v_iu;
assert(BOXED_INT);
v_ii.push_back(UNKNOWN);
v_ii.push_back(BOXED_INT);
v_ii.push_back(BOXED_INT);
v_iu.push_back(BOXED_INT);
v_iu.push_back(UNKNOWN);
v_iu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction(2, 0, false, false);
......
......@@ -140,7 +140,7 @@ extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) {
}
extern "C" Box* listGetitemInt(BoxedList* self, BoxedInt* slice) {
assert(slice->cls == int_cls);
assert(isSubclass(slice->cls, int_cls));
return listGetitemUnboxed(self, slice->n);
}
......@@ -166,7 +166,7 @@ extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) {
extern "C" Box* listGetitem(BoxedList* self, Box* slice) {
assert(self->cls == list_cls);
if (slice->cls == int_cls) {
if (isSubclass(slice->cls, int_cls)) {
return listGetitemInt(self, static_cast<BoxedInt*>(slice));
} else if (slice->cls == slice_cls) {
return listGetitemSlice(self, static_cast<BoxedSlice*>(slice));
......@@ -181,7 +181,7 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) {
LOCK_REGION(self->lock.asRead());
assert(self->cls == list_cls);
assert(slice->cls == int_cls);
assert(isSubclass(slice->cls, int_cls));
int64_t n = slice->n;
if (n < 0)
n = self->size + n;
......@@ -229,7 +229,7 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
extern "C" Box* listSetitem(BoxedList* self, Box* slice, Box* v) {
assert(self->cls == list_cls);
if (slice->cls == int_cls) {
if (isSubclass(slice->cls, int_cls)) {
return listSetitemInt(self, static_cast<BoxedInt*>(slice), v);
} else if (slice->cls == slice_cls) {
return listSetitemSlice(self, static_cast<BoxedSlice*>(slice), v);
......@@ -276,7 +276,7 @@ extern "C" Box* listDelitem(BoxedList* self, Box* slice) {
Box* rtn;
if (slice->cls == int_cls) {
if (isSubclass(slice->cls, int_cls)) {
rtn = listDelitemInt(self, static_cast<BoxedInt*>(slice));
} else if (slice->cls == slice_cls) {
rtn = listDelitemSlice(self, static_cast<BoxedSlice*>(slice));
......
......@@ -215,7 +215,7 @@ extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) {
int r = mpz_init_set_str(rtn->n, s->s.c_str(), base);
RELEASE_ASSERT(r == 0, "");
} else {
if (val->cls == int_cls) {
if (isSubclass(val->cls, int_cls)) {
mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(val)->n);
} else if (val->cls == str_cls) {
const std::string& s = static_cast<BoxedString*>(val)->s;
......
......@@ -54,7 +54,7 @@
#define ATTRLIST_KIND_OFFSET ((char*)&(((HCAttrs::AttrList*)0x01)->gc_header.kind_id) - (char*)0x1)
#define INSTANCEMETHOD_FUNC_OFFSET ((char*)&(((BoxedInstanceMethod*)0x01)->func) - (char*)0x1)
#define INSTANCEMETHOD_OBJ_OFFSET ((char*)&(((BoxedInstanceMethod*)0x01)->obj) - (char*)0x1)
#define BOOL_B_OFFSET ((char*)&(((BoxedBool*)0x01)->b) - (char*)0x1)
#define BOOL_B_OFFSET ((char*)&(((BoxedBool*)0x01)->n) - (char*)0x1)
#define INT_N_OFFSET ((char*)&(((BoxedInt*)0x01)->n) - (char*)0x1)
namespace pyston {
......@@ -209,18 +209,14 @@ bool PyEq::operator()(Box* lhs, Box* rhs) const {
// TODO fix this
Box* cmp = compareInternal(lhs, rhs, AST_TYPE::Eq, NULL);
assert(cmp->cls == bool_cls);
BoxedBool* b = static_cast<BoxedBool*>(cmp);
bool rtn = b->b;
return rtn;
return cmp == True;
}
bool PyLt::operator()(Box* lhs, Box* rhs) const {
// TODO fix this
Box* cmp = compareInternal(lhs, rhs, AST_TYPE::Lt, NULL);
assert(cmp->cls == bool_cls);
BoxedBool* b = static_cast<BoxedBool*>(cmp);
bool rtn = b->b;
return rtn;
return cmp == True;
}
extern "C" bool softspace(Box* b, bool newval) {
......@@ -1568,13 +1564,14 @@ extern "C" bool nonzero(Box* obj) {
}
if (obj->cls == bool_cls) {
// TODO: is it faster to compare to True? (especially since it will be a constant we can embed in the rewrite)
if (rewriter.get()) {
RewriterVar* b = r_obj->getAttr(BOOL_B_OFFSET, rewriter->getReturnDestination());
rewriter->commitReturning(b);
}
BoxedBool* bool_obj = static_cast<BoxedBool*>(obj);
return bool_obj->b;
return bool_obj->n;
} else if (obj->cls == int_cls) {
if (rewriter.get()) {
// TODO should do:
......@@ -1623,7 +1620,7 @@ extern "C" bool nonzero(Box* obj) {
Box* r = runtimeCall0(func, ArgPassSpec(0));
if (r->cls == bool_cls) {
BoxedBool* b = static_cast<BoxedBool*>(r);
bool rtn = b->b;
bool rtn = b->n;
return rtn;
} else if (r->cls == int_cls) {
BoxedInt* b = static_cast<BoxedInt*>(r);
......
......@@ -163,7 +163,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
elt_num++;
}
RELEASE_ASSERT(val_to_use->cls == int_cls, "unsupported");
RELEASE_ASSERT(isSubclass(val_to_use->cls, int_cls), "unsupported");
RELEASE_ASSERT(nspace == 0, "unsupported");
RELEASE_ASSERT(ndot == 0, "unsupported");
RELEASE_ASSERT(nzero == 0, "unsupported");
......@@ -183,7 +183,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
elt_num++;
}
RELEASE_ASSERT(val_to_use->cls == int_cls, "unsupported");
RELEASE_ASSERT(isSubclass(val_to_use->cls, int_cls), "unsupported");
std::ostringstream fmt("");
fmt << '%';
......@@ -210,7 +210,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
double d;
if (val_to_use->cls == float_cls) {
d = static_cast<BoxedFloat*>(val_to_use)->d;
} else if (val_to_use->cls == int_cls) {
} else if (isSubclass(val_to_use->cls, int_cls)) {
d = static_cast<BoxedInt*>(val_to_use)->n;
} else {
RELEASE_ASSERT(0, "unsupported");
......@@ -251,8 +251,6 @@ extern "C" Box* strMul(BoxedString* lhs, Box* rhs) {
int n;
if (isSubclass(rhs->cls, int_cls))
n = static_cast<BoxedInt*>(rhs)->n;
else if (isSubclass(rhs->cls, bool_cls))
n = static_cast<BoxedBool*>(rhs)->b;
else
return NotImplemented;
......@@ -622,7 +620,7 @@ Box* strReplace(Box* _self, Box* _old, Box* _new, Box** _args) {
Box* _count = _args[0];
RELEASE_ASSERT(_count->cls == int_cls, "an integer is required");
RELEASE_ASSERT(isSubclass(_count->cls, int_cls), "an integer is required");
BoxedInt* count = static_cast<BoxedInt*>(_count);
RELEASE_ASSERT(count->n < 0, "'count' argument unsupported");
......@@ -696,7 +694,7 @@ Box* strSplit(BoxedString* self, BoxedString* sep, BoxedInt* _max_split) {
Box* strRsplit(BoxedString* self, BoxedString* sep, BoxedInt* _max_split) {
// TODO: implement this for real
// for now, just forward rsplit() to split() in the cases they have to return the same value
assert(_max_split->cls == int_cls);
assert(isSubclass(_max_split->cls, int_cls));
RELEASE_ASSERT(_max_split->n <= 0, "");
return strSplit(self, sep, _max_split);
}
......@@ -834,7 +832,7 @@ Box* strContains(BoxedString* self, Box* elt) {
Box* strStartswith(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'startswith' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
getTypeName(self)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
......@@ -847,7 +845,7 @@ Box* strStartswith(BoxedString* self, Box* elt) {
Box* strEndswith(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'endswith' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
getTypeName(self)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
......@@ -860,7 +858,7 @@ Box* strEndswith(BoxedString* self, Box* elt) {
Box* strFind(BoxedString* self, Box* elt, Box* _start) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'find' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
getTypeName(self)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
......@@ -888,7 +886,7 @@ Box* strFind(BoxedString* self, Box* elt, Box* _start) {
Box* strRfind(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'rfind' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
getTypeName(self)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
......@@ -905,7 +903,7 @@ Box* strRfind(BoxedString* self, Box* elt) {
extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
assert(self->cls == str_cls);
if (slice->cls == int_cls) {
if (isSubclass(slice->cls, int_cls)) {
BoxedInt* islice = static_cast<BoxedInt*>(slice);
int64_t n = islice->n;
int size = self->s.size();
......
......@@ -108,7 +108,7 @@ extern "C" PyObject* PyTuple_GetSlice(PyObject* p, Py_ssize_t low, Py_ssize_t hi
Box* tupleGetitem(BoxedTuple* self, Box* slice) {
assert(self->cls == tuple_cls);
if (slice->cls == int_cls)
if (isSubclass(slice->cls, int_cls))
return tupleGetitemInt(self, static_cast<BoxedInt*>(slice));
else if (slice->cls == slice_cls)
return tupleGetitemSlice(self, static_cast<BoxedSlice*>(slice));
......@@ -289,7 +289,7 @@ Box* tupleHash(BoxedTuple* self) {
int64_t rtn = 3527539;
for (Box* e : self->elts) {
BoxedInt* h = hash(e);
assert(h->cls == int_cls);
assert(isSubclass(h->cls, int_cls));
rtn ^= h->n + 0x9e3779b9 + (rtn << 6) + (rtn >> 2);
}
......
......@@ -825,8 +825,8 @@ void setupRuntime() {
// TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedBool), false);
int_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedInt), false);
bool_cls = new BoxedHeapClass(type_cls, int_cls, NULL, 0, sizeof(BoxedBool), false);
complex_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedComplex), false);
// TODO we're leaking long memory!
long_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedLong), false);
......
......@@ -308,11 +308,9 @@ public:
BoxedComplex(double r, double i) __attribute__((visibility("default"))) : Box(complex_cls), real(r), imag(i) {}
};
class BoxedBool : public Box {
class BoxedBool : public BoxedInt {
public:
bool b;
BoxedBool(bool b) __attribute__((visibility("default"))) : Box(bool_cls), b(b) {}
BoxedBool(bool b) __attribute__((visibility("default"))) : BoxedInt(bool_cls, b ? 1 : 0) {}
};
class BoxedString : public Box {
......
......@@ -30,22 +30,22 @@ void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64*
Box* step = sslice->step;
assert(step);
RELEASE_ASSERT(start->cls == int_cls || start->cls == none_cls, "");
RELEASE_ASSERT(stop->cls == int_cls || stop->cls == none_cls, "");
RELEASE_ASSERT(step->cls == int_cls || step->cls == none_cls, "");
RELEASE_ASSERT(isSubclass(start->cls, int_cls) || start->cls == none_cls, "");
RELEASE_ASSERT(isSubclass(stop->cls, int_cls) || stop->cls == none_cls, "");
RELEASE_ASSERT(isSubclass(step->cls, int_cls) || step->cls == none_cls, "");
int64_t istart;
int64_t istop;
int64_t istep = 1;
if (step->cls == int_cls) {
if (isSubclass(step->cls, int_cls)) {
istep = static_cast<BoxedInt*>(step)->n;
if (istep == 0) {
raiseExcHelper(ValueError, "slice step cannot be zero");
}
}
if (start->cls == int_cls) {
if (isSubclass(start->cls, int_cls)) {
istart = static_cast<BoxedInt*>(start)->n;
if (istart < 0)
istart = size + istart;
......@@ -55,7 +55,7 @@ void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64*
else
istart = size - 1;
}
if (stop->cls == int_cls) {
if (isSubclass(stop->cls, int_cls)) {
istop = static_cast<BoxedInt*>(stop)->n;
if (istop < 0)
istop = size + istop;
......
......@@ -15,3 +15,6 @@ print int(1.9)
print int(-1.1)
print int(-1.5)
print int(-1.9)
print int(True)
print int(False)
......@@ -15,3 +15,28 @@ f(())
f("")
f(0.0)
f(1L)
# Bools are subclasses of ints:
print 1 == True
print 0 == False
print 1 == False
print 0 == True
print True == 0
print type(hash(True))
print hash(0) == hash(False)
print hash(1) == hash(True)
print isinstance(True, int)
print isinstance(False, int)
print range(False, True, True)
print abs(True), abs(False)
d = {}
d[1] = "hello"
d[False] = "world"
print d[True], d[0]
print long(True), float(False)
1.0 + True
# expected: fail
# - C API exceptions are not yet supported
import math
print math.sqrt(-1)
try:
print math.sqrt(-1)
except ValueError, e:
print e
......@@ -76,3 +76,5 @@ for i in xrange(-10, 10):
print "hello world".partition("hi")
print "hello world".partition("hello")
print "hello world".partition("o")
print "hello world"[False:True:True]
import time
print type(time)
time.sleep(0)
time.sleep(False)
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