diff --git a/src/builtins.h b/src/builtins.h index 46a14781..4a2cc89a 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -25,6 +25,8 @@ del __str4split list.__repr__ = lambda self: '[' + ', '.join([repr(i) for i in self]) + ']' tuple.__repr__ = lambda self: '(' + ', '.join([repr(i) for i in self]) + ')' +list.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']' +tuple.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']' def __list4extend(self, other): for i in other: @@ -136,4 +138,12 @@ class dict: a = [repr(k)+': '+repr(v) for k,v in self.items()] return '{'+ ', '.join(a) + '}' + def __json__(self): + a = [] + for k,v in self.items(): + if type(k) is not str: + raise TypeError('json keys must be strings, got ' + repr(k) ) + a.append(k.__json__()+': '+v.__json__()) + return '{'+ ', '.join(a) + '}' + )"; \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index fe3e0940..e4736b8d 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -144,6 +144,10 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyStr("None"); }); + _vm->bindMethod("NoneType", "__json__", [](VM* vm, PyVarList args) { + return vm->PyStr("null"); + }); + _vm->bindMethodMulti({"int", "float"}, "__truediv__", [](VM* vm, PyVarList args) { if(!vm->isIntOrFloat(args[0], args[1])) vm->typeError("unsupported operand type(s) for " "/" ); @@ -200,6 +204,10 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))); }); + _vm->bindMethod("int", "__json__", [](VM* vm, PyVarList args) { + return vm->PyStr(std::to_string((int)vm->PyInt_AS_C(args[0]))); + }); + #define __INT_BITWISE_OP(name,op) \ _vm->bindMethod("int", #name, [](VM* vm, PyVarList args) { \ if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int)) \ @@ -253,6 +261,10 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyStr(s); }); + _vm->bindMethod("float", "__json__", [](VM* vm, PyVarList args) { + return vm->PyStr(std::to_string((float)vm->PyFloat_AS_C(args[0]))); + }); + /************ PyString ************/ _vm->bindMethod("str", "__new__", [](VM* vm, PyVarList args) { vm->__checkArgSize(args, 1); @@ -293,6 +305,12 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyStr("'" + _self.str() + "'"); }); + _vm->bindMethod("str", "__json__", [](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[0]->isType(vm->_tp_str) && args[1]->isType(vm->_tp_str)) return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1])); @@ -502,6 +520,11 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyStr(val ? "True" : "False"); }); + _vm->bindMethod("bool", "__json__", [](VM* vm, PyVarList args) { + bool val = vm->PyBool_AS_C(args[0]); + return vm->PyStr(val ? "true" : "false"); + }); + _vm->bindMethod("bool", "__eq__", [](VM* vm, PyVarList args) { return vm->PyBool(args[0] == args[1]); }); @@ -552,16 +575,16 @@ extern "C" { __EXPORT struct PyObjectDump: public PkExportedResource{ const char* type; // "int", "str", "float" ... - const char* string; // __str__ representation - const char* repr; // __repr__ representation + const char* json; // json representation - PyObjectDump(const char* _type, const char* _string, const char* _repr): - type(strdup(_type)), string(strdup(_string)), repr(strdup(_repr)){} + PyObjectDump(const char* _type, const char* _json){ + type = strdup(_type); + json = strdup(_json); + } ~PyObjectDump(){ delete[] type; - delete[] string; - delete[] repr; + delete[] json; } }; @@ -601,8 +624,7 @@ extern "C" { if(ret == nullptr) return nullptr; return new PyObjectDump( ret->getTypeName().c_str(), - vm->PyStr_AS_C(vm->asStr(ret)).c_str(), - vm->PyStr_AS_C(vm->asRepr(ret)).c_str() + vm->PyStr_AS_C(vm->asJson(ret)).c_str() ); } diff --git a/src/str.h b/src/str.h index 94322c21..ced560b7 100644 --- a/src/str.h +++ b/src/str.h @@ -159,6 +159,7 @@ const _Str& __setitem__ = _Str("__setitem__"); const _Str& __delitem__ = _Str("__delitem__"); const _Str& __contains__ = _Str("__contains__"); const _Str& __init__ = _Str("__init__"); +const _Str& __json__ = _Str("__json__"); const _Str CMP_SPECIAL_METHODS[] = { "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__" diff --git a/src/vm.h b/src/vm.h index 4208e53b..12876569 100644 --- a/src/vm.h +++ b/src/vm.h @@ -339,6 +339,10 @@ public: return call(obj, __repr__, {}); } + PyVar asJson(const PyVar& obj){ + return call(obj, __json__, {}); + } + PyVar asBool(const PyVar& obj){ if(obj == None) return False; PyVar tp = obj->attribs[__class__];