This commit is contained in:
blueloveTH 2023-02-09 14:59:26 +08:00
parent 02f8ad43b0
commit 029e8a5624
3 changed files with 74 additions and 74 deletions

View File

@ -39,8 +39,8 @@ enum CodeBlockType {
struct CodeBlock { struct CodeBlock {
CodeBlockType type; CodeBlockType type;
int parent; // parent index in blocks int parent; // parent index in blocks
int start; // start index of this block in co_code, inclusive int start; // start index of this block in codes, inclusive
int end; // end index of this block in co_code, exclusive int end; // end index of this block in codes, exclusive
std::string to_string() const { std::string to_string() const {
if(parent == -1) return ""; if(parent == -1) return "";
@ -57,7 +57,7 @@ struct CodeObject {
this->name = name; this->name = name;
} }
std::vector<Bytecode> co_code; std::vector<Bytecode> codes;
PyVarList consts; PyVarList consts;
std::vector<std::pair<_Str, NameScope>> names; std::vector<std::pair<_Str, NameScope>> names;
emhash8::HashMap<_Str, int> global_names; emhash8::HashMap<_Str, int> global_names;
@ -66,7 +66,7 @@ struct CodeObject {
bool add_label(const _Str& label){ bool add_label(const _Str& label){
if(labels.contains(label)) return false; if(labels.contains(label)) return false;
labels[label] = co_code.size(); labels[label] = codes.size();
return true; return true;
} }
@ -86,10 +86,10 @@ struct CodeObject {
} }
void optimize_level_1(){ void optimize_level_1(){
for(int i=0; i<co_code.size(); i++){ for(int i=0; i<codes.size(); i++){
if(co_code[i].op >= OP_BINARY_OP && co_code[i].op <= OP_CONTAINS_OP){ if(codes[i].op >= OP_BINARY_OP && codes[i].op <= OP_CONTAINS_OP){
for(int j=0; j<2; j++){ for(int j=0; j<2; j++){
Bytecode& bc = co_code[i-j-1]; Bytecode& bc = codes[i-j-1];
if(bc.op >= OP_LOAD_CONST && bc.op <= OP_LOAD_NAME_REF){ if(bc.op >= OP_LOAD_CONST && bc.op <= OP_LOAD_NAME_REF){
if(bc.op == OP_LOAD_NAME_REF){ if(bc.op == OP_LOAD_NAME_REF){
bc.op = OP_LOAD_NAME; bc.op = OP_LOAD_NAME;
@ -98,12 +98,12 @@ struct CodeObject {
break; break;
} }
} }
}else if(co_code[i].op == OP_CALL){ }else if(codes[i].op == OP_CALL){
int ARGC = co_code[i].arg & 0xFFFF; int ARGC = codes[i].arg & 0xFFFF;
int KWARGC = (co_code[i].arg >> 16) & 0xFFFF; int KWARGC = (codes[i].arg >> 16) & 0xFFFF;
if(KWARGC != 0) continue; if(KWARGC != 0) continue;
for(int j=0; j<ARGC+1; j++){ for(int j=0; j<ARGC+1; j++){
Bytecode& bc = co_code[i-j-1]; Bytecode& bc = codes[i-j-1];
if(bc.op >= OP_LOAD_CONST && bc.op <= OP_LOAD_NAME_REF){ if(bc.op >= OP_LOAD_CONST && bc.op <= OP_LOAD_NAME_REF){
if(bc.op == OP_LOAD_NAME_REF){ if(bc.op == OP_LOAD_NAME_REF){
bc.op = OP_LOAD_NAME; bc.op = OP_LOAD_NAME;
@ -127,12 +127,12 @@ struct CodeObject {
} }
void _enter_block(CodeBlockType type){ void _enter_block(CodeBlockType type){
blocks.push_back(CodeBlock{type, _curr_block_i, (int)co_code.size()}); blocks.push_back(CodeBlock{type, _curr_block_i, (int)codes.size()});
_curr_block_i = blocks.size()-1; _curr_block_i = blocks.size()-1;
} }
void _exit_block(){ void _exit_block(){
blocks[_curr_block_i].end = co_code.size(); blocks[_curr_block_i].end = codes.size();
_curr_block_i = blocks[_curr_block_i].parent; _curr_block_i = blocks[_curr_block_i].parent;
if(_curr_block_i < 0) UNREACHABLE(); if(_curr_block_i < 0) UNREACHABLE();
} }
@ -160,11 +160,11 @@ struct Frame {
inline const Bytecode& next_bytecode() { inline const Bytecode& next_bytecode() {
_ip = _next_ip; _ip = _next_ip;
_next_ip = _ip + 1; _next_ip = _ip + 1;
return co->co_code[_ip]; return co->codes[_ip];
} }
_Str snapshot(){ _Str snapshot(){
int line = co->co_code[_ip].line; int line = co->codes[_ip].line;
return co->src->snapshot(line); return co->src->snapshot(line);
} }
@ -180,7 +180,7 @@ struct Frame {
} }
inline bool has_next_bytecode() const { inline bool has_next_bytecode() const {
return _next_ip < co->co_code.size(); return _next_ip < co->codes.size();
} }
inline PyVar pop(){ inline PyVar pop(){
@ -229,7 +229,7 @@ struct Frame {
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block; std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
inline void on_try_block_enter(){ inline void on_try_block_enter(){
s_try_block.push(std::make_pair(co->co_code[_ip].block, _data)); s_try_block.push(std::make_pair(co->codes[_ip].block, _data));
} }
inline void on_try_block_exit(){ inline void on_try_block_exit(){
@ -248,16 +248,16 @@ struct Frame {
} }
void jump_abs_safe(int target){ void jump_abs_safe(int target){
const Bytecode& prev = co->co_code[_ip]; const Bytecode& prev = co->codes[_ip];
int i = prev.block; int i = prev.block;
_next_ip = target; _next_ip = target;
if(_next_ip >= co->co_code.size()){ if(_next_ip >= co->codes.size()){
while(i>=0){ while(i>=0){
if(co->blocks[i].type == FOR_LOOP) pop(); if(co->blocks[i].type == FOR_LOOP) pop();
i = co->blocks[i].parent; i = co->blocks[i].parent;
} }
}else{ }else{
const Bytecode& next = co->co_code[target]; const Bytecode& next = co->codes[target];
while(i>=0 && i!=next.block){ while(i>=0 && i!=next.block){
if(co->blocks[i].type == FOR_LOOP) pop(); if(co->blocks[i].type == FOR_LOOP) pop();
i = co->blocks[i].parent; i = co->blocks[i].parent;

View File

@ -507,7 +507,7 @@ private:
void exprList() { void exprList() {
int _patch = emit(OP_NO_OP); int _patch = emit(OP_NO_OP);
int _body_start = co()->co_code.size(); int _body_start = co()->codes.size();
int ARGC = 0; int ARGC = 0;
do { do {
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
@ -523,15 +523,15 @@ private:
__LISTCOMP: __LISTCOMP:
int _body_end_return = emit(OP_JUMP_ABSOLUTE, -1); int _body_end_return = emit(OP_JUMP_ABSOLUTE, -1);
int _body_end = co()->co_code.size(); int _body_end = co()->codes.size();
co()->co_code[_patch].op = OP_JUMP_ABSOLUTE; co()->codes[_patch].op = OP_JUMP_ABSOLUTE;
co()->co_code[_patch].arg = _body_end; co()->codes[_patch].arg = _body_end;
emit(OP_BUILD_LIST, 0); emit(OP_BUILD_LIST, 0);
EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE(); EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE();
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
int _skipPatch = emit(OP_JUMP_ABSOLUTE); int _skipPatch = emit(OP_JUMP_ABSOLUTE);
int _cond_start = co()->co_code.size(); int _cond_start = co()->codes.size();
int _cond_end_return = -1; int _cond_end_return = -1;
if(match(TK("if"))) { if(match(TK("if"))) {
EXPR_TUPLE(); EXPR_TUPLE();
@ -666,17 +666,17 @@ __LISTCOMP:
int emit(Opcode opcode, int arg=-1, bool keepline=false) { int emit(Opcode opcode, int arg=-1, bool keepline=false) {
int line = parser->prev.line; int line = parser->prev.line;
co()->co_code.push_back( co()->codes.push_back(
Bytecode{(uint8_t)opcode, arg, line, (uint16_t)co()->_curr_block_i} Bytecode{(uint8_t)opcode, arg, line, (uint16_t)co()->_curr_block_i}
); );
int i = co()->co_code.size() - 1; int i = co()->codes.size() - 1;
if(keepline && i>=1) co()->co_code[i].line = co()->co_code[i-1].line; if(keepline && i>=1) co()->codes[i].line = co()->codes[i-1].line;
return i; return i;
} }
inline void patch_jump(int addr_index) { inline void patch_jump(int addr_index) {
int target = co()->co_code.size(); int target = co()->codes.size();
co()->co_code[addr_index].arg = target; co()->codes[addr_index].arg = target;
} }
void compile_block_body(CompilerAction action=nullptr) { void compile_block_body(CompilerAction action=nullptr) {
@ -912,7 +912,7 @@ __LISTCOMP:
EXPR_ANY(); EXPR_ANY();
consume_end_stmt(); consume_end_stmt();
// If last op is not an assignment, pop the result. // If last op is not an assignment, pop the result.
uint8_t last_op = co()->co_code.back().op; uint8_t last_op = co()->codes.back().op;
if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF){ if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF){
if(mode()==REPL_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR, -1, true); if(mode()==REPL_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR, -1, true);
emit(OP_POP_TOP, -1, true); emit(OP_POP_TOP, -1, true);

View File

@ -113,7 +113,7 @@ class VM {
PyVar clsBase = frame->pop_value(this); PyVar clsBase = frame->pop_value(this);
if(clsBase == None) clsBase = _tp_object; if(clsBase == None) clsBase = _tp_object;
check_type(clsBase, _tp_type); check_type(clsBase, _tp_type);
PyVar cls = new_user_type_object(frame->_module, clsName, clsBase); PyVar cls = new_type_object(frame->_module, clsName, clsBase);
while(true){ while(true){
PyVar fn = frame->pop_value(this); PyVar fn = frame->pop_value(this);
if(fn == None) break; if(fn == None) break;
@ -507,7 +507,7 @@ public:
PyVar* it_m = (*callable)->attribs.try_get(__module__); PyVar* it_m = (*callable)->attribs.try_get(__module__);
PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module; PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module;
if(opCall){ if(opCall){
__new_frame(fn->code, _module, _locals); _new_frame(fn->code, _module, _locals);
return _py_op_call; return _py_op_call;
} }
return _exec(fn->code, _module, _locals); return _exec(fn->code, _module, _locals);
@ -535,7 +535,7 @@ public:
} }
template<typename ...Args> template<typename ...Args>
Frame* __new_frame(Args&&... args){ Frame* _new_frame(Args&&... args){
if(callstack.size() > maxRecursionDepth){ if(callstack.size() > maxRecursionDepth){
_error("RecursionError", "maximum recursion depth exceeded"); _error("RecursionError", "maximum recursion depth exceeded");
} }
@ -545,7 +545,7 @@ public:
template<typename ...Args> template<typename ...Args>
PyVar _exec(Args&&... args){ PyVar _exec(Args&&... args){
Frame* frame = __new_frame(std::forward<Args>(args)...); Frame* frame = _new_frame(std::forward<Args>(args)...);
i64 base_id = frame->id; i64 base_id = frame->id;
PyVar ret = nullptr; PyVar ret = nullptr;
bool need_raise = false; bool need_raise = false;
@ -586,7 +586,7 @@ public:
} }
} }
PyVar new_user_type_object(PyVar mod, _Str name, PyVar base){ PyVar new_type_object(PyVar mod, _Str name, PyVar base){
if(!base->is_type(_tp_type)) UNREACHABLE(); if(!base->is_type(_tp_type)) UNREACHABLE();
PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(_tp_type, DUMMY_VAL); PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(_tp_type, DUMMY_VAL);
setattr(obj, __base__, base); setattr(obj, __base__, base);
@ -597,7 +597,7 @@ public:
return obj; return obj;
} }
PyVar new_type_object(_Str name, PyVar base=nullptr) { PyVar _new_type_object(_Str name, PyVar base=nullptr) {
if(base == nullptr) base = _tp_object; if(base == nullptr) base = _tp_object;
PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(_tp_type, DUMMY_VAL); PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(_tp_type, DUMMY_VAL);
setattr(obj, __base__, base); setattr(obj, __base__, base);
@ -706,7 +706,7 @@ public:
}else if(obj->is_type(_tp_float)){ }else if(obj->is_type(_tp_float)){
return PyFloat_AS_C(obj); return PyFloat_AS_C(obj);
} }
TypeError("expected int or float, got " + OBJ_TP_NAME(obj)); TypeError("expected 'int' or 'float', got " + OBJ_TP_NAME(obj).escape(true));
return 0; return 0;
} }
@ -728,19 +728,19 @@ public:
return index; return index;
} }
_Str disassemble(_Code code){ _Str disassemble(_Code co){
std::vector<int> jumpTargets; std::vector<int> jumpTargets;
for(auto byte : code->co_code){ for(auto byte : co->codes){
if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_SAFE_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){ if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_SAFE_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){
jumpTargets.push_back(byte.arg); jumpTargets.push_back(byte.arg);
} }
} }
_StrStream ss; _StrStream ss;
ss << std::string(54, '-') << '\n'; ss << std::string(54, '-') << '\n';
ss << code->name << ":\n"; ss << co->name << ":\n";
int prev_line = -1; int prev_line = -1;
for(int i=0; i<code->co_code.size(); i++){ for(int i=0; i<co->codes.size(); i++){
const Bytecode& byte = code->co_code[i]; const Bytecode& byte = co->codes[i];
_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{
@ -759,30 +759,30 @@ public:
// ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5); // ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg); std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg);
if(byte.op == OP_LOAD_CONST){ if(byte.op == OP_LOAD_CONST){
argStr += " (" + PyStr_AS_C(asRepr(code->consts[byte.arg])) + ")"; argStr += " (" + PyStr_AS_C(asRepr(co->consts[byte.arg])) + ")";
} }
if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME || byte.op == OP_RAISE){ if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME || byte.op == OP_RAISE){
argStr += " (" + code->names[byte.arg].first.escape(true) + ")"; argStr += " (" + co->names[byte.arg].first.escape(true) + ")";
} }
ss << pad(argStr, 20); // may overflow ss << pad(argStr, 20); // may overflow
ss << code->blocks[byte.block].to_string(); ss << co->blocks[byte.block].to_string();
if(i != code->co_code.size() - 1) ss << '\n'; if(i != co->codes.size() - 1) ss << '\n';
} }
_StrStream consts; _StrStream consts;
consts << "consts: "; consts << "co_consts: ";
consts << PyStr_AS_C(asRepr(PyList(code->consts))); consts << PyStr_AS_C(asRepr(PyList(co->consts)));
_StrStream names; _StrStream names;
names << "names: "; names << "co_names: ";
PyVarList list; PyVarList list;
for(int i=0; i<code->names.size(); i++){ for(int i=0; i<co->names.size(); i++){
list.push_back(PyStr(code->names[i].first)); list.push_back(PyStr(co->names[i].first));
} }
names << PyStr_AS_C(asRepr(PyList(list))); names << PyStr_AS_C(asRepr(PyList(list)));
ss << '\n' << consts.str() << '\n' << names.str() << '\n'; ss << '\n' << consts.str() << '\n' << names.str() << '\n';
for(int i=0; i<code->consts.size(); i++){ for(int i=0; i<co->consts.size(); i++){
PyVar obj = code->consts[i]; PyVar obj = co->consts[i];
if(obj->is_type(_tp_function)){ if(obj->is_type(_tp_function)){
const auto& f = PyFunction_AS_C(obj); const auto& f = PyFunction_AS_C(obj);
ss << disassemble(f->code); ss << disassemble(f->code);
@ -838,31 +838,31 @@ public:
_types["object"] = _tp_object; _types["object"] = _tp_object;
_types["type"] = _tp_type; _types["type"] = _tp_type;
_tp_bool = new_type_object("bool"); _tp_bool = _new_type_object("bool");
_tp_int = new_type_object("int"); _tp_int = _new_type_object("int");
_tp_float = new_type_object("float"); _tp_float = _new_type_object("float");
_tp_str = new_type_object("str"); _tp_str = _new_type_object("str");
_tp_list = new_type_object("list"); _tp_list = _new_type_object("list");
_tp_tuple = new_type_object("tuple"); _tp_tuple = _new_type_object("tuple");
_tp_slice = new_type_object("slice"); _tp_slice = _new_type_object("slice");
_tp_range = new_type_object("range"); _tp_range = _new_type_object("range");
_tp_module = new_type_object("module"); _tp_module = _new_type_object("module");
_tp_ref = new_type_object("_ref"); _tp_ref = _new_type_object("_ref");
_tp_function = new_type_object("function"); _tp_function = _new_type_object("function");
_tp_native_function = new_type_object("native_function"); _tp_native_function = _new_type_object("native_function");
_tp_native_iterator = new_type_object("native_iterator"); _tp_native_iterator = _new_type_object("native_iterator");
_tp_bound_method = new_type_object("bound_method"); _tp_bound_method = _new_type_object("bound_method");
_tp_super = new_type_object("super"); _tp_super = _new_type_object("super");
_tp_exception = new_type_object("Exception"); _tp_exception = _new_type_object("Exception");
this->None = new_object(new_type_object("NoneType"), DUMMY_VAL); this->None = new_object(_new_type_object("NoneType"), DUMMY_VAL);
this->Ellipsis = new_object(new_type_object("ellipsis"), DUMMY_VAL); this->Ellipsis = new_object(_new_type_object("ellipsis"), DUMMY_VAL);
this->True = new_object(_tp_bool, true); this->True = new_object(_tp_bool, true);
this->False = new_object(_tp_bool, false); this->False = new_object(_tp_bool, false);
this->builtins = new_module("builtins"); this->builtins = new_module("builtins");
this->_main = new_module("__main__"); this->_main = new_module("__main__");
this->_py_op_call = new_object(new_type_object("_internal"), DUMMY_VAL); this->_py_op_call = new_object(_new_type_object("_internal"), DUMMY_VAL);
setattr(_tp_type, __base__, _tp_object); setattr(_tp_type, __base__, _tp_object);
_tp_type->type = _tp_type; _tp_type->type = _tp_type;
@ -939,7 +939,7 @@ public:
template<typename T> template<typename T>
PyVar register_class(PyVar mod){ PyVar register_class(PyVar mod){
PyVar type = new_user_type_object(mod, T::_name(), _tp_object); PyVar type = new_type_object(mod, T::_name(), _tp_object);
if(OBJ_NAME(mod) != T::_mod()) UNREACHABLE(); if(OBJ_NAME(mod) != T::_mod()) UNREACHABLE();
T::_register(this, mod, type); T::_register(this, mod, type);
return type; return type;