mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
fix some errors
This commit is contained in:
parent
9c16aefda3
commit
9b9e1b9fd0
@ -17,7 +17,6 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@ -229,6 +229,28 @@ def sorted(iterable, key=None, reverse=False):
|
|||||||
b[i], b[j] = b[j], b[i]
|
b[i], b[j] = b[j], b[i]
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
import json as _json
|
||||||
|
|
||||||
|
def jsonrpc(method, params, raw=False):
|
||||||
|
assert type(method) is str
|
||||||
|
assert type(params) is list
|
||||||
|
data = {
|
||||||
|
'jsonrpc': '2.0',
|
||||||
|
'method': method,
|
||||||
|
'params': params,
|
||||||
|
}
|
||||||
|
ret = __string_channel_call(_json.dumps(data))
|
||||||
|
ret = _json.loads(ret)
|
||||||
|
if raw:
|
||||||
|
return ret
|
||||||
|
assert type(ret) is dict
|
||||||
|
if 'result' in ret:
|
||||||
|
return ret['result']
|
||||||
|
raise JsonRpcError(ret['error']['message'])
|
||||||
|
|
||||||
|
def input(prompt=None):
|
||||||
|
return jsonrpc('input', [prompt])
|
||||||
|
|
||||||
class FileIO:
|
class FileIO:
|
||||||
def __init__(self, path, mode):
|
def __init__(self, path, mode):
|
||||||
assert type(path) is str
|
assert type(path) is str
|
||||||
@ -236,19 +258,19 @@ class FileIO:
|
|||||||
assert mode in ['r', 'w']
|
assert mode in ['r', 'w']
|
||||||
self.path = path
|
self.path = path
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.fp = jsonrpc({"method": "fopen", "params": [path, mode]})
|
self.fp = jsonrpc('fopen', [path, mode])
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
assert self.mode == 'r'
|
assert self.mode == 'r'
|
||||||
return jsonrpc({"method": "fread", "params": [self.fp]})
|
return jsonrpc('fread', [self.fp])
|
||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
assert self.mode == 'w'
|
assert self.mode == 'w'
|
||||||
assert type(s) is str
|
assert type(s) is str
|
||||||
jsonrpc({"method": "fwrite", "params": [self.fp, s]})
|
jsonrpc('fwrite', [self.fp, s])
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
jsonrpc({"method": "fclose", "params": [self.fp]})
|
jsonrpc('fclose', [self.fp])
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
pass
|
pass
|
||||||
|
@ -1020,8 +1020,9 @@ __LISTCOMP:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE) {
|
_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) {
|
||||||
Compiler compiler(vm, source, filename, mode);
|
Compiler compiler(vm, source, filename, mode);
|
||||||
|
if(!noThrow) return compiler.__fillCode();
|
||||||
try{
|
try{
|
||||||
return compiler.__fillCode();
|
return compiler.__fillCode();
|
||||||
}catch(std::exception& e){
|
}catch(std::exception& e){
|
||||||
|
@ -43,11 +43,15 @@ void _tvm_dispatch(ThreadedVM* vm){
|
|||||||
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){
|
||||||
char* obj = pkpy_tvm_read_jsonrpc_request(vm);
|
char* obj = pkpy_tvm_read_jsonrpc_request(vm);
|
||||||
bool is_input_call = INPUT_JSONRPC_STR == std::string(obj);
|
bool is_input_call = std::string_view(obj).find("\"input\"") != std::string::npos;
|
||||||
if(is_input_call){
|
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());
|
_StrStream ss;
|
||||||
|
ss << '{';
|
||||||
|
ss << "\"result\": " << _Str(line).__escape(false);
|
||||||
|
ss << '}';
|
||||||
|
pkpy_tvm_jsonrpc_response(vm, ss.str().c_str());
|
||||||
}else{
|
}else{
|
||||||
std::cout << "unknown jsonrpc call" << std::endl;
|
std::cout << "unknown jsonrpc call" << std::endl;
|
||||||
std::cout << obj << std::endl;
|
std::cout << obj << std::endl;
|
||||||
|
@ -58,8 +58,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkArgSize(args, 1);
|
vm->__checkArgSize(args, 1);
|
||||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||||
_Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE);
|
_Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE, false);
|
||||||
if(code == nullptr) return vm->None;
|
|
||||||
return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals);
|
return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -639,8 +638,7 @@ void __addModuleJson(VM* vm){
|
|||||||
vm->bindFunc(mod, "loads", [](VM* vm, const pkpy::ArgList& args) {
|
vm->bindFunc(mod, "loads", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkArgSize(args, 1);
|
vm->__checkArgSize(args, 1);
|
||||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||||
_Code code = compile(vm, expr.c_str(), "<json>", JSON_MODE);
|
_Code code = compile(vm, expr.c_str(), "<json>", JSON_MODE, false);
|
||||||
if(code == nullptr) return vm->None;
|
|
||||||
return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals);
|
return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -650,14 +648,14 @@ void __addModuleJson(VM* vm){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PkExported;
|
|
||||||
static std::vector<_PkExported*> _pkLookupTable;
|
|
||||||
class _PkExported{
|
class _PkExported{
|
||||||
public:
|
public:
|
||||||
virtual ~_PkExported() = default;
|
virtual ~_PkExported() = default;
|
||||||
virtual void* get() = 0;
|
virtual void* get() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static std::vector<_PkExported*> _pkLookupTable;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class PkExported : public _PkExported{
|
class PkExported : public _PkExported{
|
||||||
T* _ptr;
|
T* _ptr;
|
||||||
@ -763,13 +761,13 @@ extern "C" {
|
|||||||
|
|
||||||
void __vm_init(VM* vm){
|
void __vm_init(VM* vm){
|
||||||
__initializeBuiltinFunctions(vm);
|
__initializeBuiltinFunctions(vm);
|
||||||
_Code code = compile(vm, __BUILTINS_CODE, "<builtins>");
|
|
||||||
if(code == nullptr) exit(1);
|
|
||||||
vm->_exec(code, vm->builtins, {});
|
|
||||||
|
|
||||||
__addModuleSys(vm);
|
__addModuleSys(vm);
|
||||||
__addModuleTime(vm);
|
__addModuleTime(vm);
|
||||||
__addModuleJson(vm);
|
__addModuleJson(vm);
|
||||||
|
|
||||||
|
_Code code = compile(vm, __BUILTINS_CODE, "<builtins>");
|
||||||
|
if(code == nullptr) exit(1);
|
||||||
|
vm->_exec(code, vm->builtins, {});
|
||||||
pkpy_vm_add_module(vm, "random", __RANDOM_CODE);
|
pkpy_vm_add_module(vm, "random", __RANDOM_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,22 +828,15 @@ extern "C" {
|
|||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
/// Read the current JSONRPC request from shared string buffer.
|
/// Read the current JSONRPC request from shared string buffer.
|
||||||
///
|
|
||||||
/// Return a `PyObjectDump*` representing the string.
|
|
||||||
/// You need to call `pkpy_delete` to free the returned `PyObjectDump*` later.
|
|
||||||
/// If the buffer is empty, return `nullptr`.
|
|
||||||
char* pkpy_tvm_read_jsonrpc_request(ThreadedVM* vm){
|
char* pkpy_tvm_read_jsonrpc_request(ThreadedVM* vm){
|
||||||
std::optional<_Str> s = vm->readSharedStr();
|
_Str s = vm->readSharedStr();
|
||||||
if(!s.has_value()) return nullptr;
|
return strdup(s.c_str());
|
||||||
return strdup(s.value().c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
/// Resume a suspended threaded virtual machine
|
/// Write a JSONRPC response to shared string buffer.
|
||||||
/// and put the given string into the shared string buffer.
|
void pkpy_tvm_jsonrpc_response(ThreadedVM* vm, const char* value){
|
||||||
/// It is usually used for JSONRPC.
|
vm->jsonrpcResponse(value);
|
||||||
void pkpy_tvm_resume(ThreadedVM* vm, const char* value){
|
|
||||||
vm->resume(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
|
51
src/vm.h
51
src/vm.h
@ -40,7 +40,8 @@ protected:
|
|||||||
PyVar runFrame(Frame* frame){
|
PyVar runFrame(Frame* frame){
|
||||||
while(!frame->isCodeEnd()){
|
while(!frame->isCodeEnd()){
|
||||||
const ByteCode& byte = frame->readCode();
|
const ByteCode& byte = frame->readCode();
|
||||||
//printf("%s (%d) stack_size: %d\n", OP_NAMES[byte.op], byte.arg, frame->stackSize());
|
//printf("[%d] %s (%d)\n", frame->stackSize(), OP_NAMES[byte.op], byte.arg);
|
||||||
|
//printf("%s\n", frame->code->src->getLine(byte.line).c_str());
|
||||||
|
|
||||||
_checkStopFlag();
|
_checkStopFlag();
|
||||||
|
|
||||||
@ -466,8 +467,6 @@ public:
|
|||||||
obj = call(it->second, args);
|
obj = call(it->second, args);
|
||||||
}else{
|
}else{
|
||||||
obj = newObject(_callable, (_Int)-1);
|
obj = newObject(_callable, (_Int)-1);
|
||||||
}
|
|
||||||
if(obj->isType(_callable)){
|
|
||||||
PyVarOrNull init_fn = getAttr(obj, __init__, false);
|
PyVarOrNull init_fn = getAttr(obj, __init__, false);
|
||||||
if (init_fn != nullptr) call(init_fn, args);
|
if (init_fn != nullptr) call(init_fn, args);
|
||||||
}
|
}
|
||||||
@ -1082,21 +1081,11 @@ enum ThreadState {
|
|||||||
THREAD_FINISHED
|
THREAD_FINISHED
|
||||||
};
|
};
|
||||||
|
|
||||||
const _Str INPUT_JSONRPC_STR = "{\"method\": \"input\", \"params\": []}";
|
|
||||||
|
|
||||||
class ThreadedVM : public VM {
|
class ThreadedVM : public VM {
|
||||||
std::thread* _thread = nullptr;
|
std::thread* _thread = nullptr;
|
||||||
std::atomic<ThreadState> _state = THREAD_READY;
|
std::atomic<ThreadState> _state = THREAD_READY;
|
||||||
std::optional<_Str> _sharedStr = {};
|
_Str _sharedStr = ""_c;
|
||||||
|
|
||||||
PyVar jsonRpc(const _Str& _json){
|
|
||||||
_sharedStr = _json;
|
|
||||||
suspend();
|
|
||||||
std::optional<_Str> ret = readSharedStr();
|
|
||||||
if(ret.has_value()) return PyStr(ret.value());
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __deleteThread(){
|
void __deleteThread(){
|
||||||
if(_thread != nullptr){
|
if(_thread != nullptr){
|
||||||
if(_state == THREAD_RUNNING || _state == THREAD_SUSPENDED){
|
if(_state == THREAD_RUNNING || _state == THREAD_SUSPENDED){
|
||||||
@ -1109,20 +1098,14 @@ class ThreadedVM : public VM {
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
ThreadedVM(bool use_stdio) : VM(use_stdio) {
|
ThreadedVM(bool use_stdio) : VM(use_stdio) {
|
||||||
bindBuiltinFunc("jsonrpc", [](VM* vm, const pkpy::ArgList& args){
|
bindBuiltinFunc("__string_channel_call", [](VM* vm, const pkpy::ArgList& args){
|
||||||
ThreadedVM *tvm = dynamic_cast<ThreadedVM*>(vm);
|
vm->__checkArgSize(args, 1);
|
||||||
if(tvm == nullptr) UNREACHABLE();
|
_Str data = vm->PyStr_AS_C(args[0]);
|
||||||
tvm->__checkArgSize(args, 1);
|
|
||||||
tvm->__checkType(args[0], vm->builtins->attribs["dict"_c]);
|
|
||||||
_Str _json = tvm->PyStr_AS_C(tvm->asJson(args[0]));
|
|
||||||
return tvm->jsonRpc(_json);
|
|
||||||
});
|
|
||||||
|
|
||||||
bindBuiltinFunc("input", [](VM* vm, const pkpy::ArgList& args) {
|
ThreadedVM* tvm = (ThreadedVM*)vm;
|
||||||
ThreadedVM *tvm = dynamic_cast<ThreadedVM*>(vm);
|
tvm->_sharedStr = data;
|
||||||
if(tvm == nullptr) UNREACHABLE();
|
tvm->suspend();
|
||||||
tvm->__checkArgSize(args, 0);
|
return tvm->PyStr(tvm->readSharedStr());
|
||||||
return tvm->jsonRpc(INPUT_JSONRPC_STR);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1136,9 +1119,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<_Str> readSharedStr(){
|
_Str readSharedStr(){
|
||||||
std::optional<_Str> copy = _sharedStr;
|
_Str copy = _sharedStr;
|
||||||
_sharedStr = {};
|
_sharedStr = ""_c;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1148,14 +1131,10 @@ public:
|
|||||||
return _state;
|
return _state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resume(const char* value=nullptr){
|
void jsonrpcResponse(const char* value){
|
||||||
if(_state != THREAD_SUSPENDED) UNREACHABLE();
|
if(_state != THREAD_SUSPENDED) UNREACHABLE();
|
||||||
_state = THREAD_RUNNING;
|
_state = THREAD_RUNNING;
|
||||||
if(value == nullptr){
|
_sharedStr = _Str(value);
|
||||||
_sharedStr = {};
|
|
||||||
}else{
|
|
||||||
_sharedStr = _Str(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void execAsync(const _Code& code) override {
|
void execAsync(const _Code& code) override {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user