Commit 7ae78bdc authored by Kevin Modzelewski's avatar Kevin Modzelewski

Support subclassing from float

parent 8460bae3
......@@ -115,7 +115,8 @@ extern "C" Box* abs_(Box* x) {
} else if (x->cls == long_cls) {
return longAbs(static_cast<BoxedLong*>(x));
} else {
RELEASE_ASSERT(0, "%s", getTypeName(x)->c_str());
static const std::string abs_str("__abs__");
return callattr(x, &abs_str, CallattrFlags({.cls_only = true }), ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
}
......
......@@ -544,13 +544,29 @@ std::string floatFmt(double x, int precision, char code) {
return std::string(buf, n);
}
Box* floatNew(BoxedClass* cls, Box* a) {
RELEASE_ASSERT(cls == float_cls, "");
Box* floatNew(BoxedClass* _cls, Box* a) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, float_cls))
raiseExcHelper(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
// Note: "a->cls == cls" is not a strong enough condition to let us
// reuse the argument:
if (cls == float_cls && a->cls == float_cls)
return a;
assert(cls->tp_basicsize >= sizeof(BoxedFloat));
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedFloat* rtn = ::new (mem) BoxedFloat(cls, 0);
initUserAttrs(rtn, cls);
if (a->cls == float_cls) {
return a;
rtn->d = static_cast<BoxedFloat*>(a)->d;
} else if (isSubclass(a->cls, int_cls)) {
return boxFloat(static_cast<BoxedInt*>(a)->n);
rtn->d = static_cast<BoxedInt*>(a)->n;
} else if (a->cls == str_cls) {
const std::string& s = static_cast<BoxedString*>(a)->s;
if (s == "nan")
......@@ -562,13 +578,32 @@ Box* floatNew(BoxedClass* cls, Box* a) {
if (s == "-inf")
return boxFloat(-INFINITY);
return boxFloat(strtod(s.c_str(), NULL));
rtn->d = strtod(s.c_str(), NULL);
} else {
static const std::string float_str("__float__");
Box* r = callattr(a, &float_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (!r) {
fprintf(stderr, "TypeError: float() argument must be a string or a number, not '%s'\n",
getTypeName(a)->c_str());
raiseExcHelper(TypeError, "");
}
if (!isSubclass(r->cls, float_cls)) {
raiseExcHelper(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
}
rtn->d = static_cast<BoxedFloat*>(r)->d;
}
RELEASE_ASSERT(0, "%s", getTypeName(a)->c_str());
return rtn;
}
Box* floatStr(BoxedFloat* self) {
assert(self->cls == float_cls);
if (!isSubclass(self->cls, float_cls))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'float' object but received a '%s'",
getTypeName(self)->c_str());
return boxString(floatFmt(self->d, 12, 'g'));
}
......
......@@ -23,7 +23,7 @@ namespace pyston {
extern "C" inline Box* boxFloat(double d) __attribute__((visibility("default")));
extern "C" inline Box* boxFloat(double d) {
return new BoxedFloat(d);
return new BoxedFloat(float_cls, d);
}
extern "C" inline Box* boxComplex(double r, double i) __attribute__((visibility("default")));
......
......@@ -333,9 +333,23 @@ extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) {
int r = mpz_init_set_str(rtn->n, s.c_str(), 10);
RELEASE_ASSERT(r == 0, "");
} else {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n",
getTypeName(val)->c_str());
raiseExcHelper(TypeError, "");
static const std::string long_str("__long__");
Box* r = callattr(val, &long_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (!r) {
fprintf(stderr, "TypeError: long() argument must be a string or a number, not '%s'\n",
getTypeName(val)->c_str());
raiseExcHelper(TypeError, "");
}
if (isSubclass(r->cls, int_cls)) {
mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(r)->n);
} else if (!isSubclass(r->cls, long_cls)) {
raiseExcHelper(TypeError, "__long__ returned non-long (type %s)", r->cls->tp_name);
} else {
mpz_init_set(rtn->n, static_cast<BoxedLong*>(r)->n);
}
}
}
return rtn;
......
......@@ -297,7 +297,7 @@ class BoxedFloat : public Box {
public:
double d;
BoxedFloat(double d) __attribute__((visibility("default"))) : Box(float_cls), d(d) {}
BoxedFloat(BoxedClass* cls, double d) __attribute__((visibility("default"))) : Box(cls), d(d) {}
};
class BoxedComplex : public Box {
......
class CustomInt(int):
pass
print int.__new__(CustomInt, "1")
class CustomFloat(float):
pass
print float.__new__(CustomFloat, "1.0")
class CustomLong(long):
pass
print long.__new__(CustomLong, "10")
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