Commit a419290b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #974 from undingen/str_cleanup

Cleanup the __str__, __repr__ support and let they handle unicode strings
parents a9118c1d dbd46f86
......@@ -388,7 +388,7 @@ float_repr(PyFloatObject *v)
return float_str_or_repr(v, 0, 'r');
}
static PyObject *
PyObject *
float_str(PyFloatObject *v)
{
return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g');
......
......@@ -632,22 +632,33 @@ extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept {
static PyObject* slot_tp_repr(PyObject* self) noexcept {
STAT_TIMER(t0, "us_timer_slot_tprepr", SLOT_AVOIDABILITY(self));
try {
return repr(self);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
PyObject* func, *res;
static PyObject* repr_str;
func = lookup_method(self, "__repr__", &repr_str);
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 {
STAT_TIMER(t0, "us_timer_slot_tpstr", SLOT_AVOIDABILITY(self));
try {
return str(self);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
PyObject* func, *res;
static PyObject* str_str;
func = lookup_method(self, "__str__", &str_str);
if (func != NULL) {
res = PyEval_CallObject(func, NULL);
Py_DECREF(func);
return res;
} else {
PyErr_Clear();
return slot_tp_repr(self);
}
}
......
......@@ -1074,9 +1074,9 @@ AST_Module* parse_file(const char* fn, FutureFlags inherited_flags) {
const char* getMagic() {
if (ENABLE_PYPA_PARSER)
return "a\ncN";
return "a\ncO";
else
return "a\ncn";
return "a\nco";
}
#define MAGIC_STRING_LENGTH 4
......
......@@ -1169,6 +1169,7 @@ static AST_Module* parse_with_reader(std::unique_ptr<pypa::Reader> reader, Futur
pypa::AstModulePtr module;
pypa::ParserOptions options;
options.perform_inline_optimizations = true;
options.printerrors = false;
options.python3allowed = false;
options.python3only = false;
......
......@@ -221,8 +221,6 @@ void initGlobalFuncs(GlobalState& g) {
GET(importFrom);
GET(importStar);
GET(repr);
GET(str);
GET(strOrUnicode);
GET(exceptionMatches);
GET(yield);
GET(getiterHelper);
......
......@@ -37,8 +37,7 @@ struct GlobalFuncs {
*createGenerator, *createSet;
llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare,
*augbinop, *unboxedLen, *getitem, *getitem_capi, *getclsattr, *getGlobal, *setitem, *unaryop, *import,
*importFrom, *importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext,
*setGlobal;
*importFrom, *importStar, *repr, *exceptionMatches, *yield, *getiterHelper, *hasnext, *setGlobal;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi,
......
......@@ -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__format__(PyObject* v) 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;
namespace pyston {
......@@ -1704,6 +1705,7 @@ void setupFloat() {
floatFormatInit();
float_cls->tp_str = float_str;
float_cls->tp_as_number->nb_power = float_pow;
}
......
......@@ -115,7 +115,6 @@ void force() {
FORCE(printExprHelper);
FORCE(printHelper);
FORCE(strOrUnicode);
FORCE(printFloat);
FORCE(listAppendInternal);
FORCE(getSysStdout);
......
......@@ -2661,32 +2661,11 @@ extern "C" BoxedString* str(Box* obj) {
static StatCounter slowpath_str("slowpath_str");
slowpath_str.log();
static BoxedString* str_box = internStringImmortal(str_str.c_str());
if (obj->cls != str_cls) {
// TODO could do an IC optimization here (once we do rewrites here at all):
// if __str__ is objectStr, just guard on that and call repr directly.
obj = callattrInternal<CXX, NOT_REWRITABLE>(obj, str_box, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL,
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);
Box* rtn = PyObject_Str(obj);
if (!rtn)
throwCAPIException();
assert(rtn->cls == str_cls); // PyObject_Str always returns a str
return (BoxedString*)rtn;
}
extern "C" BoxedString* repr(Box* obj) {
......@@ -2694,40 +2673,11 @@ extern "C" BoxedString* repr(Box* obj) {
static StatCounter slowpath_repr("slowpath_repr");
slowpath_repr.log();
static BoxedString* repr_box = internStringImmortal(repr_str.c_str());
obj = callattrInternal<CXX, NOT_REWRITABLE>(obj, repr_box, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL,
NULL);
if (isSubclass(obj->cls, unicode_cls)) {
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;
}
Box* rtn = PyObject_Repr(obj);
if (!rtn)
throwCAPIException();
assert(rtn->cls == str_cls); // PyObject_Repr always returns a str
return (BoxedString*)rtn;
}
extern "C" bool exceptionMatches(Box* obj, Box* cls) {
......
......@@ -73,9 +73,6 @@ extern "C" Box* callattrCapi(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box*
const std::vector<BoxedString*>*) noexcept;
extern "C" BoxedString* str(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" BoxedInt* hash(Box* obj);
extern "C" int64_t hashUnboxed(Box* obj);
......
......@@ -1278,8 +1278,9 @@ extern "C" Box* strLen(BoxedString* self) {
return boxInt(self->size());
}
extern "C" Box* strStr(BoxedString* self) {
assert(PyString_Check(self));
extern "C" Box* str_str(Box* _self) noexcept {
assert(PyString_Check(_self));
BoxedString* self = (BoxedString*)_self;
if (self->cls == str_cls)
return self;
......@@ -2854,7 +2855,7 @@ void setupStr() {
ParamNames::empty(), CAPI)));
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("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, UNKNOWN, 1)));
str_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)strNonzero, BOXED_BOOL, 1)));
......@@ -2935,6 +2936,7 @@ void setupStr() {
str_cls->freeze();
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_hash = (hashfunc)str_hash;
str_cls->tp_as_sequence->sq_length = str_length;
......
......@@ -1613,14 +1613,10 @@ extern "C" Box* boxUnboundInstanceMethod(Box* func, Box* type) {
return new BoxedInstanceMethod(NULL, func, type);
}
extern "C" BoxedString* noneRepr(Box* v) {
extern "C" Box* none_repr(Box* v) noexcept {
return boxString("None");
}
extern "C" Box* noneHash(Box* v) {
return boxInt(819239); // chosen randomly
}
extern "C" Box* noneNonzero(Box* v) {
return False;
}
......@@ -3867,11 +3863,12 @@ void setupRuntime() {
type_cls->tpp_call.capi_val = &typeTppCall<CAPI>;
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("__doc__", None);
none_cls->tp_hash = (hashfunc)_Py_HashPointer;
none_cls->freeze();
none_cls->tp_repr = none_repr;
module_cls->giveAttr("__init__",
new BoxedFunction(boxRTFunction((void*)moduleInit, UNKNOWN, 3, false, false), { NULL }));
......
......@@ -166,3 +166,12 @@ class C(object):
print type(unicode(C()))
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