mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
up
This commit is contained in:
parent
0e56b25b0d
commit
a4c2cc5605
126
src/codeobject.h
126
src/codeobject.h
@ -27,6 +27,44 @@ _Str pad(const _Str& s, const int n){
|
|||||||
return s + std::string(n - s.size(), ' ');
|
return s + std::string(n - s.size(), ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CodeBlockType {
|
||||||
|
NO_BLOCK,
|
||||||
|
FOR_LOOP,
|
||||||
|
CONTEXT_MANAGER,
|
||||||
|
TRY_EXCEPT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CodeBlock {
|
||||||
|
CodeBlockType type;
|
||||||
|
std::vector<int> id;
|
||||||
|
int parent; // parent index in co_blocks
|
||||||
|
|
||||||
|
std::string toString() const {
|
||||||
|
if(parent == -1) return "";
|
||||||
|
std::string s = "[";
|
||||||
|
for(int i = 0; i < id.size(); i++){
|
||||||
|
s += std::to_string(id[i]);
|
||||||
|
if(i != id.size()-1) s += "-";
|
||||||
|
}
|
||||||
|
s += ": ";
|
||||||
|
s += std::to_string(type);
|
||||||
|
s += "]";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const std::vector<int>& other) const {
|
||||||
|
return id == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const std::vector<int>& other) const {
|
||||||
|
return id != other;
|
||||||
|
}
|
||||||
|
|
||||||
|
int depth() const {
|
||||||
|
return id.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct CodeObject {
|
struct CodeObject {
|
||||||
_Source src;
|
_Source src;
|
||||||
_Str name;
|
_Str name;
|
||||||
@ -45,48 +83,32 @@ struct CodeObject {
|
|||||||
std::vector<std::pair<_Str, NameScope>> co_names;
|
std::vector<std::pair<_Str, NameScope>> co_names;
|
||||||
std::vector<_Str> co_global_names;
|
std::vector<_Str> co_global_names;
|
||||||
|
|
||||||
std::vector<std::vector<int>> co_loops = {{}};
|
std::vector<CodeBlock> co_blocks = { CodeBlock{NO_BLOCK, {}, -1} };
|
||||||
int _currLoopIndex = 0;
|
|
||||||
|
|
||||||
std::string getBlockStr(int block){
|
// tmp variables
|
||||||
std::vector<int> loopId = co_loops[block];
|
int _currBlockIndex = 0;
|
||||||
std::string s = "";
|
|
||||||
for(int i=0; i<loopId.size(); i++){
|
void __enterBlock(CodeBlockType type){
|
||||||
s += std::to_string(loopId[i]);
|
const CodeBlock& currBlock = co_blocks[_currBlockIndex];
|
||||||
if(i != loopId.size()-1) s += "-";
|
std::vector<int> copy(currBlock.id);
|
||||||
|
copy.push_back(-1);
|
||||||
|
int t = 0;
|
||||||
|
while(true){
|
||||||
|
copy[copy.size()-1] = t;
|
||||||
|
auto it = std::find(co_blocks.begin(), co_blocks.end(), copy);
|
||||||
|
if(it == co_blocks.end()) break;
|
||||||
|
t++;
|
||||||
}
|
}
|
||||||
return s;
|
co_blocks.push_back(CodeBlock{type, copy, _currBlockIndex});
|
||||||
|
_currBlockIndex = co_blocks.size()-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __enterLoop(int depth){
|
void __exitBlock(){
|
||||||
const std::vector<int>& prevLoopId = co_loops[_currLoopIndex];
|
_currBlockIndex = co_blocks[_currBlockIndex].parent;
|
||||||
if(depth - prevLoopId.size() == 1){
|
if(_currBlockIndex < 0) UNREACHABLE();
|
||||||
std::vector<int> copy = prevLoopId;
|
|
||||||
copy.push_back(0);
|
|
||||||
int t = 0;
|
|
||||||
while(true){
|
|
||||||
copy[copy.size()-1] = t;
|
|
||||||
auto it = std::find(co_loops.begin(), co_loops.end(), copy);
|
|
||||||
if(it == co_loops.end()) break;
|
|
||||||
t++;
|
|
||||||
}
|
|
||||||
co_loops.push_back(copy);
|
|
||||||
}else{
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
_currLoopIndex = co_loops.size()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __exitLoop(){
|
|
||||||
std::vector<int> copy = co_loops[_currLoopIndex];
|
|
||||||
copy.pop_back();
|
|
||||||
auto it = std::find(co_loops.begin(), co_loops.end(), copy);
|
|
||||||
if(it == co_loops.end()) UNREACHABLE();
|
|
||||||
_currLoopIndex = it - co_loops.begin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for goto use
|
// for goto use
|
||||||
// note: some opcodes moves the bytecode, such as listcomp
|
|
||||||
// goto/label should be put at toplevel statements
|
// goto/label should be put at toplevel statements
|
||||||
emhash8::HashMap<_Str, int> co_labels;
|
emhash8::HashMap<_Str, int> co_labels;
|
||||||
|
|
||||||
@ -125,7 +147,7 @@ public:
|
|||||||
PyVar _module;
|
PyVar _module;
|
||||||
PyVarDict f_locals;
|
PyVarDict f_locals;
|
||||||
|
|
||||||
inline PyVarDict copy_f_locals(){
|
inline PyVarDict copy_f_locals() const {
|
||||||
return f_locals;
|
return f_locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,27 +216,25 @@ public:
|
|||||||
this->ip += i;
|
this->ip += i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jumpAbsoluteSafe(int i){
|
void jumpAbsoluteSafe(int target){
|
||||||
const ByteCode& prev = code->co_code[this->ip];
|
const ByteCode& prev = code->co_code[this->ip];
|
||||||
const std::vector<int> prevLoopId = code->co_loops[prev.block];
|
int i = prev.block;
|
||||||
this->ip = i;
|
this->ip = target;
|
||||||
if(isCodeEnd()){
|
if(isCodeEnd()){
|
||||||
for(int i=0; i<prevLoopId.size(); i++) __pop();
|
while(i>=0){
|
||||||
return;
|
if(code->co_blocks[i].type == FOR_LOOP) __pop();
|
||||||
}
|
i = code->co_blocks[i].parent;
|
||||||
const ByteCode& next = code->co_code[i];
|
|
||||||
const std::vector<int> nextLoopId = code->co_loops[next.block];
|
|
||||||
int sizeDelta = prevLoopId.size() - nextLoopId.size();
|
|
||||||
if(sizeDelta < 0){
|
|
||||||
throw std::runtime_error("invalid jump from " + code->getBlockStr(prev.block) + " to " + code->getBlockStr(next.block));
|
|
||||||
}else{
|
|
||||||
for(int i=0; i<nextLoopId.size(); i++){
|
|
||||||
if(nextLoopId[i] != prevLoopId[i]){
|
|
||||||
throw std::runtime_error("invalid jump from " + code->getBlockStr(prev.block) + " to " + code->getBlockStr(next.block));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
const ByteCode& next = code->co_code[target];
|
||||||
|
while(i>=0 && i!=next.block){
|
||||||
|
if(code->co_blocks[i].type == FOR_LOOP) __pop();
|
||||||
|
i = code->co_blocks[i].parent;
|
||||||
|
}
|
||||||
|
if(i!=next.block) throw std::runtime_error(
|
||||||
|
"invalid jump from " + code->co_blocks[prev.block].toString() + " to " + code->co_blocks[next.block].toString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for(int i=0; i<sizeDelta; i++) __pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pkpy::ArgList popNValuesReversed(VM* vm, int n){
|
pkpy::ArgList popNValuesReversed(VM* vm, int n){
|
||||||
|
@ -575,7 +575,7 @@ __LISTCOMP:
|
|||||||
patchJump(_skipPatch);
|
patchJump(_skipPatch);
|
||||||
|
|
||||||
emitCode(OP_GET_ITER);
|
emitCode(OP_GET_ITER);
|
||||||
Loop& loop = enterLoop();
|
Loop& loop = enterLoop(); getCode()->__enterBlock(FOR_LOOP);
|
||||||
int patch = emitCode(OP_FOR_ITER);
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
|
|
||||||
if(_cond_end_return != -1) { // there is an if condition
|
if(_cond_end_return != -1) { // there is an if condition
|
||||||
@ -594,7 +594,7 @@ __LISTCOMP:
|
|||||||
|
|
||||||
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
||||||
patchJump(patch);
|
patchJump(patch);
|
||||||
exitLoop();
|
exitLoop(); getCode()->__exitBlock();
|
||||||
matchNewLines(mode()==SINGLE_MODE);
|
matchNewLines(mode()==SINGLE_MODE);
|
||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
}
|
}
|
||||||
@ -710,7 +710,7 @@ __LISTCOMP:
|
|||||||
int emitCode(Opcode opcode, int arg=-1) {
|
int emitCode(Opcode opcode, int arg=-1) {
|
||||||
int line = parser->previous.line;
|
int line = parser->previous.line;
|
||||||
getCode()->co_code.push_back(
|
getCode()->co_code.push_back(
|
||||||
ByteCode{(uint8_t)opcode, arg, (uint16_t)line, (uint16_t)getCode()->_currLoopIndex}
|
ByteCode{(uint8_t)opcode, arg, (uint16_t)line, (uint16_t)getCode()->_currBlockIndex}
|
||||||
);
|
);
|
||||||
return getCode()->co_code.size() - 1;
|
return getCode()->co_code.size() - 1;
|
||||||
}
|
}
|
||||||
@ -818,14 +818,12 @@ __LISTCOMP:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Loop& enterLoop(){
|
Loop& enterLoop(){
|
||||||
getCode()->__enterLoop(loops.size()+1);
|
|
||||||
Loop lp((int)getCode()->co_code.size());
|
Loop lp((int)getCode()->co_code.size());
|
||||||
loops.push(lp);
|
loops.push(lp);
|
||||||
return loops.top();
|
return loops.top();
|
||||||
}
|
}
|
||||||
|
|
||||||
void exitLoop(){
|
void exitLoop(){
|
||||||
getCode()->__exitLoop();
|
|
||||||
Loop& lp = loops.top();
|
Loop& lp = loops.top();
|
||||||
for(int addr : lp.breaks) patchJump(addr);
|
for(int addr : lp.breaks) patchJump(addr);
|
||||||
loops.pop();
|
loops.pop();
|
||||||
@ -851,14 +849,14 @@ __LISTCOMP:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void compileForLoop() {
|
void compileForLoop() {
|
||||||
EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE();
|
EXPR_FOR_VARS();consume(TK("in")); EXPR_TUPLE();
|
||||||
emitCode(OP_GET_ITER);
|
emitCode(OP_GET_ITER);
|
||||||
Loop& loop = enterLoop();
|
Loop& loop = enterLoop(); getCode()->__enterBlock(FOR_LOOP);
|
||||||
int patch = emitCode(OP_FOR_ITER);
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
compileBlockBody();
|
compileBlockBody();
|
||||||
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
||||||
patchJump(patch);
|
patchJump(patch);
|
||||||
exitLoop();
|
exitLoop(); getCode()->__exitBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void compileStatement() {
|
void compileStatement() {
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
#ifdef OPCODE
|
#ifdef OPCODE
|
||||||
|
|
||||||
|
// Do nothing
|
||||||
OPCODE(NO_OP)
|
OPCODE(NO_OP)
|
||||||
|
|
||||||
|
// This op is a placeholder that should never be executed
|
||||||
OPCODE(DELETED_OP)
|
OPCODE(DELETED_OP)
|
||||||
|
|
||||||
|
// Load a constant from the `co_consts`
|
||||||
|
// ARG: array index
|
||||||
OPCODE(LOAD_CONST)
|
OPCODE(LOAD_CONST)
|
||||||
|
|
||||||
OPCODE(IMPORT_NAME)
|
OPCODE(IMPORT_NAME)
|
||||||
OPCODE(PRINT_EXPR)
|
OPCODE(PRINT_EXPR)
|
||||||
OPCODE(POP_TOP)
|
OPCODE(POP_TOP)
|
||||||
@ -67,4 +74,6 @@ OPCODE(WITH_EXIT)
|
|||||||
|
|
||||||
OPCODE(JUMP_RELATIVE)
|
OPCODE(JUMP_RELATIVE)
|
||||||
|
|
||||||
|
OPCODE(RAISE_VARARGS)
|
||||||
|
|
||||||
#endif
|
#endif
|
10
src/vm.h
10
src/vm.h
@ -136,7 +136,6 @@ protected:
|
|||||||
setAttr(fn, __module__, frame->_module);
|
setAttr(fn, __module__, frame->_module);
|
||||||
setAttr(cls, f->name, fn);
|
setAttr(cls, f->name, fn);
|
||||||
}
|
}
|
||||||
// frame->f_globals()[clsName] = cls;
|
|
||||||
} break;
|
} break;
|
||||||
case OP_RETURN_VALUE: return frame->popValue(this);
|
case OP_RETURN_VALUE: return frame->popValue(this);
|
||||||
case OP_PRINT_EXPR:
|
case OP_PRINT_EXPR:
|
||||||
@ -548,9 +547,9 @@ public:
|
|||||||
try {
|
try {
|
||||||
_Code code = compile(source, filename, mode);
|
_Code code = compile(source, filename, mode);
|
||||||
|
|
||||||
// if(filename != "<builtins>"){
|
if(filename != "<builtins>"){
|
||||||
// std::cout << disassemble(code) << std::endl;
|
std::cout << disassemble(code) << std::endl;
|
||||||
// }
|
}
|
||||||
|
|
||||||
return _exec(code, _module, {});
|
return _exec(code, _module, {});
|
||||||
}catch (const _Error& e){
|
}catch (const _Error& e){
|
||||||
@ -774,7 +773,6 @@ public:
|
|||||||
int prev_line = -1;
|
int prev_line = -1;
|
||||||
for(int i=0; i<code->co_code.size(); i++){
|
for(int i=0; i<code->co_code.size(); i++){
|
||||||
const ByteCode& byte = code->co_code[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);
|
_Str line = std::to_string(byte.line);
|
||||||
if(byte.line == prev_line) line = "";
|
if(byte.line == prev_line) line = "";
|
||||||
else{
|
else{
|
||||||
@ -784,7 +782,7 @@ public:
|
|||||||
ss << pad(line, 12) << " " << pad(std::to_string(i), 3);
|
ss << pad(line, 12) << " " << pad(std::to_string(i), 3);
|
||||||
ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
|
ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
|
||||||
ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
|
ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
|
||||||
ss << '[' << code->getBlockStr(byte.block) << ']';
|
ss << code->co_blocks[byte.block].toString();
|
||||||
if(i != code->co_code.size() - 1) ss << '\n';
|
if(i != code->co_code.size() - 1) ss << '\n';
|
||||||
}
|
}
|
||||||
_StrStream consts;
|
_StrStream consts;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user