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 <queue>
#include <iomanip> #include <iomanip>
#include <map> #include <map>
#include <optional>
#include <thread> #include <thread>
#include <atomic> #include <atomic>

View File

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

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

View File

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

View File

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

View File

@ -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,20 +1081,10 @@ 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){
@ -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 {