mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 21:10:19 +00:00
some change
This commit is contained in:
parent
4e40487df7
commit
af582c7bc7
@ -37,7 +37,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PK_VERSION "0.6.1"
|
#define PK_VERSION "0.6.2"
|
||||||
|
|
||||||
//#define PKPY_NO_TYPE_CHECK
|
//#define PKPY_NO_TYPE_CHECK
|
||||||
//#define PKPY_NO_INDEX_CHECK
|
//#define PKPY_NO_INDEX_CHECK
|
@ -73,51 +73,6 @@ struct CodeObject {
|
|||||||
co_consts.push_back(v);
|
co_consts.push_back(v);
|
||||||
return co_consts.size() - 1;
|
return co_consts.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __moveToEnd(int start, int end){
|
|
||||||
auto _start = co_code.begin() + start;
|
|
||||||
auto _end = co_code.begin() + end;
|
|
||||||
co_code.insert(co_code.end(), _start, _end);
|
|
||||||
for(int i=start; i<end; i++) co_code[i].op = OP_DELETED_OP;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Str toString(){
|
|
||||||
_StrStream ss;
|
|
||||||
int prev_line = -1;
|
|
||||||
for(int i=0; i<co_code.size(); i++){
|
|
||||||
const ByteCode& byte = co_code[i];
|
|
||||||
if(byte.op == OP_NO_OP) continue;
|
|
||||||
_Str line = std::to_string(byte.line);
|
|
||||||
if(byte.line == prev_line) line = "";
|
|
||||||
else{
|
|
||||||
if(prev_line != -1) ss << "\n";
|
|
||||||
prev_line = byte.line;
|
|
||||||
}
|
|
||||||
ss << pad(line, 12) << " " << pad(std::to_string(i), 3);
|
|
||||||
ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
|
|
||||||
ss << (byte.arg == -1 ? "" : std::to_string(byte.arg));
|
|
||||||
if(i != co_code.size() - 1) ss << '\n';
|
|
||||||
}
|
|
||||||
_StrStream consts;
|
|
||||||
consts << "co_consts: ";
|
|
||||||
for(int i=0; i<co_consts.size(); i++){
|
|
||||||
consts << UNION_TP_NAME(co_consts[i]);
|
|
||||||
if(i != co_consts.size() - 1) consts << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
_StrStream names;
|
|
||||||
names << "co_names: ";
|
|
||||||
for(int i=0; i<co_names.size(); i++){
|
|
||||||
names << co_names[i].first;
|
|
||||||
if(i != co_names.size() - 1) names << ", ";
|
|
||||||
}
|
|
||||||
ss << '\n' << consts.str() << '\n' << names.str() << '\n';
|
|
||||||
// for(int i=0; i<co_consts.size(); i++){
|
|
||||||
// auto fn = std::get_if<_Func>(&co_consts[i]->_native);
|
|
||||||
// if(fn) ss << '\n' << (*fn)->code->name << ":\n" << (*fn)->code->toString();
|
|
||||||
// }
|
|
||||||
return _Str(ss.str());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Frame {
|
class Frame {
|
||||||
@ -126,12 +81,10 @@ private:
|
|||||||
int ip = 0;
|
int ip = 0;
|
||||||
std::stack<int> forLoops; // record the FOR_ITER bytecode index
|
std::stack<int> forLoops; // record the FOR_ITER bytecode index
|
||||||
public:
|
public:
|
||||||
const CodeObject* code;
|
const _Code code;
|
||||||
PyVar _module;
|
PyVar _module;
|
||||||
PyVarDict f_locals;
|
PyVarDict f_locals;
|
||||||
|
|
||||||
uint64_t id;
|
|
||||||
|
|
||||||
inline PyVarDict copy_f_locals(){
|
inline PyVarDict copy_f_locals(){
|
||||||
return f_locals;
|
return f_locals;
|
||||||
}
|
}
|
||||||
@ -140,11 +93,8 @@ public:
|
|||||||
return _module->attribs;
|
return _module->attribs;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame(const CodeObject* code, PyVar _module, PyVarDict&& locals)
|
Frame(const _Code code, PyVar _module, PyVarDict&& locals)
|
||||||
: code(code), _module(_module), f_locals(std::move(locals)) {
|
: code(code), _module(_module), f_locals(std::move(locals)) {
|
||||||
|
|
||||||
static thread_local uint64_t frame_id = 1;
|
|
||||||
id = frame_id++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ByteCode& readCode() {
|
inline const ByteCode& readCode() {
|
||||||
@ -207,16 +157,19 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void jump(int i){
|
inline void jumpAbsolute(int i){
|
||||||
this->ip = i;
|
this->ip = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void safeJump(int i){
|
inline void jumpRelative(int i){
|
||||||
this->ip = i;
|
this->ip += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __safeJumpClean(){
|
||||||
while(!forLoops.empty()){
|
while(!forLoops.empty()){
|
||||||
int start = forLoops.top();
|
int start = forLoops.top();
|
||||||
int end = code->co_code[start].arg;
|
int end = code->co_code[start].arg;
|
||||||
if(i < start || i >= end){
|
if(ip < start || ip >= end){
|
||||||
//printf("%d <- [%d, %d)\n", i, start, end);
|
//printf("%d <- [%d, %d)\n", i, start, end);
|
||||||
__pop(); // pop the iterator
|
__pop(); // pop the iterator
|
||||||
forLoops.pop();
|
forLoops.pop();
|
||||||
|
@ -557,6 +557,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
__LISTCOMP:
|
__LISTCOMP:
|
||||||
|
int _body_end_return = emitCode(OP_JUMP_ABSOLUTE, -1);
|
||||||
int _body_end = getCode()->co_code.size();
|
int _body_end = getCode()->co_code.size();
|
||||||
getCode()->co_code[_patch].op = OP_JUMP_ABSOLUTE;
|
getCode()->co_code[_patch].op = OP_JUMP_ABSOLUTE;
|
||||||
getCode()->co_code[_patch].arg = _body_end;
|
getCode()->co_code[_patch].arg = _body_end;
|
||||||
@ -566,22 +567,28 @@ __LISTCOMP:
|
|||||||
|
|
||||||
int _skipPatch = emitCode(OP_JUMP_ABSOLUTE);
|
int _skipPatch = emitCode(OP_JUMP_ABSOLUTE);
|
||||||
int _cond_start = getCode()->co_code.size();
|
int _cond_start = getCode()->co_code.size();
|
||||||
if(match(TK("if"))) EXPR_TUPLE();
|
int _cond_end_return = -1;
|
||||||
int _cond_end = getCode()->co_code.size();
|
if(match(TK("if"))) {
|
||||||
|
EXPR_TUPLE();
|
||||||
|
_cond_end_return = emitCode(OP_JUMP_ABSOLUTE, -1);
|
||||||
|
}
|
||||||
patchJump(_skipPatch);
|
patchJump(_skipPatch);
|
||||||
|
|
||||||
emitCode(OP_GET_ITER);
|
emitCode(OP_GET_ITER);
|
||||||
Loop& loop = enterLoop();
|
Loop& loop = enterLoop();
|
||||||
int patch = emitCode(OP_FOR_ITER);
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
|
|
||||||
if(_cond_end != _cond_start) { // there is an if condition
|
if(_cond_end_return != -1) { // there is an if condition
|
||||||
getCode()->__moveToEnd(_cond_start, _cond_end);
|
emitCode(OP_JUMP_ABSOLUTE, _cond_start);
|
||||||
|
patchJump(_cond_end_return);
|
||||||
int ifpatch = emitCode(OP_POP_JUMP_IF_FALSE);
|
int ifpatch = emitCode(OP_POP_JUMP_IF_FALSE);
|
||||||
getCode()->__moveToEnd(_body_start, _body_end);
|
emitCode(OP_JUMP_ABSOLUTE, _body_start);
|
||||||
|
patchJump(_body_end_return);
|
||||||
emitCode(OP_LIST_APPEND);
|
emitCode(OP_LIST_APPEND);
|
||||||
patchJump(ifpatch);
|
patchJump(ifpatch);
|
||||||
}else{
|
}else{
|
||||||
getCode()->__moveToEnd(_body_start, _body_end);
|
emitCode(OP_JUMP_ABSOLUTE, _body_start);
|
||||||
|
patchJump(_body_end_return);
|
||||||
emitCode(OP_LIST_APPEND);
|
emitCode(OP_LIST_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "pocketpy.h"
|
#include "pocketpy.h"
|
||||||
|
|
||||||
//#define PK_DEBUG_TIME
|
//#define PK_DEBUG_TIME
|
||||||
#define PK_DEBUG_THREADED
|
//#define PK_DEBUG_THREADED
|
||||||
|
|
||||||
struct Timer{
|
struct Timer{
|
||||||
const char* title;
|
const char* title;
|
||||||
@ -85,7 +85,6 @@ int main(int argc, char** argv){
|
|||||||
std::string src((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
std::string src((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
ThreadedVM* vm = pkpy_new_tvm(true);
|
ThreadedVM* vm = pkpy_new_tvm(true);
|
||||||
//std::cout << code->toString() << std::endl;
|
|
||||||
#ifdef PK_DEBUG_THREADED
|
#ifdef PK_DEBUG_THREADED
|
||||||
Timer("Running time").run([=]{
|
Timer("Running time").run([=]{
|
||||||
vm->execAsync(src.c_str(), filename, EXEC_MODE);
|
vm->execAsync(src.c_str(), filename, EXEC_MODE);
|
||||||
|
@ -65,4 +65,6 @@ OPCODE(GOTO)
|
|||||||
OPCODE(WITH_ENTER)
|
OPCODE(WITH_ENTER)
|
||||||
OPCODE(WITH_EXIT)
|
OPCODE(WITH_EXIT)
|
||||||
|
|
||||||
|
OPCODE(JUMP_RELATIVE)
|
||||||
|
|
||||||
#endif
|
#endif
|
69
src/vm.h
69
src/vm.h
@ -193,7 +193,7 @@ protected:
|
|||||||
frame->push(PyBool(!PyBool_AS_C(obj_bool)));
|
frame->push(PyBool(!PyBool_AS_C(obj_bool)));
|
||||||
} break;
|
} break;
|
||||||
case OP_POP_JUMP_IF_FALSE:
|
case OP_POP_JUMP_IF_FALSE:
|
||||||
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
|
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jumpAbsolute(byte.arg);
|
||||||
break;
|
break;
|
||||||
case OP_LOAD_NONE: frame->push(None); break;
|
case OP_LOAD_NONE: frame->push(None); break;
|
||||||
case OP_LOAD_TRUE: frame->push(True); break;
|
case OP_LOAD_TRUE: frame->push(True); break;
|
||||||
@ -246,8 +246,9 @@ protected:
|
|||||||
if(ret == __py2py_call_signal) return ret;
|
if(ret == __py2py_call_signal) return ret;
|
||||||
frame->push(std::move(ret));
|
frame->push(std::move(ret));
|
||||||
} break;
|
} break;
|
||||||
case OP_JUMP_ABSOLUTE: frame->jump(byte.arg); break;
|
case OP_JUMP_ABSOLUTE: frame->jumpAbsolute(byte.arg); break;
|
||||||
case OP_SAFE_JUMP_ABSOLUTE: frame->safeJump(byte.arg); break;
|
case OP_JUMP_RELATIVE: frame->jumpRelative(byte.arg); break;
|
||||||
|
case OP_SAFE_JUMP_ABSOLUTE: frame->jumpAbsolute(byte.arg); frame->__safeJumpClean(); break;
|
||||||
case OP_GOTO: {
|
case OP_GOTO: {
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
const _Str& label = PyStr_AS_C(obj);
|
const _Str& label = PyStr_AS_C(obj);
|
||||||
@ -255,7 +256,8 @@ protected:
|
|||||||
if(target == nullptr){
|
if(target == nullptr){
|
||||||
_error("KeyError", "label '" + label + "' not found");
|
_error("KeyError", "label '" + label + "' not found");
|
||||||
}
|
}
|
||||||
frame->safeJump(*target);
|
frame->jumpAbsolute(*target);
|
||||||
|
frame->__safeJumpClean();
|
||||||
} break;
|
} break;
|
||||||
case OP_GET_ITER:
|
case OP_GET_ITER:
|
||||||
{
|
{
|
||||||
@ -280,19 +282,20 @@ protected:
|
|||||||
PyRef_AS_C(it->var)->set(this, frame, it->next());
|
PyRef_AS_C(it->var)->set(this, frame, it->next());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
frame->safeJump(byte.arg);
|
frame->jumpAbsolute(byte.arg);
|
||||||
|
frame->__safeJumpClean();
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case OP_JUMP_IF_FALSE_OR_POP:
|
case OP_JUMP_IF_FALSE_OR_POP:
|
||||||
{
|
{
|
||||||
const PyVar expr = frame->topValue(this);
|
const PyVar expr = frame->topValue(this);
|
||||||
if(asBool(expr)==False) frame->jump(byte.arg);
|
if(asBool(expr)==False) frame->jumpAbsolute(byte.arg);
|
||||||
else frame->popValue(this);
|
else frame->popValue(this);
|
||||||
} break;
|
} break;
|
||||||
case OP_JUMP_IF_TRUE_OR_POP:
|
case OP_JUMP_IF_TRUE_OR_POP:
|
||||||
{
|
{
|
||||||
const PyVar expr = frame->topValue(this);
|
const PyVar expr = frame->topValue(this);
|
||||||
if(asBool(expr)==True) frame->jump(byte.arg);
|
if(asBool(expr)==True) frame->jumpAbsolute(byte.arg);
|
||||||
else frame->popValue(this);
|
else frame->popValue(this);
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_SLICE:
|
case OP_BUILD_SLICE:
|
||||||
@ -324,6 +327,7 @@ protected:
|
|||||||
frame->push(it->second);
|
frame->push(it->second);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
// TODO: goto inside with block is unsafe
|
||||||
case OP_WITH_ENTER: call(frame->popValue(this), __enter__); break;
|
case OP_WITH_ENTER: call(frame->popValue(this), __enter__); break;
|
||||||
case OP_WITH_EXIT: call(frame->popValue(this), __exit__); break;
|
case OP_WITH_EXIT: call(frame->popValue(this), __exit__); break;
|
||||||
default:
|
default:
|
||||||
@ -394,15 +398,6 @@ public:
|
|||||||
return asRepr(obj);
|
return asRepr(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame* __findFrame(uint64_t up_f_id){
|
|
||||||
for(auto it=callstack.crbegin(); it!=callstack.crend(); ++it){
|
|
||||||
uint64_t f_id = it->get()->id;
|
|
||||||
if(f_id == up_f_id) return it->get();
|
|
||||||
if(f_id < up_f_id) return nullptr;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame* topFrame(){
|
Frame* topFrame(){
|
||||||
if(callstack.size() == 0) UNREACHABLE();
|
if(callstack.size() == 0) UNREACHABLE();
|
||||||
return callstack.back().get();
|
return callstack.back().get();
|
||||||
@ -555,6 +550,11 @@ public:
|
|||||||
if(_module == nullptr) _module = _main;
|
if(_module == nullptr) _module = _main;
|
||||||
try {
|
try {
|
||||||
_Code code = compile(source, filename, mode);
|
_Code code = compile(source, filename, mode);
|
||||||
|
|
||||||
|
if(filename == "<stdin>"){
|
||||||
|
std::cout << disassemble(code) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return _exec(code, _module, {});
|
return _exec(code, _module, {});
|
||||||
}catch (const _Error& e){
|
}catch (const _Error& e){
|
||||||
*_stderr << e.what() << '\n';
|
*_stderr << e.what() << '\n';
|
||||||
@ -574,14 +574,13 @@ public:
|
|||||||
if(callstack.size() > maxRecursionDepth){
|
if(callstack.size() > maxRecursionDepth){
|
||||||
throw RuntimeError("RecursionError", "maximum recursion depth exceeded", _cleanErrorAndGetSnapshots());
|
throw RuntimeError("RecursionError", "maximum recursion depth exceeded", _cleanErrorAndGetSnapshots());
|
||||||
}
|
}
|
||||||
Frame* frame = new Frame(code.get(), _module, std::move(locals));
|
Frame* frame = new Frame(code, _module, std::move(locals));
|
||||||
callstack.emplace_back(pkpy::unique_ptr<Frame>(frame));
|
callstack.emplace_back(pkpy::unique_ptr<Frame>(frame));
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar _exec(const _Code& code, PyVar _module, PyVarDict&& locals){
|
PyVar _exec(_Code code, PyVar _module, PyVarDict&& locals){
|
||||||
Frame* frame = __pushNewFrame(code, _module, std::move(locals));
|
Frame* frame = __pushNewFrame(code, _module, std::move(locals));
|
||||||
if(code->mode() == SINGLE_MODE) frame->id = 0;
|
|
||||||
Frame* frameBase = frame;
|
Frame* frameBase = frame;
|
||||||
PyVar ret = nullptr;
|
PyVar ret = nullptr;
|
||||||
|
|
||||||
@ -773,6 +772,38 @@ public:
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Str disassemble(_Code code){
|
||||||
|
_StrStream ss;
|
||||||
|
int prev_line = -1;
|
||||||
|
for(int i=0; i<code->co_code.size(); i++){
|
||||||
|
const ByteCode& byte = code->co_code[i];
|
||||||
|
if(byte.op == OP_NO_OP || byte.op == OP_DELETED_OP) continue;
|
||||||
|
_Str line = std::to_string(byte.line);
|
||||||
|
if(byte.line == prev_line) line = "";
|
||||||
|
else{
|
||||||
|
if(prev_line != -1) ss << "\n";
|
||||||
|
prev_line = byte.line;
|
||||||
|
}
|
||||||
|
ss << pad(line, 12) << " " << pad(std::to_string(i), 3);
|
||||||
|
ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
|
||||||
|
ss << (byte.arg == -1 ? "" : std::to_string(byte.arg));
|
||||||
|
if(i != code->co_code.size() - 1) ss << '\n';
|
||||||
|
}
|
||||||
|
_StrStream consts;
|
||||||
|
consts << "co_consts: ";
|
||||||
|
consts << PyStr_AS_C(asRepr(PyList(code->co_consts)));
|
||||||
|
|
||||||
|
_StrStream names;
|
||||||
|
names << "co_names: ";
|
||||||
|
PyVarList list;
|
||||||
|
for(int i=0; i<code->co_names.size(); i++){
|
||||||
|
list.push_back(PyStr(code->co_names[i].first));
|
||||||
|
}
|
||||||
|
names << PyStr_AS_C(asRepr(PyList(list)));
|
||||||
|
ss << '\n' << consts.str() << '\n' << names.str() << '\n';
|
||||||
|
return _Str(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
// for quick access
|
// for quick access
|
||||||
PyVar _tp_object, _tp_type, _tp_int, _tp_float, _tp_bool, _tp_str;
|
PyVar _tp_object, _tp_type, _tp_int, _tp_float, _tp_bool, _tp_str;
|
||||||
PyVar _tp_list, _tp_tuple;
|
PyVar _tp_list, _tp_tuple;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user