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;
|
_Source src;
|
||||||
_Str name;
|
_Str name;
|
||||||
|
|
||||||
CodeObject(_Source src, _Str name, CompileMode mode=EXEC_MODE) {
|
CodeObject(_Source src, _Str name) {
|
||||||
this->src = src;
|
this->src = src;
|
||||||
this->name = name;
|
this->name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompileMode mode() const {
|
||||||
|
return src->mode;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ByteCode> co_code;
|
std::vector<ByteCode> co_code;
|
||||||
PyVarList co_consts;
|
PyVarList co_consts;
|
||||||
std::vector<std::shared_ptr<NamePointer>> co_names;
|
std::vector<std::shared_ptr<NamePointer>> co_names;
|
||||||
|
@ -931,7 +931,7 @@ __LISTCOMP:
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Code __fillCode(){
|
_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);
|
codes.push(code);
|
||||||
|
|
||||||
// Lex initial tokens. current <-- next.
|
// Lex initial tokens. current <-- next.
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
enum CompileMode {
|
enum CompileMode {
|
||||||
EXEC_MODE,
|
EXEC_MODE,
|
||||||
EVAL_MODE,
|
EVAL_MODE,
|
||||||
SINGLE_MODE
|
SINGLE_MODE // for REPL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SourceMetadata {
|
struct SourceMetadata {
|
||||||
|
23
src/main.cpp
23
src/main.cpp
@ -21,19 +21,21 @@ struct Timer{
|
|||||||
#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
|
||||||
|
|
||||||
REPL* _repl;
|
REPL* _repl;
|
||||||
|
VM* _vm;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__EXPORT
|
__EXPORT
|
||||||
void repl_start(){
|
void repl_start(){
|
||||||
VM* vm = pkpy_new_vm(true);
|
_vm = pkpy_new_vm(true);
|
||||||
_repl = pkpy_new_repl(vm, false);
|
_repl = pkpy_new_repl(_vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
bool repl_input(const char* line){
|
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);
|
VM* vm = pkpy_new_vm(true);
|
||||||
REPL repl(vm);
|
REPL repl(vm);
|
||||||
while(true){
|
while(true){
|
||||||
|
(*vm->_stdout) << (repl.is_need_more_lines() ? "... " : ">>> ");
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(std::cin, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -82,11 +89,15 @@ int main(int argc, char** argv){
|
|||||||
while(pkpy_tvm_get_state(vm) != THREAD_FINISHED){
|
while(pkpy_tvm_get_state(vm) != THREAD_FINISHED){
|
||||||
if(pkpy_tvm_get_state(vm) == THREAD_SUSPENDED){
|
if(pkpy_tvm_get_state(vm) == THREAD_SUSPENDED){
|
||||||
PyObjectDump* obj = pkpy_tvm_read_json(vm);
|
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);
|
pkpy_delete(obj);
|
||||||
|
if(is_input_call){
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(std::cin, line);
|
std::getline(std::cin, line);
|
||||||
pkpy_tvm_resume(vm, line.c_str());
|
pkpy_tvm_resume(vm, line.c_str());
|
||||||
|
}else{
|
||||||
|
pkpy_tvm_resume(vm, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -657,6 +657,13 @@ extern "C" {
|
|||||||
return vm->exec(code) != nullptr;
|
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
|
__EXPORT
|
||||||
PyObjectDump* pkpy_get_global(VM* vm, const char* name){
|
PyObjectDump* pkpy_get_global(VM* vm, const char* name){
|
||||||
auto it = vm->_main->attribs.find(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
|
__EXPORT
|
||||||
PyObjectDump* pkpy_eval(VM* vm, const char* source){
|
PyObjectDump* pkpy_eval(VM* vm, const char* source){
|
||||||
_Code code = compile(vm, source, "<eval>", EVAL_MODE);
|
_Code code = compile(vm, source, "<eval>", EVAL_MODE);
|
||||||
if(code == nullptr) return nullptr;
|
if(code == nullptr) return nullptr;
|
||||||
PyVar ret = vm->exec(code);
|
PyVarOrNull ret = vm->exec(code);
|
||||||
if(ret == nullptr) return nullptr;
|
if(ret == nullptr) return nullptr;
|
||||||
return new PyObjectDump(
|
return new PyObjectDump(
|
||||||
ret->getTypeName(),
|
ret->getTypeName(),
|
||||||
@ -700,8 +687,8 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
REPL* pkpy_new_repl(VM* vm, bool use_prompt){
|
REPL* pkpy_new_repl(VM* vm){
|
||||||
return new REPL(vm, use_prompt);
|
return new REPL(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
@ -767,11 +754,25 @@ extern "C" {
|
|||||||
return true;
|
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
|
__EXPORT
|
||||||
PyObjectDump* pkpy_tvm_read_json(ThreadedVM* vm){
|
PyObjectDump* pkpy_tvm_read_json(ThreadedVM* vm){
|
||||||
std::optional<_Str> s = vm->readSharedStr();
|
std::optional<_Str> s = vm->readSharedStr();
|
||||||
if(!s.has_value()) return nullptr;
|
if(!s.has_value()) return nullptr;
|
||||||
return new PyObjectDump("str", s.value());
|
return new PyObjectDump("str"_c, s.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
|
44
src/repl.h
44
src/repl.h
@ -4,33 +4,28 @@
|
|||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
class REPL: public PkExportedResource {
|
class REPL: public PkExportedResource {
|
||||||
|
protected:
|
||||||
int need_more_lines = 0;
|
int need_more_lines = 0;
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
CompileMode mode;
|
CompileMode mode;
|
||||||
VM* vm;
|
VM* vm;
|
||||||
|
|
||||||
bool use_prompt; // whether to print >>> or ...
|
|
||||||
|
|
||||||
bool exited = false;
|
bool exited = false;
|
||||||
|
|
||||||
void _exit(){
|
void _exit(){
|
||||||
exited = true;
|
exited = true;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loop_start(){
|
|
||||||
mode = SINGLE_MODE;
|
|
||||||
if(use_prompt){
|
|
||||||
(*vm->_stdout) << (need_more_lines ? "... " : ">>> ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
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) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n");
|
||||||
(*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
|
(*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
|
||||||
(*vm->_stdout) << ("Type \"exit()\" to exit." "\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){
|
bool input(const char* line){
|
||||||
@ -39,6 +34,7 @@ public:
|
|||||||
|
|
||||||
bool input(std::string line){
|
bool input(std::string line){
|
||||||
if(exited) return false;
|
if(exited) return false;
|
||||||
|
mode = SINGLE_MODE;
|
||||||
if(need_more_lines){
|
if(need_more_lines){
|
||||||
buffer += line;
|
buffer += line;
|
||||||
buffer += '\n';
|
buffer += '\n';
|
||||||
@ -62,14 +58,30 @@ __NOT_ENOUGH_LINES:
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
_Code code = compile(vm, line.c_str(), "<stdin>", mode);
|
_Code code = compile(vm, line.c_str(), "<stdin>", mode);
|
||||||
if(code != nullptr) vm->exec(code, nullptr, true);
|
this->onCompiled(code);
|
||||||
}catch(NeedMoreLines& ne){
|
}catch(NeedMoreLines& ne){
|
||||||
buffer += line;
|
buffer += line;
|
||||||
buffer += '\n';
|
buffer += '\n';
|
||||||
need_more_lines = ne.isClassDef ? 3 : 2;
|
need_more_lines = ne.isClassDef ? 3 : 2;
|
||||||
}
|
}
|
||||||
__LOOP_CONTINUE:
|
__LOOP_CONTINUE:
|
||||||
_loop_start();
|
return is_need_more_lines();
|
||||||
return need_more_lines > 0;
|
}
|
||||||
|
|
||||||
|
_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);
|
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;
|
if(_module == nullptr) _module = _main;
|
||||||
try {
|
try {
|
||||||
return _exec(code, _module, {}, repl_mode);
|
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 << e.what() << '\n';
|
*_stderr << e.what() << '\n';
|
||||||
@ -532,9 +533,9 @@ public:
|
|||||||
return frame;
|
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);
|
Frame* frame = __pushNewFrame(code, _module, locals);
|
||||||
if(repl_mode) frame->id = 0;
|
if(code->mode() == SINGLE_MODE) frame->id = 0;
|
||||||
Frame* frameBase = frame;
|
Frame* frameBase = frame;
|
||||||
PyVar ret = nullptr;
|
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(){
|
~ThreadedVM(){
|
||||||
if(_thread != nullptr){
|
if(_thread != nullptr){
|
||||||
_thread->join();
|
_thread->join();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user