Commit 8c5a8657 authored by Marius Wachtler's avatar Marius Wachtler

implement tp_str and tp_repr for more of our builtin types

parent 6a33d150
...@@ -41,12 +41,14 @@ public: ...@@ -41,12 +41,14 @@ public:
PyCFunction getFunction() { return method_def->ml_meth; } PyCFunction getFunction() { return method_def->ml_meth; }
static BoxedString* __repr__(BoxedCApiFunction* self) { template <ExceptionStyle S> static Box* __repr__(Box* _self) noexcept(S == CAPI) {
assert(self->cls == capifunc_cls); if (!isSubclass(_self->cls, capifunc_cls))
return setDescrTypeError<S>(_self, "capifunc", "__repr__");
BoxedCApiFunction* self = (BoxedCApiFunction*)_self;
if (self->passthrough == NULL) if (self->passthrough == NULL)
return (BoxedString*)PyString_FromFormat("<built-in function %s>", self->method_def->ml_name); return callCAPIFromStyle<S>(PyString_FromFormat, "<built-in function %s>", self->method_def->ml_name);
return (BoxedString*)PyString_FromFormat("<built-in method %s of %s object at %p>", self->method_def->ml_name, return callCAPIFromStyle<S>(PyString_FromFormat, "<built-in method %s of %s object at %p>",
self->passthrough->cls->tp_name, self->passthrough); self->method_def->ml_name, self->passthrough->cls->tp_name, self->passthrough);
} }
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs); static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs);
......
...@@ -30,9 +30,11 @@ extern "C" Box* boolNonzero(BoxedBool* v) { ...@@ -30,9 +30,11 @@ extern "C" Box* boolNonzero(BoxedBool* v) {
return incref(v); return incref(v);
} }
extern "C" Box* boolRepr(BoxedBool* v) { template <ExceptionStyle S> Box* boolRepr(Box* v) noexcept(S == CAPI) {
static BoxedString* true_str = getStaticString("True"); static BoxedString* true_str = getStaticString("True");
static BoxedString* false_str = getStaticString("False"); static BoxedString* false_str = getStaticString("False");
if (!PyBool_Check(v))
return setDescrTypeError<S>(v, "bool", "__repr__");
if (v == Py_True) if (v == Py_True)
return incref(true_str); return incref(true_str);
...@@ -92,7 +94,7 @@ void setupBool() { ...@@ -92,7 +94,7 @@ void setupBool() {
bool_cls->tp_as_number = &bool_as_number; bool_cls->tp_as_number = &bool_as_number;
bool_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)boolNonzero, BOXED_BOOL, 1))); bool_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)boolNonzero, BOXED_BOOL, 1)));
bool_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)boolRepr, STR, 1))); bool_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)boolRepr<CXX>, STR, 1)));
bool_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)boolHash, BOXED_INT, 1))); bool_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)boolHash, BOXED_INT, 1)));
bool_cls->giveAttr("__new__", bool_cls->giveAttr("__new__",
...@@ -105,5 +107,6 @@ void setupBool() { ...@@ -105,5 +107,6 @@ void setupBool() {
bool_cls->freeze(); bool_cls->freeze();
bool_cls->tp_hash = (hashfunc)bool_hash; bool_cls->tp_hash = (hashfunc)bool_hash;
bool_cls->tp_repr = boolRepr<CAPI>;
} }
} }
...@@ -1907,8 +1907,8 @@ extern "C" int PyCFunction_ClearFreeList() noexcept { ...@@ -1907,8 +1907,8 @@ extern "C" int PyCFunction_ClearFreeList() noexcept {
} }
void setupCAPI() { void setupCAPI() {
capifunc_cls->giveAttr("__repr__", capifunc_cls->giveAttr(
new BoxedFunction(FunctionMetadata::create((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1))); "__repr__", new BoxedFunction(FunctionMetadata::create((void*)BoxedCApiFunction::__repr__<CXX>, UNKNOWN, 1)));
auto capi_call auto capi_call
= new BoxedFunction(FunctionMetadata::create((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, true, true)); = new BoxedFunction(FunctionMetadata::create((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, true, true));
...@@ -1920,5 +1920,6 @@ void setupCAPI() { ...@@ -1920,5 +1920,6 @@ void setupCAPI() {
capifunc_cls->giveAttrMember("__module__", T_OBJECT, offsetof(BoxedCApiFunction, module)); capifunc_cls->giveAttrMember("__module__", T_OBJECT, offsetof(BoxedCApiFunction, module));
capifunc_cls->freeze(); capifunc_cls->freeze();
capifunc_cls->tp_repr = BoxedCApiFunction::__repr__<CAPI>;
} }
} }
...@@ -438,16 +438,12 @@ Box* complexNonzero(BoxedComplex* self) { ...@@ -438,16 +438,12 @@ Box* complexNonzero(BoxedComplex* self) {
return boxBool(res); return boxBool(res);
} }
Box* complexStr(BoxedComplex* self) {
template <ExceptionStyle S> Box* complexStr(Box* self) noexcept(S == CAPI) {
if (!PyComplex_Check(self)) if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'complex' object but received a '%s'", return setDescrTypeError<S>(self, "complex", "__str__");
getTypeName(self));
Box* r = complex_format((PyComplexObject*)self, 12, 'g'); return callCAPIFromStyle<S>(complex_format, (PyComplexObject*)self, 12, 'g');
if (!r) {
throwCAPIException();
}
return r;
} }
Box* complexInt(BoxedComplex* self) { Box* complexInt(BoxedComplex* self) {
...@@ -474,16 +470,11 @@ Box* complexLong(BoxedComplex* self) { ...@@ -474,16 +470,11 @@ Box* complexLong(BoxedComplex* self) {
raiseExcHelper(TypeError, "can't convert complex to long"); raiseExcHelper(TypeError, "can't convert complex to long");
} }
Box* complexRepr(BoxedComplex* self) { template <ExceptionStyle S> Box* complexRepr(Box* self) noexcept(S == CAPI) {
if (!PyComplex_Check(self)) if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'complex' object but received a '%s'", return setDescrTypeError<S>(self, "complex", "__repr__");
getTypeName(self));
Box* r = complex_format((PyComplexObject*)self, 16, 'g'); return callCAPIFromStyle<S>(complex_format, (PyComplexObject*)self, 16, 'g');
if (!r) {
throwCAPIException();
}
return r;
} }
template <ExceptionStyle S> Box* complexNew(BoxedClass* cls, Box* real, Box* imag) noexcept(S == CAPI) { template <ExceptionStyle S> Box* complexNew(BoxedClass* cls, Box* real, Box* imag) noexcept(S == CAPI) {
...@@ -806,11 +797,11 @@ void setupComplex() { ...@@ -806,11 +797,11 @@ void setupComplex() {
complex_cls->giveAttr("__neg__", new BoxedFunction(FunctionMetadata::create((void*)complexNeg, BOXED_COMPLEX, 1))); complex_cls->giveAttr("__neg__", new BoxedFunction(FunctionMetadata::create((void*)complexNeg, BOXED_COMPLEX, 1)));
complex_cls->giveAttr("__pos__", new BoxedFunction(FunctionMetadata::create((void*)complexPos, BOXED_COMPLEX, 1))); complex_cls->giveAttr("__pos__", new BoxedFunction(FunctionMetadata::create((void*)complexPos, BOXED_COMPLEX, 1)));
complex_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)complexHash, BOXED_INT, 1))); complex_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)complexHash, BOXED_INT, 1)));
complex_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)complexStr, STR, 1))); complex_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)complexStr<CXX>, STR, 1)));
complex_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)complexInt, UNKNOWN, 1))); complex_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)complexInt, UNKNOWN, 1)));
complex_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)complexFloat, UNKNOWN, 1))); complex_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)complexFloat, UNKNOWN, 1)));
complex_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)complexLong, UNKNOWN, 1))); complex_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)complexLong, UNKNOWN, 1)));
complex_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)complexRepr, STR, 1))); complex_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)complexRepr<CXX>, STR, 1)));
complex_cls->giveAttrMember("real", T_DOUBLE, offsetof(BoxedComplex, real), true); complex_cls->giveAttrMember("real", T_DOUBLE, offsetof(BoxedComplex, real), true);
complex_cls->giveAttrMember("imag", T_DOUBLE, offsetof(BoxedComplex, imag), true); complex_cls->giveAttrMember("imag", T_DOUBLE, offsetof(BoxedComplex, imag), true);
...@@ -824,6 +815,8 @@ void setupComplex() { ...@@ -824,6 +815,8 @@ void setupComplex() {
add_operators(complex_cls); add_operators(complex_cls);
complex_cls->freeze(); complex_cls->freeze();
complex_cls->tp_str = complexStr<CAPI>;
complex_cls->tp_repr = complexRepr<CAPI>;
complex_cls->tp_as_number->nb_negative = (unaryfunc)complex_neg; complex_cls->tp_as_number->nb_negative = (unaryfunc)complex_neg;
complex_cls->tp_richcompare = complex_richcompare; complex_cls->tp_richcompare = complex_richcompare;
} }
......
...@@ -780,16 +780,16 @@ extern "C" Box* floatFloat(BoxedFloat* self) { ...@@ -780,16 +780,16 @@ extern "C" Box* floatFloat(BoxedFloat* self) {
return boxFloat(self->d); return boxFloat(self->d);
} }
Box* floatStr(BoxedFloat* self) { template <ExceptionStyle S> Box* floatStr(BoxedFloat* self) noexcept(S == CAPI) {
if (!PyFloat_Check(self)) if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'float' object but received a '%s'", return setDescrTypeError<S>(self, "float", "__str__");
getTypeName(self)); return callCAPIFromStyle<S>(float_str_or_repr, self->d, PyFloat_STR_PRECISION, 'g');
return float_str_or_repr(self->d, PyFloat_STR_PRECISION, 'g');
} }
Box* floatRepr(BoxedFloat* self) { template <ExceptionStyle S> Box* floatRepr(BoxedFloat* self) noexcept(S == CAPI) {
return float_str_or_repr(self->d, 0, 'r'); if (!PyFloat_Check(self))
return setDescrTypeError<S>(self, "float", "__repr__");
return callCAPIFromStyle<S>(float_str_or_repr, self->d, 0, 'r');
} }
Box* floatToInt(BoxedFloat* self) { Box* floatToInt(BoxedFloat* self) {
...@@ -996,8 +996,8 @@ void setupFloat() { ...@@ -996,8 +996,8 @@ void setupFloat() {
// float_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)floatNonzero, NULL, 1))); // float_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)floatNonzero, NULL, 1)));
float_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)floatFloat, BOXED_FLOAT, 1))); float_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)floatFloat, BOXED_FLOAT, 1)));
float_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)floatStr, STR, 1))); float_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)floatStr<CXX>, STR, 1)));
float_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)floatRepr, STR, 1))); float_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)floatRepr<CXX>, STR, 1)));
float_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)floatCoerce, UNKNOWN, 2))); float_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)floatCoerce, UNKNOWN, 2)));
float_cls->giveAttr("__trunc__", new BoxedFunction(FunctionMetadata::create((void*)floatTrunc, UNKNOWN, 1))); float_cls->giveAttr("__trunc__", new BoxedFunction(FunctionMetadata::create((void*)floatTrunc, UNKNOWN, 1)));
...@@ -1021,8 +1021,9 @@ void setupFloat() { ...@@ -1021,8 +1021,9 @@ void setupFloat() {
_PyFloat_Init(); _PyFloat_Init();
float_cls->tp_str = float_str;
float_cls->tp_as_number->nb_power = float_pow; float_cls->tp_as_number->nb_power = float_pow;
float_cls->tp_new = (newfunc)floatNewPacked; float_cls->tp_new = (newfunc)floatNewPacked;
float_cls->tp_repr = (reprfunc)floatRepr<CAPI>;
float_cls->tp_str = (reprfunc)floatStr<CAPI>;
} }
} }
...@@ -60,7 +60,11 @@ extern "C" PyObject* PyList_AsTuple(PyObject* v) noexcept { ...@@ -60,7 +60,11 @@ extern "C" PyObject* PyList_AsTuple(PyObject* v) noexcept {
return BoxedTuple::create(l->size, &l->elts->elts[0]); return BoxedTuple::create(l->size, &l->elts->elts[0]);
} }
extern "C" Box* listRepr(BoxedList* self) { extern "C" Box* listRepr(Box* _self) {
if (!PyList_Check(_self))
return setDescrTypeError<CXX>(_self, "list", "__repr__");
BoxedList* self = (BoxedList*)_self;
std::vector<char> chars; std::vector<char> chars;
int status = Py_ReprEnter((PyObject*)self); int status = Py_ReprEnter((PyObject*)self);
...@@ -98,6 +102,10 @@ extern "C" Box* listRepr(BoxedList* self) { ...@@ -98,6 +102,10 @@ extern "C" Box* listRepr(BoxedList* self) {
return boxString(llvm::StringRef(&chars[0], chars.size())); return boxString(llvm::StringRef(&chars[0], chars.size()));
} }
Box* list_repr(Box* self) noexcept {
return callCXXFromStyle<CAPI>(listRepr, self);
}
extern "C" Box* listNonzero(BoxedList* self) { extern "C" Box* listNonzero(BoxedList* self) {
return boxBool(self->size != 0); return boxBool(self->size != 0);
} }
...@@ -1527,6 +1535,7 @@ void setupList() { ...@@ -1527,6 +1535,7 @@ void setupList() {
list_cls->giveAttrBorrowed("__hash__", None); list_cls->giveAttrBorrowed("__hash__", None);
list_cls->freeze(); list_cls->freeze();
list_cls->tp_iter = listIter; list_cls->tp_iter = listIter;
list_cls->tp_repr = list_repr;
list_cls->tp_as_sequence->sq_length = list_length; list_cls->tp_as_sequence->sq_length = list_length;
list_cls->tp_as_sequence->sq_concat = (binaryfunc)list_concat; list_cls->tp_as_sequence->sq_concat = (binaryfunc)list_concat;
......
...@@ -823,16 +823,16 @@ Box* longFloat(BoxedLong* v) { ...@@ -823,16 +823,16 @@ Box* longFloat(BoxedLong* v) {
return longToFloat(v); return longToFloat(v);
} }
Box* longRepr(BoxedLong* v) { template <ExceptionStyle S> Box* longRepr(Box* v) noexcept(S == CAPI) {
if (!PyLong_Check(v)) if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'long' object but received a '%s'", getTypeName(v)); return setDescrTypeError<S>(v, "long", "__repr__");
return _PyLong_Format(v, 10, 1 /* add L */, 0); return callCAPIFromStyle<S>(_PyLong_Format, v, 10, 1 /* add L */, 0);
} }
Box* longStr(BoxedLong* v) { template <ExceptionStyle S> Box* longStr(Box* v) noexcept(S == CAPI) {
if (!PyLong_Check(v)) if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'long' object but received a '%s'", getTypeName(v)); return setDescrTypeError<S>(v, "long", "__str__");
return _PyLong_Format(v, 10, 0 /* no L */, 0); return callCAPIFromStyle<S>(_PyLong_Format, v, 10, 0 /* no L */, 0);
} }
Box* long__format__(BoxedLong* self, Box* format_spec) noexcept { Box* long__format__(BoxedLong* self, Box* format_spec) noexcept {
...@@ -1744,8 +1744,8 @@ void setupLong() { ...@@ -1744,8 +1744,8 @@ void setupLong() {
long_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)longInt, UNKNOWN, 1))); long_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)longInt, UNKNOWN, 1)));
long_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)longFloat, UNKNOWN, 1))); long_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)longFloat, UNKNOWN, 1)));
long_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)longRepr, STR, 1))); long_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)longRepr<CXX>, STR, 1)));
long_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)longStr, STR, 1))); long_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)longStr<CXX>, STR, 1)));
long_cls->giveAttr("__format__", new BoxedFunction(FunctionMetadata::create((void*)longFormat, STR, 2))); long_cls->giveAttr("__format__", new BoxedFunction(FunctionMetadata::create((void*)longFormat, STR, 2)));
long_cls->giveAttr("__bin__", new BoxedFunction(FunctionMetadata::create((void*)longBin, STR, 1))); long_cls->giveAttr("__bin__", new BoxedFunction(FunctionMetadata::create((void*)longBin, STR, 1)));
long_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)longHex, STR, 1))); long_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)longHex, STR, 1)));
...@@ -1786,5 +1786,7 @@ void setupLong() { ...@@ -1786,5 +1786,7 @@ void setupLong() {
long_cls->tp_as_number->nb_power = long_pow; long_cls->tp_as_number->nb_power = long_pow;
long_cls->tp_hash = long_hash; long_cls->tp_hash = long_hash;
long_cls->tp_repr = longRepr<CAPI>;
long_cls->tp_str = longStr<CAPI>;
} }
} }
...@@ -39,8 +39,6 @@ public: ...@@ -39,8 +39,6 @@ public:
extern "C" Box* createLong(llvm::StringRef s); extern "C" Box* createLong(llvm::StringRef s);
extern "C" BoxedLong* boxLong(int64_t n); extern "C" BoxedLong* boxLong(int64_t n);
Box* longRepr(BoxedLong* v);
Box* longNeg(BoxedLong* lhs); Box* longNeg(BoxedLong* lhs);
Box* longAbs(BoxedLong* v1); Box* longAbs(BoxedLong* v1);
......
...@@ -213,6 +213,21 @@ static const char* objectNewParameterTypeErrorMsg() { ...@@ -213,6 +213,21 @@ static const char* objectNewParameterTypeErrorMsg() {
} }
} }
// use this like:
// if (!PyBool_Check(v))
// return setDescrTypeError<S>(v, "bool", "__repr__");
// ...
template <ExceptionStyle S>
Box* __attribute__((warn_unused_result))
setDescrTypeError(Box* got, const char* expected_cls_name, const char* descr_name) {
if (S == CXX)
raiseExcHelper((PyTypeObject*)PyExc_TypeError, "descriptor '%s' requires a '%s' object but received a '%s'",
descr_name, expected_cls_name, getTypeName(got));
PyErr_Format(PyExc_TypeError, "descriptor '%s' requires a '%s' object but received a '%s'", descr_name,
expected_cls_name, getTypeName(got));
return NULL;
}
inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int num_args) { inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int num_args) {
Box* arg1 = num_args >= 1 ? args[0] : nullptr; Box* arg1 = num_args >= 1 ? args[0] : nullptr;
Box* arg2 = num_args >= 2 ? args[1] : nullptr; Box* arg2 = num_args >= 2 ? args[1] : nullptr;
......
...@@ -248,9 +248,11 @@ Box* setInit(Box* _self, Box* container, BoxedDict* kwargs) { ...@@ -248,9 +248,11 @@ Box* setInit(Box* _self, Box* container, BoxedDict* kwargs) {
return incref(None); return incref(None);
} }
static Box* setRepr(BoxedSet* self) { static Box* setRepr(Box* _self) {
RELEASE_ASSERT(PyAnySet_Check(self), ""); if (!PyAnySet_Check(_self))
return setDescrTypeError<CXX>(_self, "set", "__repr__");
BoxedSet* self = (BoxedSet*)_self;
std::vector<char> chars; std::vector<char> chars;
int status = Py_ReprEnter((PyObject*)self); int status = Py_ReprEnter((PyObject*)self);
...@@ -298,6 +300,9 @@ static Box* setRepr(BoxedSet* self) { ...@@ -298,6 +300,9 @@ static Box* setRepr(BoxedSet* self) {
Py_ReprLeave((PyObject*)self); Py_ReprLeave((PyObject*)self);
return boxString(llvm::StringRef(&chars[0], chars.size())); return boxString(llvm::StringRef(&chars[0], chars.size()));
} }
static Box* set_repr(Box* self) noexcept {
return callCXXFromStyle<CAPI>(setRepr, self);
}
static void _setSymmetricDifferenceUpdate(BoxedSet* self, Box* other) { static void _setSymmetricDifferenceUpdate(BoxedSet* self, Box* other) {
if (!PyAnySet_Check(other)) { if (!PyAnySet_Check(other)) {
...@@ -966,11 +971,9 @@ void setupSet() { ...@@ -966,11 +971,9 @@ void setupSet() {
frozenset_cls->giveAttr( frozenset_cls->giveAttr(
"__new__", new BoxedFunction(FunctionMetadata::create((void*)frozensetNew, UNKNOWN, 2, false, true), { NULL })); "__new__", new BoxedFunction(FunctionMetadata::create((void*)frozensetNew, UNKNOWN, 2, false, true), { NULL }));
Box* set_repr = new BoxedFunction(FunctionMetadata::create((void*)setRepr, STR, 1)); Box* set_repr_func = new BoxedFunction(FunctionMetadata::create((void*)setRepr, STR, 1));
set_cls->giveAttrBorrowed("__repr__", set_repr); set_cls->giveAttrBorrowed("__repr__", set_repr_func);
set_cls->giveAttrBorrowed("__str__", set_repr); frozenset_cls->giveAttr("__repr__", set_repr_func);
frozenset_cls->giveAttrBorrowed("__repr__", set_repr);
frozenset_cls->giveAttr("__str__", set_repr);
std::vector<ConcreteCompilerType*> v_ss, v_sf, v_su, v_ff, v_fs, v_fu; std::vector<ConcreteCompilerType*> v_ss, v_sf, v_su, v_ff, v_fs, v_fu;
v_ss.push_back(SET); v_ss.push_back(SET);
...@@ -1083,7 +1086,7 @@ void setupSet() { ...@@ -1083,7 +1086,7 @@ void setupSet() {
set_cls->freeze(); set_cls->freeze();
frozenset_cls->freeze(); frozenset_cls->freeze();
set_cls->tp_iter = (decltype(set_cls->tp_iter))setIter; frozenset_cls->tp_repr = set_cls->tp_repr = set_repr;
frozenset_cls->tp_iter = (decltype(frozenset_cls->tp_iter))setIter; frozenset_cls->tp_iter = set_cls->tp_iter = (decltype(set_cls->tp_iter))setIter;
} }
} }
...@@ -259,9 +259,11 @@ extern "C" Py_ssize_t PyTuple_Size(PyObject* op) noexcept { ...@@ -259,9 +259,11 @@ extern "C" Py_ssize_t PyTuple_Size(PyObject* op) noexcept {
return static_cast<BoxedTuple*>(op)->size(); return static_cast<BoxedTuple*>(op)->size();
} }
Box* tupleRepr(BoxedTuple* t) { Box* tupleRepr(Box* _t) {
if (!PyTuple_Check(_t))
return setDescrTypeError<CXX>(_t, "tuple", "__repr__");
assert(PyTuple_Check(t)); BoxedTuple* t = (BoxedTuple*)_t;
int n; int n;
std::vector<char> chars; std::vector<char> chars;
int status = Py_ReprEnter((PyObject*)t); int status = Py_ReprEnter((PyObject*)t);
...@@ -308,6 +310,9 @@ Box* tupleRepr(BoxedTuple* t) { ...@@ -308,6 +310,9 @@ Box* tupleRepr(BoxedTuple* t) {
return boxString(llvm::StringRef(&chars[0], chars.size())); return boxString(llvm::StringRef(&chars[0], chars.size()));
} }
static Box* tuple_repr(Box* v) noexcept {
return callCXXFromStyle<CAPI>(tupleRepr, v);
}
Box* tupleNonzero(BoxedTuple* self) { Box* tupleNonzero(BoxedTuple* self) {
RELEASE_ASSERT(PyTuple_Check(self), ""); RELEASE_ASSERT(PyTuple_Check(self), "");
...@@ -810,6 +815,7 @@ void setupTuple() { ...@@ -810,6 +815,7 @@ void setupTuple() {
tuple_cls->tp_as_sequence->sq_repeat = (ssizeargfunc)tuplerepeat; tuple_cls->tp_as_sequence->sq_repeat = (ssizeargfunc)tuplerepeat;
tuple_cls->tp_as_sequence->sq_contains = (objobjproc)tuplecontains; tuple_cls->tp_as_sequence->sq_contains = (objobjproc)tuplecontains;
tuple_cls->tp_iter = tupleIter; tuple_cls->tp_iter = tupleIter;
tuple_cls->tp_repr = tuple_repr;
tuple_cls->tp_as_mapping->mp_length = (lenfunc)tuplelength; tuple_cls->tp_as_mapping->mp_length = (lenfunc)tuplelength;
tuple_cls->tp_as_mapping->mp_subscript = (binaryfunc)tupleGetitem<CAPI>; tuple_cls->tp_as_mapping->mp_subscript = (binaryfunc)tupleGetitem<CAPI>;
......
...@@ -1503,10 +1503,13 @@ static Box* builtinFunctionOrMethodCall(BoxedBuiltinFunctionOrMethod* self, Box* ...@@ -1503,10 +1503,13 @@ static Box* builtinFunctionOrMethodCall(BoxedBuiltinFunctionOrMethod* self, Box*
NULL); NULL);
} }
extern "C" BoxedString* functionRepr(BoxedFunction* v) { template <ExceptionStyle S> static Box* functionRepr(Box* _v) noexcept(S == CAPI) {
if (!isSubclass(_v->cls, function_cls))
return setDescrTypeError<S>(_v, "function", "__repr__");
BoxedFunction* v = (BoxedFunction*)_v;
if (!v->name) if (!v->name)
return (BoxedString*)PyString_FromFormat("<function <name_missing?> at %p>", v); return callCAPIFromStyle<S>(PyString_FromFormat, "<function <name_missing?> at %p>", v);
return (BoxedString*)PyString_FromFormat("<function %s at %p>", PyString_AsString(v->name), v); return callCAPIFromStyle<S>(PyString_FromFormat, "<function %s at %p>", PyString_AsString(v->name), v);
} }
static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) { static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) {
...@@ -2057,7 +2060,12 @@ extern "C" PyObject* PySlice_New(PyObject* start, PyObject* stop, PyObject* step ...@@ -2057,7 +2060,12 @@ extern "C" PyObject* PySlice_New(PyObject* start, PyObject* stop, PyObject* step
return createSlice(start, stop, step); return createSlice(start, stop, step);
} }
Box* typeRepr(BoxedClass* self) { Box* typeRepr(Box* _self) {
if (!isSubclass(_self->cls, type_cls))
return setDescrTypeError<CXX>(_self, "type", "__repr__");
BoxedClass* self = (BoxedClass*)_self;
std::string O(""); std::string O("");
llvm::raw_string_ostream os(O); llvm::raw_string_ostream os(O);
...@@ -2081,6 +2089,10 @@ Box* typeRepr(BoxedClass* self) { ...@@ -2081,6 +2089,10 @@ Box* typeRepr(BoxedClass* self) {
return boxString(os.str()); return boxString(os.str());
} }
static Box* type_repr(Box* self) noexcept {
return callCXXFromStyle<CAPI>(typeRepr, self);
}
static PyObject* type_module(Box* _type, void* context) noexcept { static PyObject* type_module(Box* _type, void* context) noexcept {
PyTypeObject* type = static_cast<PyTypeObject*>(_type); PyTypeObject* type = static_cast<PyTypeObject*>(_type);
...@@ -4364,6 +4376,7 @@ void setupRuntime() { ...@@ -4364,6 +4376,7 @@ void setupRuntime() {
type_cls->freeze(); type_cls->freeze();
type_cls->tp_new = type_new; type_cls->tp_new = type_new;
type_cls->tp_repr = type_repr;
type_cls->tpp_call.capi_val = &typeTppCall<CAPI>; type_cls->tpp_call.capi_val = &typeTppCall<CAPI>;
type_cls->tpp_call.cxx_val = &typeTppCall<CXX>; type_cls->tpp_call.cxx_val = &typeTppCall<CXX>;
...@@ -4428,7 +4441,7 @@ void setupRuntime() { ...@@ -4428,7 +4441,7 @@ void setupRuntime() {
{ None, None, None })); { None, None, None }));
function_cls->giveAttrBorrowed("__dict__", dict_descr); function_cls->giveAttrBorrowed("__dict__", dict_descr);
function_cls->giveAttrDescriptor("__name__", func_name, func_set_name); function_cls->giveAttrDescriptor("__name__", func_name, func_set_name);
function_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)functionRepr, STR, 1))); function_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)functionRepr<CXX>, STR, 1)));
function_cls->giveAttrMember("__module__", T_OBJECT, offsetof(BoxedFunction, modname), false); function_cls->giveAttrMember("__module__", T_OBJECT, offsetof(BoxedFunction, modname), false);
function_cls->giveAttrMember("__doc__", T_OBJECT, offsetof(BoxedFunction, doc), false); function_cls->giveAttrMember("__doc__", T_OBJECT, offsetof(BoxedFunction, doc), false);
function_cls->giveAttrBorrowed("func_doc", function_cls->getattr(getStaticString("__doc__"))); function_cls->giveAttrBorrowed("func_doc", function_cls->getattr(getStaticString("__doc__")));
...@@ -4448,6 +4461,7 @@ void setupRuntime() { ...@@ -4448,6 +4461,7 @@ void setupRuntime() {
function_cls->giveAttrMember("func_closure", T_OBJECT, offsetof(BoxedFunction, closure), true); function_cls->giveAttrMember("func_closure", T_OBJECT, offsetof(BoxedFunction, closure), true);
function_cls->freeze(); function_cls->freeze();
function_cls->tp_descr_get = function_descr_get; function_cls->tp_descr_get = function_descr_get;
function_cls->tp_repr = functionRepr<CAPI>;
builtin_function_or_method_cls->giveAttrMember("__module__", T_OBJECT, builtin_function_or_method_cls->giveAttrMember("__module__", T_OBJECT,
offsetof(BoxedBuiltinFunctionOrMethod, modname)); offsetof(BoxedBuiltinFunctionOrMethod, modname));
......
...@@ -478,16 +478,22 @@ template <typename B> B* xincref(B* b) { ...@@ -478,16 +478,22 @@ template <typename B> B* xincref(B* b) {
// } // }
// //
// since this version does not need the try-catch block when called from a CXX-style function // since this version does not need the try-catch block when called from a CXX-style function
template <ExceptionStyle S, typename Functor> Box* callCXXFromStyle(Functor f) { template <ExceptionStyle S, typename Functor, typename... Args> Box* callCXXFromStyle(Functor f, Args&&... args) {
if (S == CAPI) { if (S == CAPI) {
try { try {
return f(); return f(std::forward<Args>(args)...);
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return NULL; return NULL;
} }
} else } else
return f(); return f(std::forward<Args>(args)...);
}
template <ExceptionStyle S, typename Func, typename... Args> Box* callCAPIFromStyle(Func f, Args&&... args) {
Box* rtn = f(std::forward<Args>(args)...);
if (S == CXX && !rtn)
throwCAPIException();
return rtn;
} }
// Uncoment this to disable the int freelist, which can make debugging eassier. // Uncoment this to disable the int freelist, which can make debugging eassier.
......
...@@ -227,7 +227,7 @@ extern "C" void dumpEx(void* p, int levels) { ...@@ -227,7 +227,7 @@ extern "C" void dumpEx(void* p, int levels) {
} }
if (PyLong_Check(b)) { if (PyLong_Check(b)) {
PyObject* str = longRepr(static_cast<BoxedLong*>(b)); PyObject* str = long_cls->tp_repr(b);
AUTO_DECREF(str); AUTO_DECREF(str);
printf("Long value: %s\n", static_cast<BoxedString*>(str)->c_str()); printf("Long value: %s\n", static_cast<BoxedString*>(str)->c_str());
} }
......
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