Browse Source

fix some errors

blueloveTH 3 years ago
parent
commit
9b9e1b9fd0
6 changed files with 63 additions and 67 deletions
  1. 0 1
      src/__stl__.h
  2. 26 4
      src/builtins.h
  3. 2 1
      src/compiler.h
  4. 6 2
      src/main.cpp
  5. 13 22
      src/pocketpy.h
  6. 16 37
      src/vm.h

+ 0 - 1
src/__stl__.h

@@ -17,7 +17,6 @@
 #include <queue>
 #include <iomanip>
 #include <map>
-#include <optional>
 
 #include <thread>
 #include <atomic>

+ 26 - 4
src/builtins.h

@@ -229,6 +229,28 @@ def sorted(iterable, key=None, reverse=False):
                 b[i], b[j] = b[j], b[i]
     return b
 
+import json as _json
+
+def jsonrpc(method, params, raw=False):
+  assert type(method) is str
+  assert type(params) is list
+  data = {
+    'jsonrpc': '2.0',
+    'method': method,
+    'params': params,
+  }
+  ret = __string_channel_call(_json.dumps(data))
+  ret = _json.loads(ret)
+  if raw:
+    return ret
+  assert type(ret) is dict
+  if 'result' in ret:
+    return ret['result']
+  raise JsonRpcError(ret['error']['message'])
+
+def input(prompt=None):
+  return jsonrpc('input', [prompt])
+  
 class FileIO:
   def __init__(self, path, mode):
     assert type(path) is str
@@ -236,19 +258,19 @@ class FileIO:
     assert mode in ['r', 'w']
     self.path = path
     self.mode = mode
-    self.fp = jsonrpc({"method": "fopen", "params": [path, mode]})
+    self.fp = jsonrpc('fopen', [path, mode])
 
   def read(self):
     assert self.mode == 'r'
-    return jsonrpc({"method": "fread", "params": [self.fp]})
+    return jsonrpc('fread', [self.fp])
 
   def write(self, s):
     assert self.mode == 'w'
     assert type(s) is str
-    jsonrpc({"method": "fwrite", "params": [self.fp, s]})
+    jsonrpc('fwrite', [self.fp, s])
 
   def close(self):
-    jsonrpc({"method": "fclose", "params": [self.fp]})
+    jsonrpc('fclose', [self.fp])
 
   def __enter__(self):
     pass

+ 2 - 1
src/compiler.h

@@ -1020,8 +1020,9 @@ __LISTCOMP:
     }
 };
 
-_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE) {
+_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) {
     Compiler compiler(vm, source, filename, mode);
+    if(!noThrow) return compiler.__fillCode();
     try{
         return compiler.__fillCode();
     }catch(std::exception& e){

+ 6 - 2
src/main.cpp

@@ -43,11 +43,15 @@ void _tvm_dispatch(ThreadedVM* vm){
     while(pkpy_tvm_get_state(vm) != THREAD_FINISHED){
         if(pkpy_tvm_get_state(vm) == THREAD_SUSPENDED){
             char* obj = pkpy_tvm_read_jsonrpc_request(vm);
-            bool is_input_call = INPUT_JSONRPC_STR == std::string(obj);
+            bool is_input_call = std::string_view(obj).find("\"input\"") != std::string::npos;
             if(is_input_call){
                 std::string line;
                 std::getline(std::cin, line);
-                pkpy_tvm_resume(vm, line.c_str());
+                _StrStream ss;
+                ss << '{';
+                ss << "\"result\": " << _Str(line).__escape(false);
+                ss << '}';
+                pkpy_tvm_jsonrpc_response(vm, ss.str().c_str());
             }else{
                 std::cout << "unknown jsonrpc call" << std::endl;
                 std::cout << obj << std::endl;

+ 13 - 22
src/pocketpy.h

@@ -58,8 +58,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
     _vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
         vm->__checkArgSize(args, 1);
         const _Str& expr = vm->PyStr_AS_C(args[0]);
-        _Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE);
-        if(code == nullptr) return vm->None;
+        _Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE, false);
         return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals);
     });
 
@@ -639,8 +638,7 @@ void __addModuleJson(VM* vm){
     vm->bindFunc(mod, "loads", [](VM* vm, const pkpy::ArgList& args) {
         vm->__checkArgSize(args, 1);
         const _Str& expr = vm->PyStr_AS_C(args[0]);
-        _Code code = compile(vm, expr.c_str(), "<json>", JSON_MODE);
-        if(code == nullptr) return vm->None;
+        _Code code = compile(vm, expr.c_str(), "<json>", JSON_MODE, false);
         return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals);
     });
 
@@ -650,14 +648,14 @@ void __addModuleJson(VM* vm){
     });
 }
 
-class _PkExported;
-static std::vector<_PkExported*> _pkLookupTable;
 class _PkExported{
 public:
     virtual ~_PkExported() = default;
     virtual void* get() = 0;
 };
 
