blueloveTH 3 年 前
コミット
29bdeca8eb
5 ファイル変更68 行追加44 行削除
  1. 16 14
      src/main.cpp
  2. 1 1
      src/obj.h
  3. 6 12
      src/pocketpy.h
  4. 45 17
      src/vm.h
  5. 0 0
      tests/hidden/tvm.py

+ 16 - 14
src/main.cpp

@@ -70,24 +70,26 @@ int main(int argc, char** argv){
         if(code == nullptr) return 1;
         //std::cout << code->toString() << std::endl;
 
-        Timer("Running time").run([=]{
-            vm->exec(code);
-        });
+        // Timer("Running time").run([=]{
+        //     vm->exec(code);
+        // });
 
         // for(auto& kv : _strIntern)
         //     std::cout << kv.first << ", ";
 
-        // Timer("Running time").run([=]{
-        //     vm->startExec(code);
-        //     while(pkpy_tvm_get_state(vm) != THREAD_FINISHED){
-        //         if(pkpy_tvm_get_state(vm) == THREAD_SUSPENDED){
-        //             std::string line;
-        //             std::getline(std::cin, line);
-        //             pkpy_tvm_write_stdin(vm, line.c_str());
-        //             pkpy_tvm_resume(vm);
-        //         }
-        //     }
-        // });
+        Timer("Running time").run([=]{
+            vm->startExec(code);
+            while(pkpy_tvm_get_state(vm) != THREAD_FINISHED){
+                if(pkpy_tvm_get_state(vm) == THREAD_SUSPENDED){
+                    PyObjectDump* obj = pkpy_tvm_read_json(vm);
+                    if(INPUT_JSONRPC_STR != obj->json) UNREACHABLE();
+                    pkpy_delete(obj);
+                    std::string line;
+                    std::getline(std::cin, line);
+                    pkpy_tvm_resume(vm, line.c_str());
+                }
+            }
+        });
         return 0;
     }
 

+ 1 - 1
src/obj.h

@@ -10,7 +10,7 @@ const _Int _Int_MAX_NEG = -9223372036854775807LL;
 const _Float _FLOAT_INF_POS = INFINITY;
 const _Float _FLOAT_INF_NEG = -INFINITY;
 
-#define PK_VERSION "0.3.1"
+#define PK_VERSION "0.3.2"
 
 class CodeObject;
 class BasePointer;

+ 6 - 12
src/pocketpy.h

@@ -48,14 +48,6 @@ void __initializeBuiltinFunctions(VM* _vm) {
         return vm->None;
     });
 
-    _vm->bindBuiltinFunc("input", [](VM* vm, const pkpy::ArgList& args) {
-        vm->__checkArgSize(args, 0);
-        ThreadedVM* tvm = dynamic_cast<ThreadedVM*>(vm);
-        if(tvm == nullptr) vm->typeError("input() can only be called in threaded mode");
-        tvm->suspend();
-        return vm->PyStr(tvm->readStdin());
-    });
-
     _vm->bindBuiltinFunc("super", [](VM* vm, const pkpy::ArgList& args) {
         vm->__checkArgSize(args, 0);
         auto it = vm->topFrame()->f_locals.find("self"_c);
@@ -776,12 +768,14 @@ extern "C" {
     }
 
     __EXPORT
-    void pkpy_tvm_write_stdin(ThreadedVM* vm, const char* line){
-        vm->_stdin = _Str(line);
+    PyObjectDump* pkpy_tvm_read_json(ThreadedVM* vm){
+        std::optional<_Str> s = vm->readSharedStr();
+        if(!s.has_value()) return nullptr;
+        return new PyObjectDump("str", s.value());
     }
 
     __EXPORT
-    void pkpy_tvm_resume(ThreadedVM* vm){
-        vm->resume();
+    void pkpy_tvm_resume(ThreadedVM* vm, const char* value){
+        vm->resume(value);
     }
 }

+ 45 - 17
src/vm.h

@@ -44,7 +44,7 @@
 typedef void(*PrintFn)(const VM*, const char*);
 
 class VM: public PkExportedResource{
-private:
+protected:
     std::deque< std::unique_ptr<Frame> > callstack;
     PyVarDict _modules;       // 3rd modules
     PyVar __py2py_call_signal;
@@ -1042,48 +1042,76 @@ 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::atomic<ThreadState> _state = THREAD_READY;
+    std::optional<_Str> _sharedStr = {};
+
+    PyVar jsonRpc(const _Str& _json){
+        _sharedStr = _json;
+        suspend();
+        std::optional<_Str> ret = readSharedStr();
+        if(ret.has_value()) return PyStr(ret.value());
+        return None;
+    }
 public:
-    ThreadedVM(bool use_stdio) : VM(use_stdio) {}
+    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);
+            return tvm->jsonRpc(tvm->PyStr_AS_C(args[0]));
+        });
 
-    _Str _stdin;
+        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);
+        });
+    }
 
     void suspend(){
         if(_thread == nullptr) UNREACHABLE();
-        if(state != THREAD_RUNNING) UNREACHABLE();
-        state = THREAD_SUSPENDED;
+        if(_state != THREAD_RUNNING) UNREACHABLE();
+        _state = THREAD_SUSPENDED;
         // 50 fps is enough
-        while(state == THREAD_SUSPENDED) std::this_thread::sleep_for(std::chrono::milliseconds(20));
+        while(_state == THREAD_SUSPENDED) std::this_thread::sleep_for(std::chrono::milliseconds(20));
     }
 
-    _Str readStdin(){
+    std::optional<_Str> readSharedStr(){
         if(_thread == nullptr) UNREACHABLE();
-        _Str copy = _stdin;
-        _stdin = "";
+        std::optional<_Str> copy = _sharedStr.value();
+        _sharedStr = {};
         return copy;
     }
 
     /***** For outer use *****/
 
     ThreadState getState(){
-        return state.load();
+        return _state;
     }
 
-    void resume(){
+    void resume(const char* value=nullptr){
         if(_thread == nullptr) UNREACHABLE();
-        if(state != THREAD_SUSPENDED) UNREACHABLE();
-        state = THREAD_RUNNING;
+        if(_state != THREAD_SUSPENDED) UNREACHABLE();
+        _state = THREAD_RUNNING;
+        if(value == nullptr){
+            _sharedStr = {};
+        }else{
+            _sharedStr = value;
+        }
     }
 
     void startExec(const _Code& code){
         if(_thread != nullptr) UNREACHABLE();
-        if(state != THREAD_READY) UNREACHABLE();
+        if(_state != THREAD_READY) UNREACHABLE();
         _thread = new std::thread([this, code](){
-            this->state = THREAD_RUNNING;
+            this->_state = THREAD_RUNNING;
             this->exec(code);
-            this->state = THREAD_FINISHED;
+            this->_state = THREAD_FINISHED;
         });
     }
 

+ 0 - 0
tests/hidden/3.py → tests/hidden/tvm.py