mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
fix some errors
This commit is contained in:
parent
9c16aefda3
commit
9b9e1b9fd0
@ -17,7 +17,6 @@
|
||||
#include <queue>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
@ -229,6 +229,28 @@ def sorted(iterable, key=None, reverse=False):
|
||||
b[i], b[j] = b[j], b[i]
|
||||
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:
|
||||
def __init__(self, path, mode):
|
||||
assert type(path) is str
|
||||
@ -236,19 +258,19 @@ class FileIO:
|
||||
assert mode in ['r', 'w']
|
||||
self.path = path
|
||||
self.mode = mode
|
||||
self.fp = jsonrpc({"method": "fopen", "params": [path, mode]})
|
||||
self.fp = jsonrpc('fopen', [path, mode])
|
||||
|
||||
def read(self):
|
||||
assert self.mode == 'r'
|
||||
return jsonrpc({"method": "fread", "params": [self.fp]})
|
||||
return jsonrpc('fread', [self.fp])
|
||||
|
||||
def write(self, s):
|
||||
assert self.mode == 'w'
|
||||
assert type(s) is str
|
||||
jsonrpc({"method": "fwrite", "params": [self.fp, s]})
|
||||
jsonrpc('fwrite', [self.fp, s])
|
||||
|
||||
def close(self):
|
||||
jsonrpc({"method": "fclose", "params": [self.fp]})
|
||||
jsonrpc('fclose', [self.fp])
|
||||
|
||||
def __enter__(self):
|
||||
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);
|
||||
if(!noThrow) return compiler.__fillCode();
|
||||
try{
|
||||
return compiler.__fillCode();
|
||||
}catch(std::exception& e){
|
||||
|
@ -43,11 +43,15 @@ void _tvm_dispatch(ThreadedVM* vm){
|
||||
while(pkpy_tvm_get_state(vm) != THREAD_FINISHED){
|
||||
if(pkpy_tvm_get_state(vm) == THREAD_SUSPENDED){
|
||||
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){
|
||||
std::string 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{
|
||||
std::cout << "unknown jsonrpc call" << 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->__checkArgSize(args, 1);
|
||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||
_Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE);
|
||||
if(code == nullptr) return vm->None;
|
||||
_Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE, false);
|
||||
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->__checkArgSize(args, 1);
|
||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||
_Code code = compile(vm, expr.c_str(), "<json>", JSON_MODE);
|
||||
if(code == nullptr) return vm->None;
|
||||
_Code code = compile(vm, expr.c_str(), "<json>", JSON_MODE, false);
|
||||
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{
|
||||
public:
|
||||
virtual ~_PkExported() = default;
|
||||
virtual void* get() = 0;
|
||||
};
|
||||
|
||||
static std::vector<_PkExported*> _pkLookupTable;
|
||||
|
||||
template<typename T>
|
||||
class PkExported : public _PkExported{
|
||||
T* _ptr;
|
||||
@ -763,13 +761,13 @@ extern "C" {
|
||||
|
||||
void __vm_init(VM* vm){
|
||||
__initializeBuiltinFunctions(vm);
|
||||
_Code code = compile(vm, __BUILTINS_CODE, "<builtins>");
|
||||
if(code == nullptr) exit(1);
|
||||
vm->_exec(code, vm->builtins, {});
|
||||
|
||||
__addModuleSys(vm);
|
||||
__addModuleTime(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);
|
||||
}
|
||||
|
||||
@ -830,22 +828,15 @@ extern "C" {
|
||||
|
||||
__EXPORT
|
||||
/// 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){
|
||||
std::optional<_Str> s = vm->readSharedStr();
|
||||
if(!s.has_value()) return nullptr;
|
||||
return strdup(s.value().c_str());
|
||||
_Str s = vm->readSharedStr();
|
||||
return strdup(s.c_str());
|
||||
}
|
||||
|
||||
__EXPORT
|
||||
/// Resume a suspended threaded virtual machine
|
||||
/// and put the given string into the shared string buffer.
|
||||
/// It is usually used for JSONRPC.
|
||||
void pkpy_tvm_resume(ThreadedVM* vm, const char* value){
|
||||
vm->resume(value);
|
||||
/// Write a JSONRPC response to shared string buffer.
|
||||
void pkpy_tvm_jsonrpc_response(ThreadedVM* vm, const char* value){
|
||||
vm->jsonrpcResponse(value);
|
||||
}
|
||||
|
||||
__EXPORT
|
||||
|
49
src/vm.h
49
src/vm.h
@ -40,7 +40,8 @@ protected:
|
||||
PyVar runFrame(Frame* frame){
|
||||
while(!frame->isCodeEnd()){
|
||||
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();
|
||||
|
||||
@ -466,8 +467,6 @@ public:
|
||||
obj = call(it->second, args);
|
||||
}else{
|
||||
obj = newObject(_callable, (_Int)-1);
|
||||
}
|
||||
if(obj->isType(_callable)){
|
||||
PyVarOrNull init_fn = getAttr(obj, __init__, false);
|
||||
if (init_fn != nullptr) call(init_fn, args);
|
||||
}
|
||||
@ -1082,20 +1081,10 @@ enum ThreadState {
|
||||
THREAD_FINISHED
|
||||
};
|
||||
|
||||
const _Str INPUT_JSONRPC_STR = "{\"method\": \"input\", \"params\": []}";
|
||||
|
||||
class ThreadedVM : public VM {
|
||||
std::thread* _thread = nullptr;
|
||||
std::atomic<ThreadState> _state = THREAD_READY;
|
||||
std::optional<_Str> _sharedStr = {};
|
||||
|
||||
PyVar jsonRpc(const _Str& _json){
|
||||
_sharedStr = _json;
|
||||
suspend();
|
||||
std::optional<_Str> ret = readSharedStr();
|
||||
if(ret.has_value()) return PyStr(ret.value());
|
||||
return None;
|
||||
}
|
||||
_Str _sharedStr = ""_c;
|
||||
|
||||
void __deleteThread(){
|
||||
if(_thread != nullptr){
|
||||
@ -1109,20 +1098,14 @@ class ThreadedVM : public VM {
|
||||
}
|
||||
public:
|
||||
ThreadedVM(bool use_stdio) : VM(use_stdio) {
|
||||
bindBuiltinFunc("jsonrpc", [](VM* vm, const pkpy::ArgList& args){
|
||||
ThreadedVM *tvm = dynamic_cast<ThreadedVM*>(vm);
|
||||
if(tvm == nullptr) UNREACHABLE();
|
||||
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("__string_channel_call", [](VM* vm, const pkpy::ArgList& args){
|
||||
vm->__checkArgSize(args, 1);
|
||||
_Str data = vm->PyStr_AS_C(args[0]);
|
||||
|
||||
bindBuiltinFunc("input", [](VM* vm, const pkpy::ArgList& args) {
|
||||
ThreadedVM *tvm = dynamic_cast<ThreadedVM*>(vm);
|
||||
if(tvm == nullptr) UNREACHABLE();
|
||||
tvm->__checkArgSize(args, 0);
|
||||
return tvm->jsonRpc(INPUT_JSONRPC_STR);
|
||||
ThreadedVM* tvm = (ThreadedVM*)vm;
|
||||
tvm->_sharedStr = data;
|
||||
tvm->suspend();
|
||||
return tvm->PyStr(tvm->readSharedStr());
|
||||
});
|
||||
}
|
||||
|
||||
@ -1136,9 +1119,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<_Str> readSharedStr(){
|
||||
std::optional<_Str> copy = _sharedStr;
|
||||
_sharedStr = {};
|
||||
_Str readSharedStr(){
|
||||
_Str copy = _sharedStr;
|
||||
_sharedStr = ""_c;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -1148,15 +1131,11 @@ public:
|
||||
return _state;
|
||||
}
|
||||
|
||||
void resume(const char* value=nullptr){
|
||||
void jsonrpcResponse(const char* value){
|
||||
if(_state != THREAD_SUSPENDED) UNREACHABLE();
|
||||
_state = THREAD_RUNNING;
|
||||
if(value == nullptr){
|
||||
_sharedStr = {};
|
||||
}else{
|
||||
_sharedStr = _Str(value);
|
||||
}
|
||||
}
|
||||
|
||||
void execAsync(const _Code& code) override {
|
||||
if(_state != THREAD_READY) UNREACHABLE();
|
||||
|
Loading…
x
Reference in New Issue
Block a user