+static std::vector<_PkExported*> _pkLookupTable;
+
 template<typename T>
 class PkExported : public _PkExported{
     T* _ptr;
@@ -763,13 +761,13 @@ extern "C" {
 
     void __vm_init(VM* vm){
         __initializeBuiltinFunctions(vm);
-        _Code code = compile(vm, __BUILTINS_CODE, "<builtins>");
-        if(code == nullptr) exit(1);
-        vm->_exec(code, vm->builtins, {});
-
         __addModuleSys(vm);
         __addModuleTime(vm);
         __addModuleJson(vm);
+
+        _Code code = compile(vm, __BUILTINS_CODE, "<builtins>");
+        if(code == nullptr) exit(1);
+        vm->_exec(code, vm->builtins, {});
         pkpy_vm_add_module(vm, "random", __RANDOM_CODE);
     }
 
@@ -830,22 +828,15 @@ extern "C" {
 
     __EXPORT
     /// Read the current JSONRPC request from shared string buffer.
-    /// 
-    /// Return a `PyObjectDump*` representing the string.
-    /// You need to call `pkpy_delete` to free the returned `PyObjectDump*` later.
-    /// If the buffer is empty, return `nullptr`.
     char* pkpy_tvm_read_jsonrpc_request(ThreadedVM* vm){
-        std::optional<_Str> s = vm->readSharedStr();
-        if(!s.has_value()) return nullptr;
-        return strdup(s.value().c_str());
+        _Str s = vm->readSharedStr();
+        return strdup(s.c_str());
     }
 
     __EXPORT
-    /// Resume a suspended threaded virtual machine
-    /// and put the given string into the shared string buffer.
-    /// It is usually used for JSONRPC.
-    void pkpy_tvm_resume(ThreadedVM* vm, const char* value){
-        vm->resume(value);
+    /// Write a JSONRPC response to shared string buffer.
+    void pkpy_tvm_jsonrpc_response(ThreadedVM* vm, const char* value){
+        vm->jsonrpcResponse(value);
     }
 
     __EXPORT

+ 16 - 37
src/vm.h

@@ -40,7 +40,8 @@ protected:
     PyVar runFrame(Frame* frame){
         while(!frame->isCodeEnd()){
             const ByteCode& byte = frame->readCode();
-            //printf("%s (%d) stack_size: %d\n", OP_NAMES[byte.op], byte.arg, frame->stackSize());
+            //printf("[%d] %s (%d)\n", frame->stackSize(), OP_NAMES[byte.op], byte.arg);
+            //printf("%s\n", frame->code->src->getLine(byte.line).c_str());
 
             _checkStopFlag();
 
@@ -466,8 +467,6 @@ public:
                 obj = call(it->second, args);
             }else{
                 obj = newObject(_callable, (_Int)-1);
-            }
-            if(obj->isType(_callable)){
                 PyVarOrNull init_fn = getAttr(obj, __init__, false);
                 if (init_fn != nullptr) call(init_fn, args);
             }
@@ -1082,21 +1081,11 @@ enum ThreadState {
     THREAD_FINISHED
 };
 
-const _Str INPUT_JSONRPC_STR = "{\"method\": \"input\", \"params\": []}";
-
 class ThreadedVM : public VM {
     std::thread* _thread = nullptr;
     std::atomic<ThreadState> _state = THREAD_READY;
-    std::optional<_Str> _sharedStr = {};
+    _Str _sharedStr = ""_c;
     
-    PyVar jsonRpc(const _Str& _json){
-        _sharedStr = _json;
-        suspend();
-        std::optional<_Str> ret = readSharedStr();
-        if(ret.has_value()) return PyStr(ret.value());
-        return None;
-    }
-
     void __deleteThread(){
         if(_thread != nullptr){
             if(_state == THREAD_RUNNING || _state == THREAD_SUSPENDED){
@@ -1109,20 +1098,14 @@ class ThreadedVM : public VM {
     }
 public:
     ThreadedVM(bool use_stdio) : VM(use_stdio) {
-        bindBuiltinFunc("jsonrpc", [](VM* vm, const pkpy::ArgList& args){
-            ThreadedVM *tvm = dynamic_cast<ThreadedVM*>(vm);
-            if(tvm == nullptr) UNREACHABLE();
-            tvm->__checkArgSize(args, 1);
-            tvm->__checkType(args[0], vm->builtins->attribs["dict"_c]);
-            _Str _json = tvm->PyStr_AS_C(tvm->asJson(args[0]));
-            return tvm->jsonRpc(_json);
-        });
-
-        bindBuiltinFunc("input", [](VM* vm, const pkpy::ArgList& args) {
-            ThreadedVM *tvm = dynamic_cast<ThreadedVM*>(vm);
-            if(tvm == nullptr) UNREACHABLE();
-            tvm->__checkArgSize(args, 0);
-            return tvm->jsonRpc(INPUT_JSONRPC_STR);
+        bindBuiltinFunc("__string_channel_call", [](VM* vm, const pkpy::ArgList& args){
+            vm->__checkArgSize(args, 1);
+            _Str data = vm->PyStr_AS_C(args[0]);
+
+            ThreadedVM* tvm = (ThreadedVM*)vm;
+            tvm->_sharedStr = data;
+            tvm->suspend();
+            return tvm->PyStr(tvm->readSharedStr());
         });
     }
 
@@ -1136,9 +1119,9 @@ public:
         }
     }
 
-    std::optional<_Str> readSharedStr(){
-        std::optional<_Str> copy = _sharedStr;
-        _sharedStr = {};
+    _Str readSharedStr(){
+        _Str copy = _sharedStr;
+        _sharedStr = ""_c;
         return copy;
     }
 
@@ -1148,14 +1131,10 @@ public:
         return _state;
     }
 
-    void resume(const char* value=nullptr){
+    void jsonrpcResponse(const char* value){
         if(_state != THREAD_SUSPENDED) UNREACHABLE();
         _state = THREAD_RUNNING;
-        if(value == nullptr){
-            _sharedStr = {};
-        }else{
-            _sharedStr = _Str(value);
-        }
+        _sharedStr = _Str(value);
     }
 
     void execAsync(const _Code& code) override {