adjust buffer settings

This commit is contained in:
blueloveTH 2022-11-15 18:06:14 +08:00
parent b13009dc8b
commit ad2a15a76c
7 changed files with 82 additions and 59 deletions

View File

@ -18,4 +18,5 @@
#include <iomanip> #include <iomanip>
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <iostream>

View File

@ -941,12 +941,11 @@ _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_M
return compiler.__fillCode(); return compiler.__fillCode();
}catch(std::exception& e){ }catch(std::exception& e){
if(const _Error* _ = dynamic_cast<const _Error*>(&e)){ if(const _Error* _ = dynamic_cast<const _Error*>(&e)){
vm->_stderr(vm, e.what()); (*vm->_stderr) << e.what() << '\n';
}else{ }else{
auto ce = CompileError("UnexpectedError", e.what(), compiler.getLineSnapshot()); auto ce = CompileError("UnexpectedError", e.what(), compiler.getLineSnapshot());
vm->_stderr(vm, ce.what()); (*vm->_stderr) << ce.what() << '\n';
} }
vm->_stderr(vm, "\n");
return nullptr; return nullptr;
} }
} }

View File

@ -1,4 +1,3 @@
#include <iostream>
#include <fstream> #include <fstream>
#include "pocketpy.h" #include "pocketpy.h"
@ -19,25 +18,6 @@ struct Timer{
} }
}; };
ThreadedVM* new_tvm_with_callbacks(){
ThreadedVM* vm = pkpy_new_tvm([](const VM* vm, const char* str) {
std::cout << str; std::cout.flush();
}, [](const VM* vm, const char* str) {
std::cerr << str; std::cerr.flush();
});
return vm;
}
VM* new_vm_with_callbacks(){
VM* vm = pkpy_new_vm([](const VM* vm, const char* str) {
std::cout << str; std::cout.flush();
}, [](const VM* vm, const char* str) {
std::cerr << str; std::cerr.flush();
});
return vm;
}
#if defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__) #if defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
// these code is for demo use, feel free to modify it // these code is for demo use, feel free to modify it
@ -47,7 +27,9 @@ REPL* _repl;
extern "C" { extern "C" {
__EXPORT __EXPORT
void repl_start(){ void repl_start(){
_repl = pkpy_new_repl(new_vm_with_callbacks(), false); VM* vm = pkpy_new_vm(true);
useStandardBuffer(vm);
_repl = pkpy_new_repl(vm, false);
} }
__EXPORT __EXPORT
@ -58,10 +40,10 @@ extern "C" {
#else #else
int main(int argc, char** argv){ int main(int argc, char** argv){
if(argc == 1){ if(argc == 1){
REPL repl(new_vm_with_callbacks()); VM* vm = pkpy_new_vm(true);
REPL repl(vm);
while(true){ while(true){
std::string line; std::string line;
std::getline(std::cin, line); std::getline(std::cin, line);
@ -81,7 +63,7 @@ int main(int argc, char** argv){
} }
std::string src((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::string src((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
ThreadedVM* vm = new_tvm_with_callbacks(); ThreadedVM* vm = pkpy_new_tvm(true);
_Code code; _Code code;
Timer("Compile time").run([&]{ Timer("Compile time").run([&]{
code = compile(vm, src.c_str(), filename); code = compile(vm, src.c_str(), filename);

View File

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

View File

@ -42,8 +42,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
_vm->bindBuiltinFunc("print", [](VM* vm, PyVarList args) { _vm->bindBuiltinFunc("print", [](VM* vm, PyVarList args) {
_StrStream ss; _StrStream ss;
for (auto& arg : args) ss << vm->PyStr_AS_C(vm->asStr(arg)) << " "; for (auto& arg : args) ss << vm->PyStr_AS_C(vm->asStr(arg)) << " ";
vm->_stdout(vm, ss.str().c_str()); (*vm->_stdout) << ss.str() << '\n';
vm->_stdout(vm, "\n");
return vm->None; return vm->None;
}); });
@ -593,6 +592,22 @@ extern "C" {
} }
}; };
__EXPORT
struct PyOutputDump: public PkExportedResource{
const char* stdout;
const char* stderr;
PyOutputDump(const char* _stdout, const char* _stderr){
stdout = strdup(_stdout);
stderr = strdup(_stderr);
}
~PyOutputDump(){
delete[] stdout;
delete[] stderr;
}
};
__EXPORT __EXPORT
void pkpy_delete(PkExportedResource* p){ void pkpy_delete(PkExportedResource* p){
delete p; delete p;
@ -665,11 +680,8 @@ extern "C" {
return vm->exec(code, _m) != nullptr; return vm->exec(code, _m) != nullptr;
} }
void __vm_init(VM* vm, PrintFn _stdout, PrintFn _stderr){ void __vm_init(VM* vm){
__initializeBuiltinFunctions(vm); __initializeBuiltinFunctions(vm);
vm->_stdout = _stdout;
vm->_stderr = _stderr;
_Code code = compile(vm, __BUILTINS_CODE, "<builtins>"); _Code code = compile(vm, __BUILTINS_CODE, "<builtins>");
if(code == nullptr) exit(1); if(code == nullptr) exit(1);
vm->_exec(code, vm->builtins); vm->_exec(code, vm->builtins);
@ -680,19 +692,34 @@ extern "C" {
} }
__EXPORT __EXPORT
VM* pkpy_new_vm(PrintFn _stdout, PrintFn _stderr){ VM* pkpy_new_vm(bool use_stdio){
VM* vm = new VM(); VM* vm = new VM(use_stdio);
__vm_init(vm, _stdout, _stderr); __vm_init(vm);
return vm; return vm;
} }
__EXPORT __EXPORT
ThreadedVM* pkpy_new_tvm(PrintFn _stdout, PrintFn _stderr){ ThreadedVM* pkpy_new_tvm(bool use_stdio){
ThreadedVM* vm = new ThreadedVM(); ThreadedVM* vm = new ThreadedVM(use_stdio);
__vm_init(vm, _stdout, _stderr); __vm_init(vm);
return vm; return vm;
} }
__EXPORT
PyOutputDump* pkpy_vm_read_output(VM* vm){
if(vm->use_stdio) UNREACHABLE();
_StrStream* s_out = dynamic_cast<_StrStream*>(vm->_stdout);
_StrStream* s_err = dynamic_cast<_StrStream*>(vm->_stderr);
if(s_out == nullptr || s_err == nullptr) UNREACHABLE();
PyOutputDump* dump = new PyOutputDump(
s_out->str().c_str(),
s_out->str().c_str()
);
s_out->str("");
s_err->str("");
return dump;
}
__EXPORT __EXPORT
int pkpy_tvm_get_state(ThreadedVM* vm){ int pkpy_tvm_get_state(ThreadedVM* vm){
return vm->getState(); return vm->getState();

View File

@ -21,15 +21,15 @@ class REPL: public PkExportedResource {
void _loop_start(){ void _loop_start(){
mode = SINGLE_MODE; mode = SINGLE_MODE;
if(use_prompt){ if(use_prompt){
vm->_stdout(vm, need_more_lines ? "... " : ">>> "); (*vm->_stdout) << (need_more_lines ? "... " : ">>> ");
} }
} }
public: public:
REPL(VM* vm, bool use_prompt=true) : vm(vm), use_prompt(use_prompt) { REPL(VM* vm, bool use_prompt=true) : vm(vm), use_prompt(use_prompt) {
vm->_stdout(vm, "pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n"); (*vm->_stdout) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n");
vm->_stdout(vm, "https://github.com/blueloveTH/pocketpy" "\n"); (*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
vm->_stdout(vm, "Type \"exit()\" to exit." "\n"); (*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
_loop_start(); _loop_start();
} }

View File

@ -48,7 +48,6 @@ class VM: public PkExportedResource{
private: private:
std::stack< std::unique_ptr<Frame> > callstack; std::stack< std::unique_ptr<Frame> > callstack;
PyVarDict _modules; // 3rd modules PyVarDict _modules; // 3rd modules
PyVar __py2py_call_signal; PyVar __py2py_call_signal;
PyVar runFrame(Frame* frame){ PyVar runFrame(Frame* frame){
@ -155,8 +154,7 @@ private:
{ {
const PyVar& expr = frame->topValue(this); const PyVar& expr = frame->topValue(this);
if(expr == None) break; if(expr == None) break;
_stdout(this, PyStr_AS_C(asRepr(expr)).c_str()); *_stdout << PyStr_AS_C(asRepr(expr)) << '\n';
_stdout(this, "\n");
} break; } break;
case OP_POP_TOP: frame->popValue(this); break; case OP_POP_TOP: frame->popValue(this); break;
case OP_BINARY_OP: case OP_BINARY_OP:
@ -328,15 +326,26 @@ public:
PyVarDict _types; PyVarDict _types;
PyVar None, True, False; PyVar None, True, False;
PrintFn _stdout = [](const VM* vm, auto s){}; bool use_stdio;
PrintFn _stderr = [](const VM* vm, auto s){}; std::ostream* _stdout;
std::ostream* _stderr;
PyVar builtins; // builtins module PyVar builtins; // builtins module
PyVar _main; // __main__ module PyVar _main; // __main__ module
int maxRecursionDepth = 1000; int maxRecursionDepth = 1000;
VM(){ VM(bool use_stdio){
this->use_stdio = use_stdio;
if(use_stdio){
std::cout.setf(std::ios::unitbuf);
std::cerr.setf(std::ios::unitbuf);
this->_stdout = &std::cout;
this->_stderr = &std::cerr;
}else{
this->_stdout = new _StrStream();
this->_stderr = new _StrStream();
}
initializeBuiltinClasses(); initializeBuiltinClasses();
} }
@ -462,12 +471,11 @@ public:
return _exec(code, _module); return _exec(code, _module);
} catch (const std::exception& e) { } catch (const std::exception& e) {
if(const _Error* _ = dynamic_cast<const _Error*>(&e)){ if(const _Error* _ = dynamic_cast<const _Error*>(&e)){
_stderr(this, e.what()); *_stderr << e.what() << '\n';
}else{ }else{
auto re = RuntimeError("UnexpectedError", e.what(), _cleanErrorAndGetSnapshots()); auto re = RuntimeError("UnexpectedError", e.what(), _cleanErrorAndGetSnapshots());
_stderr(this, re.what()); *_stderr << re.what() << '\n';
} }
_stderr(this, "\n");
return nullptr; return nullptr;
} }
} }
@ -785,7 +793,12 @@ public:
if (!val) _error("AssertionError", msg); if (!val) _error("AssertionError", msg);
} }
virtual ~VM() = default; virtual ~VM() {
if(!use_stdio){
delete _stdout;
delete _stderr;
}
}
}; };
/***** Pointers' Impl *****/ /***** Pointers' Impl *****/
@ -916,10 +929,11 @@ enum ThreadState {
class ThreadedVM : public VM { class ThreadedVM : public VM {
std::thread* _thread; std::thread* _thread;
std::atomic<ThreadState> state = THREAD_READY; std::atomic<ThreadState> state = THREAD_READY;
public: public:
ThreadedVM(bool use_stdio) : VM(use_stdio) {}
_Str _stdin; _Str _stdin;
void suspend(){ void suspend(){
if(_thread == nullptr) UNREACHABLE(); if(_thread == nullptr) UNREACHABLE();
if(state != THREAD_RUNNING) UNREACHABLE(); if(state != THREAD_RUNNING) UNREACHABLE();
@ -938,8 +952,7 @@ public:
/***** For outer use *****/ /***** For outer use *****/
ThreadState getState(){ ThreadState getState(){
if(_thread == nullptr) UNREACHABLE(); return state.load();
return state;
} }
void resume(){ void resume(){
@ -950,6 +963,7 @@ public:
void startExec(const _Code& code){ void startExec(const _Code& code){
if(_thread != nullptr) UNREACHABLE(); if(_thread != nullptr) UNREACHABLE();
if(state != THREAD_READY) UNREACHABLE();
_thread = new std::thread([this, code](){ _thread = new std::thread([this, code](){
this->state = THREAD_RUNNING; this->state = THREAD_RUNNING;
this->exec(code); this->exec(code);