mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
up
fix web issues Update main.cpp Update main.cpp
This commit is contained in:
parent
d9117c4b6a
commit
ceb8e2e5de
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
enum CompileMode {
|
||||
EXEC_MODE,
|
||||
EVAL_MODE,
|
||||
SINGLE_MODE
|
||||
SINGLE_MODE // for REPL
|
||||
};
|
||||
|
||||
struct SourceMetadata {
|
||||
|
29
src/main.cpp
29
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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
|
||||
|
44
src/repl.h
44
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);
|
||||
}
|
||||
}
|
||||
};
|
23
src/vm.h
23
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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user