fix some errors

This commit is contained in:
blueloveTH 2022-12-03 22:17:29 +08:00
parent 9c16aefda3
commit 9b9e1b9fd0
6 changed files with 62 additions and 66 deletions

View File

@ -17,7 +17,6 @@
#include <queue>
#include <iomanip>
#include <map>
#include <optional>
#include <thread>
#include <atomic>

View File

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

View File

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

View File

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

View File

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

View File

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