diff --git a/docs/modules/sys.md b/docs/modules/sys.md index 86a44d13..ab9ac723 100644 --- a/docs/modules/sys.md +++ b/docs/modules/sys.md @@ -15,8 +15,4 @@ May be one of: + `darwin` + `android` + `ios` -+ `emscripten` - -### `sys._repl()` - -Get a REPL for this vm. Use its `input` method to feed strings to the REPL. This function is experimental. \ No newline at end of file ++ `emscripten` \ No newline at end of file diff --git a/include/pocketpy/pocketpy_c.h b/include/pocketpy/pocketpy_c.h index 70d75555..628cb263 100644 --- a/include/pocketpy/pocketpy_c.h +++ b/include/pocketpy/pocketpy_c.h @@ -12,6 +12,7 @@ extern "C" { typedef struct pkpy_vm_handle pkpy_vm; typedef int (*pkpy_CFunction)(pkpy_vm*); +typedef void (*pkpy_COutputHandler)(pkpy_vm*, const char*, int); typedef int pkpy_CName; typedef int pkpy_CType; @@ -92,6 +93,7 @@ PK_EXPORT pkpy_CString pkpy_string(const char* s); PK_EXPORT pkpy_CName pkpy_name(const char* s); PK_EXPORT pkpy_CString pkpy_name_to_string(pkpy_CName name); PK_EXPORT void pkpy_compile_to_string(pkpy_vm*, const char* source, const char* filename, int mode, bool* ok, char** out); +PK_EXPORT void pkpy_set_output_handler(pkpy_vm*, pkpy_COutputHandler handler); /* REPL */ PK_EXPORT void* pkpy_new_repl(pkpy_vm*); diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 3fd67e05..0349e335 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -104,7 +104,7 @@ struct FrameId{ Frame* get() const { return &data->operator[](index); } }; -typedef void(*PrintFunc)(VM*, const Str&); +typedef void(*PrintFunc)(VM*, const char*, int); class VM { PK_ALWAYS_PASS_BY_POINTER(VM) @@ -181,6 +181,10 @@ public: void _push_varargs(PyObject* _0, PyObject* _1, PyObject* _2){ PUSH(_0); PUSH(_1); PUSH(_2); } void _push_varargs(PyObject* _0, PyObject* _1, PyObject* _2, PyObject* _3){ PUSH(_0); PUSH(_1); PUSH(_2); PUSH(_3); } + void stdout_write(const Str& s){ + _stdout(this, s.data, s.size); + } + template PyObject* call(PyObject* callable, Args&&... args){ PUSH(callable); diff --git a/src/ceval.cpp b/src/ceval.cpp index 93d8f120..ef83aadd 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -73,7 +73,7 @@ __NEXT_STEP:; THIRD() = _0; DISPATCH(); TARGET(PRINT_EXPR) - if(TOP() != None) _stdout(this, CAST(Str&, py_repr(TOP())) + "\n"); + if(TOP() != None) stdout_write(CAST(Str&, py_repr(TOP())) + "\n"); POP(); DISPATCH(); /*****************************************/ diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 09677fe5..2272b282 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -1293,59 +1293,8 @@ void add_module_time(VM* vm){ }); } -struct PyREPL{ - PY_CLASS(PyREPL, sys, _repl) - - REPL* repl; - - PyREPL(VM* vm){ repl = new REPL(vm); } - ~PyREPL(){ delete repl; } - - PyREPL(const PyREPL&) = delete; - PyREPL& operator=(const PyREPL&) = delete; - - PyREPL(PyREPL&& other) noexcept{ - repl = other.repl; - other.repl = nullptr; - } - - struct TempOut{ - PrintFunc backup; - VM* vm; - TempOut(VM* vm, PrintFunc f){ - this->vm = vm; - this->backup = vm->_stdout; - vm->_stdout = f; - } - ~TempOut(){ - vm->_stdout = backup; - } - TempOut(const TempOut&) = delete; - TempOut& operator=(const TempOut&) = delete; - TempOut(TempOut&&) = delete; - TempOut& operator=(TempOut&&) = delete; - }; - - static void _register(VM* vm, PyObject* mod, PyObject* type){ - vm->bind_constructor<1>(type, [](VM* vm, ArgsView args){ - return VAR_T(PyREPL, vm); - }); - - vm->bind_method<1>(type, "input", [](VM* vm, ArgsView args){ - PyREPL& self = _CAST(PyREPL&, args[0]); - const Str& s = CAST(Str&, args[1]); - PK_LOCAL_STATIC std::stringstream ss_out; - ss_out.str(""); - TempOut _(vm, [](VM* vm, const Str& s){ ss_out << s; }); - bool ok = self.repl->input(s.str()); - return VAR(Tuple({VAR(ok), VAR(ss_out.str())})); - }); - } -}; - void add_module_sys(VM* vm){ PyObject* mod = vm->new_module("sys"); - PyREPL::register_class(vm, mod); vm->setattr(mod, "version", VAR(PK_VERSION)); vm->setattr(mod, "platform", VAR(PK_SYS_PLATFORM)); @@ -1355,12 +1304,14 @@ void add_module_sys(VM* vm){ vm->setattr(mod, "stderr", stderr_); vm->bind_func<1>(stdout_, "write", [](VM* vm, ArgsView args) { - vm->_stdout(vm, CAST(Str&, args[0])); + Str& s = CAST(Str&, args[0]); + vm->_stdout(vm, s.data, s.size); return vm->None; }); vm->bind_func<1>(stderr_, "write", [](VM* vm, ArgsView args) { - vm->_stderr(vm, CAST(Str&, args[0])); + Str& s = CAST(Str&, args[0]); + vm->_stderr(vm, s.data, s.size); return vm->None; }); } @@ -1460,7 +1411,8 @@ void add_module_traceback(VM* vm){ vm->bind_func<0>(mod, "print_exc", [](VM* vm, ArgsView args) { if(vm->_last_exception==nullptr) vm->ValueError("no exception"); Exception& e = CAST(Exception&, vm->_last_exception); - vm->_stdout(vm, e.summary()); + Str sum = e.summary(); + vm->_stdout(vm, sum.data, sum.size); return vm->None; }); @@ -1486,7 +1438,8 @@ void add_module_dis(VM* vm){ vm->bind_func<1>(mod, "dis", [](VM* vm, ArgsView args) { CodeObject_ code = get_code(vm, args[0]); - vm->_stdout(vm, vm->disassemble(code)); + Str msg = vm->disassemble(code); + vm->_stdout(vm, msg.data, msg.size); return vm->None; }); diff --git a/src/pocketpy_c.cpp b/src/pocketpy_c.cpp index cb84836e..8ba2313d 100644 --- a/src/pocketpy_c.cpp +++ b/src/pocketpy_c.cpp @@ -569,6 +569,11 @@ void pkpy_compile_to_string(pkpy_vm* vm_handle, const char* source, const char* } } +void pkpy_set_output_handler(pkpy_vm* vm_handle, pkpy_COutputHandler handler){ + VM* vm = (VM*) vm_handle; + vm->_stdout = reinterpret_cast(handler); +} + void* pkpy_new_repl(pkpy_vm* vm_handle){ return new REPL((VM*)vm_handle); } diff --git a/src/repl.cpp b/src/repl.cpp index d9b9033f..3ff64cbe 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -2,10 +2,10 @@ namespace pkpy { REPL::REPL(VM* vm) : vm(vm){ - vm->_stdout(vm, "pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") "); - vm->_stdout(vm, fmt("[", sizeof(void*)*8, " bit] on ", PK_SYS_PLATFORM "\n")); - vm->_stdout(vm, "https://github.com/blueloveTH/pocketpy" "\n"); - vm->_stdout(vm, "Type \"exit()\" to exit." "\n"); + vm->stdout_write("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") "); + vm->stdout_write(fmt("[", sizeof(void*)*8, " bit] on ", PK_SYS_PLATFORM "\n")); + vm->stdout_write("https://github.com/blueloveTH/pocketpy" "\n"); + vm->stdout_write("Type \"exit()\" to exit." "\n"); } bool REPL::input(std::string line){ diff --git a/src/vm.cpp b/src/vm.cpp index 062d4cce..a1c24759 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -5,13 +5,13 @@ namespace pkpy{ VM::VM(bool enable_os) : heap(this), enable_os(enable_os) { this->vm = this; this->_c.error = nullptr; - _stdout = [](VM* vm, const Str& s) { + _stdout = [](VM* vm, const char* buf, int size) { PK_UNUSED(vm); - std::cout << s; + std::cout.write(buf, size); }; - _stderr = [](VM* vm, const Str& s) { + _stderr = [](VM* vm, const char* buf, int size) { PK_UNUSED(vm); - std::cerr << s; + std::cerr.write(buf, size); }; callstack.reserve(8); _main = nullptr; @@ -99,13 +99,14 @@ namespace pkpy{ #endif return _exec(code, _module); }catch (const Exception& e){ - _stderr(this, e.summary() + "\n"); + Str sum = e.summary() + "\n"; + _stderr(this, sum.data, sum.size); } #if !PK_DEBUG_FULL_EXCEPTION catch (const std::exception& e) { Str msg = "An std::exception occurred! It could be a bug.\n"; - msg = msg + e.what(); - _stderr(this, msg + "\n"); + msg = msg + e.what() + "\n"; + _stderr(this, msg.data, msg.size); } #endif callstack.clear(); diff --git a/src2/pocketpy_c.c b/src2/pocketpy_c.c index 97eb41ed..dbf6ed2b 100644 --- a/src2/pocketpy_c.c +++ b/src2/pocketpy_c.c @@ -237,6 +237,10 @@ void pkpy_compile_to_string(pkpy_vm* vm, const char* source, const char* filenam } +void pkpy_set_output_handler(pkpy_vm* vm, pkpy_COutputHandler handler) { + +} + void* pkpy_new_repl(pkpy_vm* vm) { void* returnValue; return returnValue;