diff --git a/src/builtins.h b/src/builtins.h index eb55dd81..daefa8d4 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -27,19 +27,19 @@ def __str4split(self, sep): return res str.split = __str4split -def __list4__str__(self): +def __list4__repr__(self): a = [] for i in self: - a.append(str(i)) + a.append(repr(i)) return '[' + ', '.join(a) + ']' -list.__str__ = __list4__str__ +list.__repr__ = __list4__repr__ -def __tuple4__str__(self): +def __tuple4__repr__(self): a = [] for i in self: - a.append(str(i)) + a.append(repr(i)) return '(' + ', '.join(a) + ')' -tuple.__str__ = __tuple4__str__ +tuple.__repr__ = __tuple4__repr__ def __list4extend(self, other): for i in other: @@ -146,10 +146,10 @@ class dict: ret.append(kv) return ret - def __str__(self): + def __repr__(self): ret = '{' for kv in self.items(): - ret += str(kv[0]) + ': ' + str(kv[1]) + ', ' + ret += repr(kv[0]) + ': ' + repr(kv[1]) + ', ' if ret[-2:] == ', ': ret = ret[:-2] return ret + '}' diff --git a/src/pocketpy.h b/src/pocketpy.h index f1571377..4c5c6319 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -49,6 +49,10 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->None; }); + _vm->bindBuiltinFunc("repr", [](VM* vm, PyVarList args) { + return vm->asRepr(args.at(0)); + }); + _vm->bindBuiltinFunc("hash", [](VM* vm, PyVarList args) { return vm->PyInt(vm->hash(args.at(0))); }); @@ -83,7 +87,7 @@ void __initializeBuiltinFunctions(VM* _vm) { return obj; }); - _vm->bindMethod("object", "__str__", [](VM* vm, PyVarList args) { + _vm->bindMethod("object", "__repr__", [](VM* vm, PyVarList args) { PyVar _self = args[0]; _Str s = "<" + _self->getTypeName() + " object at " + std::to_string((uintptr_t)_self.get()) + ">"; return vm->PyStr(s); @@ -116,7 +120,7 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyIter(iter); }); - _vm->bindMethod("NoneType", "__str__", [](VM* vm, PyVarList args) { + _vm->bindMethod("NoneType", "__repr__", [](VM* vm, PyVarList args) { return vm->PyStr("None"); }); @@ -155,7 +159,7 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyInt(-1 * vm->PyInt_AS_C(args[0])); }); - _vm->bindMethod("int", "__str__", [](VM* vm, PyVarList args) { + _vm->bindMethod("int", "__repr__", [](VM* vm, PyVarList args) { return vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))); }); @@ -164,7 +168,7 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyFloat(-1.0f * vm->PyFloat_AS_C(args[0])); }); - _vm->bindMethod("float", "__str__", [](VM* vm, PyVarList args) { + _vm->bindMethod("float", "__repr__", [](VM* vm, PyVarList args) { return vm->PyStr(std::to_string(vm->PyFloat_AS_C(args[0]))); }); @@ -198,6 +202,12 @@ void __initializeBuiltinFunctions(VM* _vm) { return args[0]; // str is immutable }); + _vm->bindMethod("str", "__repr__", [](VM* vm, PyVarList args) { + const _Str& _self = vm->PyStr_AS_C(args[0]); + // we just do a simple repr here, no escaping + return vm->PyStr("'" + _self.str() + "'"); + }); + _vm->bindMethod("str", "__eq__", [](VM* vm, PyVarList args) { if(args.at(0)->isType(vm->_tp_str) && args.at(1)->isType(vm->_tp_str)) return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1])); @@ -385,7 +395,7 @@ void __initializeBuiltinFunctions(VM* _vm) { }); /************ PyBool ************/ - _vm->bindMethod("bool", "__str__", [](VM* vm, PyVarList args) { + _vm->bindMethod("bool", "__repr__", [](VM* vm, PyVarList args) { bool val = vm->PyBool_AS_C(args[0]); return vm->PyStr(val ? "True" : "False"); }); diff --git a/src/str.h b/src/str.h index 8a93ac1b..cea4e4e9 100644 --- a/src/str.h +++ b/src/str.h @@ -138,6 +138,7 @@ const _Str& __base__ = _Str("__base__"); const _Str& __new__ = _Str("__new__"); const _Str& __iter__ = _Str("__iter__"); const _Str& __str__ = _Str("__str__"); +const _Str& __repr__ = _Str("__repr__"); const _Str& __neg__ = _Str("__neg__"); const _Str& __getitem__ = _Str("__getitem__"); const _Str& __setitem__ = _Str("__setitem__"); diff --git a/src/vm.h b/src/vm.h index d0192af0..19d6d62c 100644 --- a/src/vm.h +++ b/src/vm.h @@ -62,8 +62,14 @@ public: } PyVar asStr(const PyVar& obj){ + PyVarOrNull str_fn = getAttr(obj, __str__, false); + if(str_fn != nullptr) return call(str_fn, {}); + return asRepr(obj); + } + + PyVar asRepr(const PyVar& obj){ if(obj->isType(_tp_type)) return PyStr("getName() + "'>"); - return call(obj, __str__, {}); + return call(obj, __repr__, {}); } PyVar asBool(const PyVar& obj){ @@ -235,7 +241,7 @@ public: { const PyVar& expr = frame->topValue(this); if(expr == None) break; - printFn(PyStr_AS_C(asStr(expr))); + printFn(PyStr_AS_C(asRepr(expr))); printFn("\n"); } break; case OP_POP_TOP: frame->popValue(this); break; @@ -288,7 +294,7 @@ public: } break; case OP_RAISE_ERROR: { - _Str msg = PyStr_AS_C(asStr(frame->popValue(this))); + _Str msg = PyStr_AS_C(asRepr(frame->popValue(this))); _Str type = PyStr_AS_C(frame->popValue(this)); _error(type, msg); } break;