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;
......
This diff is collapsed.
......@@ -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;
......
This diff is collapsed.
......@@ -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