Просмотр исходного кода

up

fix web issues

Update main.cpp

Update main.cpp
blueloveTH 3 лет назад
Родитель
Сommit
ceb8e2e5de
7 измененных файлов с 99 добавлено и 56 удалено
  1. 5 1
      src/codeobject.h
  2. 1 1
      src/compiler.h
  3. 1 1
      src/error.h
  4. 20 9
      src/main.cpp
  5. 25 24
      src/pocketpy.h
  6. 28 16
      src/repl.h
  7. 19 4
      src/vm.h

+ 5 - 1
src/codeobject.h

@@ -30,11 +30,15 @@ struct CodeObject {
     _Source src;
     _Str name;
 
-    CodeObject(_Source src, _Str name, CompileMode mode=EXEC_MODE) {
+    CodeObject(_Source src, _Str name) {
         this->src = src;
         this->name = name;
     }
 
+    CompileMode mode() const {
+        return src->mode;
+    }
+
     std::vector<ByteCode> co_code;
     PyVarList co_consts;
     std::vector<std::shared_ptr<NamePointer>> co_names;

+ 1 - 1
src/compiler.h

@@ -931,7 +931,7 @@ __LISTCOMP:
     }
 
     _Code __fillCode(){
-        _Code code = std::make_shared<CodeObject>(parser->src, _Str("<module>"), mode());
+        _Code code = std::make_shared<CodeObject>(parser->src, _Str("<module>"));
         codes.push(code);
 
         // Lex initial tokens. current <-- next.

+ 1 - 1
src/error.h

@@ -11,7 +11,7 @@ public:
 enum CompileMode {
     EXEC_MODE,
     EVAL_MODE,
-    SINGLE_MODE
+    SINGLE_MODE     // for REPL
 };
 
 struct SourceMetadata {

+ 20 - 9
src/main.cpp

@@ -21,19 +21,21 @@ struct Timer{
 #if defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
 
 // these code is for demo use, feel free to modify it
-
 REPL* _repl;
+VM* _vm;
 
 extern "C" {
     __EXPORT
     void repl_start(){
-        VM* vm = pkpy_new_vm(true);
-        _repl = pkpy_new_repl(vm, false);
+        _vm = pkpy_new_vm(true);
+        _repl = pkpy_new_repl(_vm);
     }
 
     __EXPORT
     bool repl_input(const char* line){
-        return pkpy_repl_input(_repl, line);
+        bool need_more_lines = pkpy_repl_input(_repl, line);
+        if(!need_more_lines) pkpy_exec_repl(_repl);
+        return need_more_lines;
     }
 }
 
@@ -44,9 +46,14 @@ int main(int argc, char** argv){
         VM* vm = pkpy_new_vm(true);
         REPL repl(vm);
         while(true){
+            (*vm->_stdout) << (repl.is_need_more_lines() ? "... " : ">>> ");
             std::string line;
             std::getline(std::cin, line);
-            repl.input(line);
+            if(repl.input(line) == false){      // do not need more lines
+                _Code code = repl.readBufferCode();
+                if(code == nullptr) continue;
+                vm->exec(code);
+            }
         }
         return 0;
     }
@@ -82,11 +89,15 @@ int main(int argc, char** argv){
             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();
+                    bool is_input_call = INPUT_JSONRPC_STR != obj->json;
                     pkpy_delete(obj);
-                    std::string line;
-                    std::getline(std::cin, line);
-                    pkpy_tvm_resume(vm, line.c_str());
+                    if(is_input_call){
+                        std::string line;
+                        std::getline(std::cin, line);
+                        pkpy_tvm_resume(vm, line.c_str());
+                    }else{
+                        pkpy_tvm_resume(vm, nullptr);
+                    }
                 }
             }
         });

+ 25 - 24
src/pocketpy.h

@@ -657,6 +657,13 @@ extern "C" {
         return vm->exec(code) != nullptr;
     }
 
+    __EXPORT
+    bool pkpy_exec_repl(REPL* r){
+        _Code code = r->readBufferCode();
+        if(code == nullptr) return false;
+        return r->getVM()->exec(code) != nullptr;
+    }
+
     __EXPORT
     PyObjectDump* pkpy_get_global(VM* vm, const char* name){
         auto it = vm->_main->attribs.find(name);
@@ -667,31 +674,11 @@ extern "C" {
         );
     }
 
-    __EXPORT
-    void pkpy_set_global_int(VM* vm, const char* name, _Int value){
-        vm->setAttr(vm->_main, name, vm->PyInt(value));
-    }
-
-    __EXPORT
-    void pkpy_set_global_float(VM* vm, const char* name, _Float value){
-        vm->setAttr(vm->_main, name, vm->PyFloat(value));
-    }
-
-    __EXPORT
-    void pkpy_set_global_str(VM* vm, const char* name, const char* value){
-        vm->setAttr(vm->_main, name, vm->PyStr(value));
-    }
-
-    __EXPORT
-    void pkpy_set_global_bool(VM* vm, const char* name, bool value){
-        vm->setAttr(vm->_main, name, vm->PyBool(value));
-    }
-
     __EXPORT
     PyObjectDump* pkpy_eval(VM* vm, const char* source){
         _Code code = compile(vm, source, "<eval>", EVAL_MODE);
         if(code == nullptr) return nullptr;
-        PyVar ret = vm->exec(code);
+        PyVarOrNull ret = vm->exec(code);
         if(ret == nullptr) return nullptr;
         return new PyObjectDump(
             ret->getTypeName(),
@@ -700,8 +687,8 @@ extern "C" {
     }
 
     __EXPORT
-    REPL* pkpy_new_repl(VM* vm, bool use_prompt){
-        return new REPL(vm, use_prompt);
+    REPL* pkpy_new_repl(VM* vm){
+        return new REPL(vm);
     }
 
     __EXPORT
@@ -767,11 +754,25 @@ extern "C" {
         return true;
     }
 
+    __EXPORT
+    void pkpy_tvm_reset_state(ThreadedVM* vm){
+        vm->resetState();
+    }
+
+    __EXPORT
+    bool pkpy_tvm_start_exec_repl(REPL* r){
+        _Code code = r->readBufferCode();
+        if(code == nullptr) return false;
+        ThreadedVM* vm = dynamic_cast<ThreadedVM*>(r->getVM());
+        vm->startExec(code);
+        return true;
+    }
+
     __EXPORT
     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());
+        return new PyObjectDump("str"_c, s.value());
     }
 
     __EXPORT

+ 28 - 16
src/repl.h

@@ -4,33 +4,28 @@
 #include "vm.h"
 
 class REPL: public PkExportedResource {
+protected:
     int need_more_lines = 0;
     std::string buffer;
     CompileMode mode;
     VM* vm;
-
-    bool use_prompt;        // whether to print >>> or ...
-
     bool exited = false;
 
     void _exit(){
         exited = true;
         exit(0);
     }
-
-    void _loop_start(){
-        mode = SINGLE_MODE;
-        if(use_prompt){
-            (*vm->_stdout) << (need_more_lines ? "... " : ">>> ");
-        }
-    }
-
 public:
-    REPL(VM* vm, bool use_prompt=true) : vm(vm), use_prompt(use_prompt) {
+    REPL(VM* vm) : vm(vm){
         (*vm->_stdout) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n");
         (*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
         (*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
-        _loop_start();
+    }
+
+    VM* getVM() { return vm; }
+
+    bool is_need_more_lines() const {
+        return need_more_lines;
     }
 
     bool input(const char* line){
@@ -39,6 +34,7 @@ public:
 
     bool input(std::string line){
         if(exited) return false;
+        mode = SINGLE_MODE;
         if(need_more_lines){
             buffer += line;
             buffer += '\n';
@@ -62,14 +58,30 @@ __NOT_ENOUGH_LINES:
 
         try{
             _Code code = compile(vm, line.c_str(), "<stdin>", mode);
-            if(code != nullptr) vm->exec(code, nullptr, true);
+            this->onCompiled(code);
         }catch(NeedMoreLines& ne){
             buffer += line;
             buffer += '\n';
             need_more_lines = ne.isClassDef ? 3 : 2;
         }
 __LOOP_CONTINUE:
-        _loop_start();
-        return need_more_lines > 0;
+        return is_need_more_lines();
+    }
+
+    _Code readBufferCode(){
+        auto copy = std::move(bufferCode);
+        bufferCode = nullptr;
+        return copy;
+    }
+
+protected:
+    _Code bufferCode = nullptr;
+
+    void onCompiled(_Code code){
+        if(code == nullptr){
+            bufferCode = nullptr;
+        }else{
+            bufferCode = std::move(code);
+        }
     }
 };

+ 19 - 4
src/vm.h

@@ -507,10 +507,11 @@ public:
         return call(getAttr(obj, func), args);
     }
 
-    PyVarOrNull exec(const _Code& code, PyVar _module=nullptr, bool repl_mode=false){
+    // repl mode is only for setting `frame->id` to 0
+    virtual PyVarOrNull exec(const _Code& code, PyVar _module=nullptr){
         if(_module == nullptr) _module = _main;
         try {
-            return _exec(code, _module, {}, repl_mode);
+            return _exec(code, _module, {});
         } catch (const std::exception& e) {
             if(const _Error* _ = dynamic_cast<const _Error*>(&e)){
                 *_stderr << e.what() << '\n';
@@ -532,9 +533,9 @@ public:
         return frame;
     }
 
-    PyVar _exec(const _Code& code, PyVar _module, const PyVarDict& locals, bool repl_mode=false){
+    PyVar _exec(const _Code& code, PyVar _module, const PyVarDict& locals){
         Frame* frame = __pushNewFrame(code, _module, locals);
-        if(repl_mode) frame->id = 0;
+        if(code->mode() == SINGLE_MODE) frame->id = 0;
         Frame* frameBase = frame;
         PyVar ret = nullptr;
 
@@ -1120,6 +1121,20 @@ public:
         });
     }
 
+    PyVarOrNull exec(const _Code& code, PyVar _module = nullptr) override {
+        if(_state == THREAD_READY) return VM::exec(code, _module);
+        auto callstackBackup = std::move(callstack);
+        callstack.clear();
+        PyVarOrNull ret = VM::exec(code, _module);
+        callstack = std::move(callstackBackup);
+        return ret;
+    }
+
+    void resetState(){
+        if(this->_state != THREAD_FINISHED) UNREACHABLE();
+        this->_state = THREAD_READY;
+    }
+
     ~ThreadedVM(){
         if(_thread != nullptr){
             _thread->join();