diff --git a/amalgamate.py b/amalgamate.py index 6ae1b4cb..97d843bd 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -4,7 +4,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f: pipeline = [ ["__stl__.h", "str.h", "builtins.h", "error.h"], ["obj.h", "iter.h", "parser.h", "pointer.h", "codeobject.h"], - ["vm.h", "compiler.h"], + ["vm.h", "compiler.h", "repl.h"], ["pocketpy.h"] ] diff --git a/build_wasm.sh b/build_wasm.sh index b60a93a1..e5a4d046 100644 --- a/build_wasm.sh +++ b/build_wasm.sh @@ -1,3 +1,3 @@ rm -rf build/wasm/ mkdir -p build/wasm/ -emcc src/main.cpp -fexceptions -o build/wasm/index.html +emcc src/main.cpp -fexceptions -sEXIT_RUNTIME -sEXPORTED_FUNCTIONS=_repl_input,_repl_start -sEXPORTED_RUNTIME_METHODS=ccall -o build/wasm/pocketpy.js \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e7cb21a2..baebb942 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,65 +20,44 @@ struct Timer{ }; VM* newVM(){ + // disable buff of std::cout and std::cerr + std::cout.setf(std::ios::unitbuf); + std::cerr.setf(std::ios::unitbuf); VM* vm = createVM([](const char* str) { std::cout << str; - std::cout.flush(); }, [](const char* str) { std::cerr << str; - std::cerr.flush(); }); return vm; } -void REPL(){ - std::cout << "pocketpy " PK_VERSION << std::endl; - std::cout << "https://github.com/blueloveTH/pocketpy" << std::endl; - int need_more_lines = 0; - std::string buffer; - VM* vm = newVM(); +#if defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__) - while(true){ - CompileMode mode = SINGLE_MODE; - vm->_stdout(need_more_lines ? "... " : ">>> "); - std::string line; - std::getline(std::cin, line); +REPL* _repl; - if(need_more_lines){ - buffer += line; - buffer += '\n'; - int n = buffer.size(); - if(n>=need_more_lines){ - for(int i=buffer.size()-need_more_lines; i", mode); - if(code != nullptr) vm->exec(code); - }catch(NeedMoreLines& ne){ - buffer += line; - buffer += '\n'; - need_more_lines = ne.isClassDef ? 3 : 2; - } + __EXPORT + bool repl_input(const char* line){ + return _repl->input(line); } } +#else + int main(int argc, char** argv){ if(argc == 1){ - REPL(); + REPL repl(newVM()); + while(true){ + std::string line; + std::getline(std::cin, line); + repl.input(line); + } return 0; } @@ -109,4 +88,6 @@ int main(int argc, char** argv){ __HELP: std::cout << "Usage: pocketpy [filename]" << std::endl; return 0; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/obj.h b/src/obj.h index 4f247837..ba210a13 100644 --- a/src/obj.h +++ b/src/obj.h @@ -11,6 +11,8 @@ const _Int _Int_MAX_NEG = -9223372036854775807LL; const _Float _FLOAT_INF_POS = INFINITY; const _Float _FLOAT_INF_NEG = -INFINITY; +#define PK_VERSION "0.2.0" + class PyObject; class CodeObject; class BasePointer; diff --git a/src/pocketpy.h b/src/pocketpy.h index 0d1aec5b..b928c7e1 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -2,8 +2,7 @@ #include "vm.h" #include "compiler.h" - -#define PK_VERSION "0.2.0" +#include "repl.h" #define BIND_NUM_ARITH_OPT(name, op) \ _vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, PyVarList args){ \ diff --git a/src/repl.h b/src/repl.h new file mode 100644 index 00000000..cd83da2a --- /dev/null +++ b/src/repl.h @@ -0,0 +1,75 @@ +#pragma once + +#include "compiler.h" +#include "vm.h" + +class REPL { + int need_more_lines = 0; + std::string buffer; + CompileMode mode; + VM* vm; + + bool use_prompt; + + 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) { + vm->_stdout("pocketpy " PK_VERSION "\n"); + vm->_stdout("https://github.com/blueloveTH/pocketpy" "\n"); + vm->_stdout("Type \"exit()\" to exit." "\n"); + _loop_start(); + } + + bool input(const char* line){ + return input(std::string(line)); + } + + bool input(std::string line){ + if(exited) return false; + if(need_more_lines){ + buffer += line; + buffer += '\n'; + int n = buffer.size(); + if(n>=need_more_lines){ + for(int i=buffer.size()-need_more_lines; i", mode); + if(code != nullptr) vm->exec(code); + }catch(NeedMoreLines& ne){ + buffer += line; + buffer += '\n'; + need_more_lines = ne.isClassDef ? 3 : 2; + } +__LOOP_CONTINUE: + _loop_start(); + return need_more_lines > 0; + } +}; \ No newline at end of file