Commit 1f220725 authored by Marius Wachtler's avatar Marius Wachtler

Cleanup the __str__, __repr__ support and let they handle unicode strings

parent 3ca2326d
...@@ -388,7 +388,7 @@ float_repr(PyFloatObject *v) ...@@ -388,7 +388,7 @@ float_repr(PyFloatObject *v)
return float_str_or_repr(v, 0, 'r'); return float_str_or_repr(v, 0, 'r');
} }
static PyObject * PyObject *
float_str(PyFloatObject *v) float_str(PyFloatObject *v)
{ {
return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g'); return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g');
......
...@@ -632,22 +632,33 @@ extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept { ...@@ -632,22 +632,33 @@ extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept {
static PyObject* slot_tp_repr(PyObject* self) noexcept { static PyObject* slot_tp_repr(PyObject* self) noexcept {
STAT_TIMER(t0, "us_timer_slot_tprepr", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_tprepr", SLOT_AVOIDABILITY(self));
try { PyObject* func, *res;
return repr(self); static PyObject* repr_str;
} catch (ExcInfo e) {
setCAPIException(e); func = lookup_method(self, "__repr__", &repr_str);
return NULL; if (func != NULL) {
res = PyEval_CallObject(func, NULL);
Py_DECREF(func);
return res;
} }
PyErr_Clear();
return PyString_FromFormat("<%s object at %p>", Py_TYPE(self)->tp_name, self);
} }
static PyObject* slot_tp_str(PyObject* self) noexcept { static PyObject* slot_tp_str(PyObject* self) noexcept {
STAT_TIMER(t0, "us_timer_slot_tpstr", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_tpstr", SLOT_AVOIDABILITY(self));
try { PyObject* func, *res;
return str(self); static PyObject* str_str;
} catch (ExcInfo e) {
setCAPIException(e); func = lookup_method(self, "__str__", &str_str);
return NULL; if (func != NULL) {
res = PyEval_CallObject(func, NULL);
Py_DECREF(func);
return res;
} else {
PyErr_Clear();
return slot_tp_repr(self);
} }
} }
......
...@@ -221,8 +221,6 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -221,8 +221,6 @@ void initGlobalFuncs(GlobalState& g) {
GET(importFrom); GET(importFrom);
GET(importStar); GET(importStar);
GET(repr); GET(repr);
GET(str);
GET(strOrUnicode);
GET(exceptionMatches); GET(exceptionMatches);
GET(yield); GET(yield);
GET(getiterHelper); GET(getiterHelper);
......
...@@ -37,8 +37,7 @@ struct GlobalFuncs { ...@@ -37,8 +37,7 @@ struct GlobalFuncs {
*createGenerator, *createSet; *createGenerator, *createSet;
llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare, llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare,
*augbinop, *unboxedLen, *getitem, *getitem_capi, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *augbinop, *unboxedLen, *getitem, *getitem_capi, *getclsattr, *getGlobal, *setitem, *unaryop, *import,
*importFrom, *importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext, *importFrom, *importStar, *repr, *exceptionMatches, *yield, *getiterHelper, *hasnext, *setGlobal;
*setGlobal;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi, llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi, *raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi,
......
...@@ -33,6 +33,7 @@ extern "C" PyObject* float_as_integer_ratio(PyObject* v, PyObject* unused) noexc ...@@ -33,6 +33,7 @@ extern "C" PyObject* float_as_integer_ratio(PyObject* v, PyObject* unused) noexc
extern "C" PyObject* float_is_integer(PyObject* v) noexcept; extern "C" PyObject* float_is_integer(PyObject* v) noexcept;
extern "C" PyObject* float__format__(PyObject* v) noexcept; extern "C" PyObject* float__format__(PyObject* v) noexcept;
extern "C" PyObject* float_pow(PyObject* v, PyObject* w, PyObject* z) noexcept; extern "C" PyObject* float_pow(PyObject* v, PyObject* w, PyObject* z) noexcept;
extern "C" PyObject* float_str(PyObject* v) noexcept;
extern "C" int float_pow_unboxed(double iv, double iw, double* res) noexcept; extern "C" int float_pow_unboxed(double iv, double iw, double* res) noexcept;
namespace pyston { namespace pyston {
...@@ -1704,6 +1705,7 @@ void setupFloat() { ...@@ -1704,6 +1705,7 @@ void setupFloat() {
floatFormatInit(); floatFormatInit();
float_cls->tp_str = float_str;
float_cls->tp_as_number->nb_power = float_pow; float_cls->tp_as_number->nb_power = float_pow;
} }
......
...@@ -115,7 +115,6 @@ void force() { ...@@ -115,7 +115,6 @@ void force() {
FORCE(printExprHelper); FORCE(printExprHelper);
FORCE(printHelper); FORCE(printHelper);
FORCE(strOrUnicode);
FORCE(printFloat); FORCE(printFloat);
FORCE(listAppendInternal); FORCE(listAppendInternal);
FORCE(getSysStdout); FORCE(getSysStdout);
......
...@@ -2661,32 +2661,11 @@ extern "C" BoxedString* str(Box* obj) { ...@@ -2661,32 +2661,11 @@ extern "C" BoxedString* str(Box* obj) {
static StatCounter slowpath_str("slowpath_str"); static StatCounter slowpath_str("slowpath_str");
slowpath_str.log(); slowpath_str.log();
static BoxedString* str_box = internStringImmortal(str_str.c_str()); Box* rtn = PyObject_Str(obj);
if (obj->cls != str_cls) { if (!rtn)
// TODO could do an IC optimization here (once we do rewrites here at all): throwCAPIException();
// if __str__ is objectStr, just guard on that and call repr directly. assert(rtn->cls == str_cls); // PyObject_Str always returns a str
obj = callattrInternal<CXX, NOT_REWRITABLE>(obj, str_box, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, return (BoxedString*)rtn;
NULL, NULL);
}
if (isSubclass(obj->cls, unicode_cls)) {
obj = PyUnicode_AsASCIIString(obj);
checkAndThrowCAPIException();
}
if (!PyString_Check(obj)) {
raiseExcHelper(TypeError, "__str__ returned non-string (type %s)", obj->cls->tp_name);
}
return static_cast<BoxedString*>(obj);
}
extern "C" Box* strOrUnicode(Box* obj) {
STAT_TIMER(t0, "us_timer_strOrUnicode", 10);
// Like str, but returns unicode objects unchanged.
if (obj->cls == unicode_cls) {
return obj;
}
return str(obj);
} }
extern "C" BoxedString* repr(Box* obj) { extern "C" BoxedString* repr(Box* obj) {
...@@ -2694,40 +2673,11 @@ extern "C" BoxedString* repr(Box* obj) { ...@@ -2694,40 +2673,11 @@ extern "C" BoxedString* repr(Box* obj) {
static StatCounter slowpath_repr("slowpath_repr"); static StatCounter slowpath_repr("slowpath_repr");
slowpath_repr.log(); slowpath_repr.log();
static BoxedString* repr_box = internStringImmortal(repr_str.c_str()); Box* rtn = PyObject_Repr(obj);
obj = callattrInternal<CXX, NOT_REWRITABLE>(obj, repr_box, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, if (!rtn)
NULL); throwCAPIException();
assert(rtn->cls == str_cls); // PyObject_Repr always returns a str
if (isSubclass(obj->cls, unicode_cls)) { return (BoxedString*)rtn;
obj = PyUnicode_AsASCIIString(obj);
checkAndThrowCAPIException();
}
if (!PyString_Check(obj)) {
raiseExcHelper(TypeError, "__repr__ returned non-string (type %s)", obj->cls->tp_name);
}
return static_cast<BoxedString*>(obj);
}
extern "C" BoxedString* reprOrNull(Box* obj) {
STAT_TIMER(t0, "us_timer_reprOrNull", 10);
try {
Box* r = repr(obj);
assert(r->cls == str_cls); // this should be checked by repr()
return static_cast<BoxedString*>(r);
} catch (ExcInfo e) {
return nullptr;
}
}
extern "C" BoxedString* strOrNull(Box* obj) {
STAT_TIMER(t0, "us_timer_strOrNull", 10);
try {
BoxedString* r = str(obj);
return static_cast<BoxedString*>(r);
} catch (ExcInfo e) {
return nullptr;
}
} }
extern "C" bool exceptionMatches(Box* obj, Box* cls) { extern "C" bool exceptionMatches(Box* obj, Box* cls) {
......
...@@ -73,9 +73,6 @@ extern "C" Box* callattrCapi(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box* ...@@ -73,9 +73,6 @@ extern "C" Box* callattrCapi(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box*
const std::vector<BoxedString*>*) noexcept; const std::vector<BoxedString*>*) noexcept;
extern "C" BoxedString* str(Box* obj); extern "C" BoxedString* str(Box* obj);
extern "C" BoxedString* repr(Box* obj); extern "C" BoxedString* repr(Box* obj);
extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception
extern "C" BoxedString* strOrNull(Box* obj); // similar to str, but returns NULL on exception
extern "C" Box* strOrUnicode(Box* obj);
extern "C" bool exceptionMatches(Box* obj, Box* cls); extern "C" bool exceptionMatches(Box* obj, Box* cls);
extern "C" BoxedInt* hash(Box* obj); extern "C" BoxedInt* hash(Box* obj);
extern "C" int64_t hashUnboxed(Box* obj); extern "C" int64_t hashUnboxed(Box* obj);
......
...@@ -1278,8 +1278,9 @@ extern "C" Box* strLen(BoxedString* self) { ...@@ -1278,8 +1278,9 @@ extern "C" Box* strLen(BoxedString* self) {
return boxInt(self->size()); return boxInt(self->size());
} }
extern "C" Box* strStr(BoxedString* self) { extern "C" Box* str_str(Box* _self) noexcept {
assert(PyString_Check(self)); assert(PyString_Check(_self));
BoxedString* self = (BoxedString*)_self;
if (self->cls == str_cls) if (self->cls == str_cls)
return self; return self;
...@@ -2854,7 +2855,7 @@ void setupStr() { ...@@ -2854,7 +2855,7 @@ void setupStr() {
ParamNames::empty(), CAPI))); ParamNames::empty(), CAPI)));
str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, BOXED_INT, 1))); str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, BOXED_INT, 1)));
str_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)strStr, STR, 1))); str_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)str_str, STR, 1)));
str_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)strRepr, STR, 1))); str_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)strRepr, STR, 1)));
str_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, UNKNOWN, 1))); str_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, UNKNOWN, 1)));
str_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)strNonzero, BOXED_BOOL, 1))); str_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)strNonzero, BOXED_BOOL, 1)));
...@@ -2935,6 +2936,7 @@ void setupStr() { ...@@ -2935,6 +2936,7 @@ void setupStr() {
str_cls->freeze(); str_cls->freeze();
str_cls->tp_repr = str_repr; str_cls->tp_repr = str_repr;
str_cls->tp_str = str_str;
str_cls->tp_iter = (decltype(str_cls->tp_iter))strIter; str_cls->tp_iter = (decltype(str_cls->tp_iter))strIter;
str_cls->tp_hash = (hashfunc)str_hash; str_cls->tp_hash = (hashfunc)str_hash;
str_cls->tp_as_sequence->sq_length = str_length; str_cls->tp_as_sequence->sq_length = str_length;
......
...@@ -1613,14 +1613,10 @@ extern "C" Box* boxUnboundInstanceMethod(Box* func, Box* type) { ...@@ -1613,14 +1613,10 @@ extern "C" Box* boxUnboundInstanceMethod(Box* func, Box* type) {
return new BoxedInstanceMethod(NULL, func, type); return new BoxedInstanceMethod(NULL, func, type);
} }
extern "C" BoxedString* noneRepr(Box* v) { extern "C" Box* none_repr(Box* v) noexcept {
return boxString("None"); return boxString("None");
} }
extern "C" Box* noneHash(Box* v) {
return boxInt(819239); // chosen randomly
}
extern "C" Box* noneNonzero(Box* v) { extern "C" Box* noneNonzero(Box* v) {
return False; return False;
} }
...@@ -3867,11 +3863,12 @@ void setupRuntime() { ...@@ -3867,11 +3863,12 @@ void setupRuntime() {
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>;
none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1))); none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)none_repr, STR, 1)));
none_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)noneNonzero, BOXED_BOOL, 1))); none_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)noneNonzero, BOXED_BOOL, 1)));
none_cls->giveAttr("__doc__", None); none_cls->giveAttr("__doc__", None);
none_cls->tp_hash = (hashfunc)_Py_HashPointer; none_cls->tp_hash = (hashfunc)_Py_HashPointer;
none_cls->freeze(); none_cls->freeze();
none_cls->tp_repr = none_repr;
module_cls->giveAttr("__init__", module_cls->giveAttr("__init__",
new BoxedFunction(boxRTFunction((void*)moduleInit, UNKNOWN, 3, false, false), { NULL })); new BoxedFunction(boxRTFunction((void*)moduleInit, UNKNOWN, 3, false, false), { NULL }));
......
...@@ -166,3 +166,12 @@ class C(object): ...@@ -166,3 +166,12 @@ class C(object):
print type(unicode(C())) print type(unicode(C()))
print unicode("test", encoding="UTF-8") print unicode("test", encoding="UTF-8")
class CStr(object):
def __str__(self):
return u"\u20ac"
class CRepr(object):
def __repr__(self):
return u"\u20ac"
print "%s %s" % (CStr(), CRepr())
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