Jelajahi Sumber

add __json__

blueloveTH 3 tahun lalu
induk
melakukan
d352aca6af
4 mengubah file dengan 45 tambahan dan 8 penghapusan
  1. 10 0
      src/builtins.h
  2. 30 8
      src/pocketpy.h
  3. 1 0
      src/str.h
  4. 4 0
      src/vm.h

+ 10 - 0
src/builtins.h

@@ -25,6 +25,8 @@ del __str4split
 
 
 list.__repr__ = lambda self: '[' + ', '.join([repr(i) for i in self]) + ']'
 list.__repr__ = lambda self: '[' + ', '.join([repr(i) for i in self]) + ']'
 tuple.__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):
 def __list4extend(self, other):
     for i in other:
     for i in other:
@@ -136,4 +138,12 @@ class dict:
         a = [repr(k)+': '+repr(v) for k,v in self.items()]
         a = [repr(k)+': '+repr(v) for k,v in self.items()]
         return '{'+ ', '.join(a) + '}'
         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) + '}'
+
 )";
 )";

+ 30 - 8
src/pocketpy.h

@@ -144,6 +144,10 @@ void __initializeBuiltinFunctions(VM* _vm) {
         return vm->PyStr("None");
         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) {
     _vm->bindMethodMulti({"int", "float"}, "__truediv__", [](VM* vm, PyVarList args) {
         if(!vm->isIntOrFloat(args[0], args[1]))
         if(!vm->isIntOrFloat(args[0], args[1]))
             vm->typeError("unsupported operand type(s) for " "/" );
             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])));
         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) \
 #define __INT_BITWISE_OP(name,op) \
     _vm->bindMethod("int", #name, [](VM* vm, PyVarList args) { \
     _vm->bindMethod("int", #name, [](VM* vm, PyVarList args) { \
         if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int)) \
         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);
         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 ************/
     /************ PyString ************/
     _vm->bindMethod("str", "__new__", [](VM* vm, PyVarList args) {
     _vm->bindMethod("str", "__new__", [](VM* vm, PyVarList args) {
         vm->__checkArgSize(args, 1);
         vm->__checkArgSize(args, 1);
@@ -293,6 +305,12 @@ void __initializeBuiltinFunctions(VM* _vm) {
         return vm->PyStr("'" + _self.str() + "'");
         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) {
     _vm->bindMethod("str", "__eq__", [](VM* vm, PyVarList args) {
         if(args[0]->isType(vm->_tp_str) && args[1]->isType(vm->_tp_str))
         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]));
             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");
         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) {
     _vm->bindMethod("bool", "__eq__", [](VM* vm, PyVarList args) {
         return vm->PyBool(args[0] == args[1]);
         return vm->PyBool(args[0] == args[1]);
     });
     });
@@ -552,16 +575,16 @@ extern "C" {
     __EXPORT
     __EXPORT
     struct PyObjectDump: public PkExportedResource{
     struct PyObjectDump: public PkExportedResource{
         const char* type;   // "int", "str", "float" ...
         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(){
         ~PyObjectDump(){
             delete[] type;
             delete[] type;
-            delete[] string;
-            delete[] repr;
+            delete[] json;
         }
         }
     };
     };
 
 
@@ -601,8 +624,7 @@ extern "C" {
         if(ret == nullptr) return nullptr;
         if(ret == nullptr) return nullptr;
         return new PyObjectDump(
         return new PyObjectDump(
             ret->getTypeName().c_str(),
             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()
         );
         );
     }
     }
 
 

+ 1 - 0
src/str.h

@@ -159,6 +159,7 @@ const _Str& __setitem__ = _Str("__setitem__");
 const _Str& __delitem__ = _Str("__delitem__");
 const _Str& __delitem__ = _Str("__delitem__");
 const _Str& __contains__ = _Str("__contains__");
 const _Str& __contains__ = _Str("__contains__");
 const _Str& __init__ = _Str("__init__");
 const _Str& __init__ = _Str("__init__");
+const _Str& __json__ = _Str("__json__");
 
 
 const _Str CMP_SPECIAL_METHODS[] = {
 const _Str CMP_SPECIAL_METHODS[] = {
     "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"
     "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"

+ 4 - 0
src/vm.h

@@ -339,6 +339,10 @@ public:
         return call(obj, __repr__, {});
         return call(obj, __repr__, {});
     }
     }
 
 
+    PyVar asJson(const PyVar& obj){
+        return call(obj, __json__, {});
+    }
+
     PyVar asBool(const PyVar& obj){
     PyVar asBool(const PyVar& obj){
         if(obj == None) return False;
         if(obj == None) return False;
         PyVar tp = obj->attribs[__class__];
         PyVar tp = obj->attribs[__class__];