Commit 9f5eb123 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Templatize float() and int()

parent 5a6a15cf
......@@ -627,9 +627,17 @@ std::string floatFmt(double x, int precision, char code) {
return std::string(buf, n);
}
BoxedFloat* _floatNew(Box* a) {
template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == CAPI) {
// FIXME CPython uses PyUnicode_EncodeDecimal:
a = coerceUnicodeToStr(a);
try {
a = coerceUnicodeToStr(a);
} catch (ExcInfo e) {
if (S == CAPI) {
throwCAPIException();
return NULL;
}
throw e;
}
if (a->cls == float_cls) {
return static_cast<BoxedFloat*>(a);
......@@ -653,40 +661,70 @@ BoxedFloat* _floatNew(Box* a) {
assert(s.data()[s.size()] == '\0');
const char* startptr = s.data();
double r = strtod(startptr, &endptr);
if (endptr != startptr + s.size())
raiseExcHelper(ValueError, "could not convert string to float: %s", s.data());
if (endptr != startptr + s.size()) {
if (S == CAPI) {
PyErr_Format(ValueError, "could not convert string to float: %s", s.data());
return NULL;
} else
raiseExcHelper(ValueError, "could not convert string to float: %s", s.data());
}
return new BoxedFloat(r);
} else {
static BoxedString* float_str = internStringImmortal("__float__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* r = callattr(a, float_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
Box* r = callattrInternal<S>(a, float_str, CLASS_ONLY, NULL, 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));
raiseExcHelper(TypeError, "");
if (S == CAPI) {
if (!PyErr_Occurred())
PyErr_Format(TypeError, "float() argument must be a string or a number, not '%s'\n",
getTypeName(a));
return NULL;
} else {
raiseExcHelper(TypeError, "float() argument must be a string or a number, not '%s'\n", getTypeName(a));
}
}
if (!isSubclass(r->cls, float_cls)) {
raiseExcHelper(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
if (S == CAPI) {
PyErr_Format(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
return NULL;
} else
raiseExcHelper(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
}
return static_cast<BoxedFloat*>(r);
}
}
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));
template <ExceptionStyle S> Box* floatNew(BoxedClass* _cls, Box* a) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_cls)) {
if (S == CAPI) {
PyErr_Format(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls));
return NULL;
} else
raiseExcHelper(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls));
}
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),
getNameOfClass(cls));
if (!isSubclass(cls, float_cls)) {
if (S == CAPI) {
PyErr_Format(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls),
getNameOfClass(cls));
return NULL;
} else {
raiseExcHelper(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls),
getNameOfClass(cls));
}
}
if (cls == float_cls)
return _floatNew(a);
return _floatNew<S>(a);
BoxedFloat* f = _floatNew(a);
BoxedFloat* f = _floatNew<S>(a);
if (!f) {
assert(S == CAPI);
return NULL;
}
return new (cls) BoxedFloat(f->d);
}
......@@ -1476,8 +1514,9 @@ void setupFloat() {
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
float_cls->giveAttr(
"__new__", new BoxedFunction(boxRTFunction((void*)floatNew, UNKNOWN, 2, 1, false, false), { boxFloat(0.0) }));
auto float_new = boxRTFunction((void*)floatNew<CXX>, UNKNOWN, 2, 1, false, false, ParamNames::empty(), CXX);
addRTFunction(float_new, (void*)floatNew<CAPI>, UNKNOWN, CAPI);
float_cls->giveAttr("__new__", new BoxedFunction(float_new, { boxFloat(0.0) }));
float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, BOXED_FLOAT, 1)));
float_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)floatPos, BOXED_FLOAT, 1)));
......
......@@ -884,7 +884,7 @@ extern "C" Box* intIndex(BoxedInt* v) {
return boxInt(v->n);
}
static Box* _intNew(Box* val, Box* base) {
template <ExceptionStyle S> static Box* _intNew(Box* val, Box* base) noexcept(S == CAPI) {
if (val->cls == int_cls) {
RELEASE_ASSERT(!base, "");
BoxedInt* n = static_cast<BoxedInt*>(val);
......@@ -904,8 +904,12 @@ static Box* _intNew(Box* val, Box* base) {
RELEASE_ASSERT(s->size() == strlen(s->data()), "");
Box* r = PyInt_FromString(s->data(), NULL, base_n);
if (!r)
throwCAPIException();
if (!r) {
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return r;
} else if (isSubclass(val->cls, unicode_cls)) {
int base_n;
......@@ -917,8 +921,12 @@ static Box* _intNew(Box* val, Box* base) {
}
Box* r = PyInt_FromUnicode(PyUnicode_AS_UNICODE(val), PyUnicode_GET_SIZE(val), base_n);
if (!r)
throwCAPIException();
if (!r) {
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return r;
} else if (val->cls == float_cls) {
RELEASE_ASSERT(!base, "");
......@@ -952,39 +960,68 @@ static Box* _intNew(Box* val, Box* base) {
} else {
RELEASE_ASSERT(!base, "");
static BoxedString* int_str = internStringImmortal("__int__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* r = callattr(val, int_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
Box* r = callattrInternal<S>(val, int_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (!r) {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n", getTypeName(val));
raiseExcHelper(TypeError, "");
if (S == CAPI) {
if (!PyErr_Occurred())
PyErr_Format(TypeError, "int() argument must be a string or a number, not '%s'\n",
getTypeName(val));
return NULL;
} else {
raiseExcHelper(TypeError, "int() argument must be a string or a number, not '%s'\n", getTypeName(val));
}
}
if (!PyInt_Check(r) && !PyLong_Check(r)) {
raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
if (S == CAPI) {
PyErr_Format(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
return NULL;
} else
raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
}
return r;
}
}
extern "C" Box* intNew(Box* _cls, Box* val, Box* base) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls));
template <ExceptionStyle S> Box* intNew(Box* _cls, Box* val, Box* base) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_cls)) {
if (S == CAPI) {
PyErr_Format(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls));
return NULL;
} else
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls));
}
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),
getNameOfClass(cls));
if (!isSubclass(cls, int_cls)) {
if (S == CAPI) {
PyErr_Format(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls),
getNameOfClass(cls));
return NULL;
} else
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls),
getNameOfClass(cls));
}
if (cls == int_cls)
return _intNew(val, base);
return _intNew<S>(val, base);
BoxedInt* n = (BoxedInt*)_intNew<S>(val, base);
if (!n) {
assert(S == CAPI);
return NULL;
}
BoxedInt* n = (BoxedInt*)_intNew(val, base);
if (n->cls == long_cls) {
if (cls == int_cls)
return n;
raiseExcHelper(OverflowError, "Python int too large to convert to C long", getNameOfClass(cls),
getNameOfClass(cls));
if (S == CAPI) {
PyErr_Format(OverflowError, "Python int too large to convert to C long");
return NULL;
} else
raiseExcHelper(OverflowError, "Python int too large to convert to C long");
}
return new (cls) BoxedInt(n->n);
}
......@@ -1138,9 +1175,10 @@ void setupInt() {
int_cls->giveAttr("__index__", new BoxedFunction(boxRTFunction((void*)intIndex, BOXED_INT, 1)));
int_cls->giveAttr("__int__", new BoxedFunction(boxRTFunction((void*)intInt, BOXED_INT, 1)));
int_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)intNew, UNKNOWN, 3, 2, false, false,
ParamNames({ "", "x", "base" }, "", "")),
{ boxInt(0), NULL }));
auto int_new
= boxRTFunction((void*)intNew<CXX>, UNKNOWN, 3, 2, false, false, ParamNames({ "", "x", "base" }, "", ""), CXX);
addRTFunction(int_new, (void*)intNew<CAPI>, UNKNOWN, CAPI);
int_cls->giveAttr("__new__", new BoxedFunction(int_new, { boxInt(0), NULL }));
int_cls->giveAttr("bit_length", new BoxedFunction(boxRTFunction((void*)intBitLength, BOXED_INT, 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