fix web issues

Update main.cpp

Update main.cpp
This commit is contained in:
blueloveTH 2022-11-28 17:34:02 +08:00
parent d9117c4b6a
commit ceb8e2e5de
7 changed files with 99 additions and 56 deletions

View File

@ -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;

View File

@ -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.

View File

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

View File

@ -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);
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);
}
}
}
});

View File

@ -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

View File

@ -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);
}
}
};

View File

@ -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();