From c4321b8f4bd2cb1a5b909a92b42b2002d3b78957 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 19 Feb 2023 01:34:18 +0800 Subject: [PATCH] some refactor --- src/ceval.h | 402 ++++++++++++++++++++++--------------------------- src/compiler.h | 43 ++---- src/frame.h | 2 +- src/opcodes.h | 2 +- 4 files changed, 199 insertions(+), 250 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index 7b33db87..baa5d7d1 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -12,7 +12,7 @@ PyVar VM::run_frame(Frame* frame){ { case OP_NO_OP: continue; case OP_LOAD_CONST: frame->push(frame->co->consts[byte.arg]); continue; - case OP_LOAD_LAMBDA: { + case OP_LOAD_FUNCTION: { PyVar obj = frame->co->consts[byte.arg]; setattr(obj, __module__, frame->_module); frame->push(obj); @@ -54,12 +54,11 @@ PyVar VM::run_frame(Frame* frame){ PyVarRef r = frame->pop(); PyRef_AS_C(r)->set(this, frame, std::move(obj)); } continue; - case OP_DELETE_REF: { - PyVarRef r = frame->pop(); - PyRef_AS_C(r)->del(this, frame); - } continue; - case OP_BUILD_SMART_TUPLE: - { + case OP_DELETE_REF: + PyRef_AS_C(frame->top())->del(this, frame); + frame->_pop(); + continue; + case OP_BUILD_SMART_TUPLE: { pkpy::Args items = frame->pop_n_reversed(byte.arg); bool done = false; for(int i=0; ipush(PyRef(TupleRef(std::move(items)))); } continue; - case OP_BUILD_STRING: - { + case OP_BUILD_STRING: { pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg); StrStream ss; for(int i=0; ipush(PyStr(ss.str())); } continue; - case OP_LOAD_EVAL_FN: { - frame->push(builtins->attr(m_eval)); - } continue; + case OP_LOAD_EVAL_FN: frame->push(builtins->attr(m_eval)); continue; case OP_LIST_APPEND: { pkpy::Args args(2); args[1] = frame->pop_value(this); // obj args[0] = frame->top_value_offset(this, -2); // list fast_call(m_append, std::move(args)); } continue; - case OP_STORE_FUNCTION: - { - PyVar obj = frame->pop_value(this); - const pkpy::Function_& fn = PyFunction_AS_C(obj); - setattr(obj, __module__, frame->_module); - frame->f_globals()[fn->name] = obj; - } continue; - case OP_BUILD_CLASS: - { - const Str& clsName = frame->co->names[byte.arg].first; - PyVar clsBase = frame->pop_value(this); - if(clsBase == None) clsBase = _t(tp_object); - check_type(clsBase, tp_type); - PyVar cls = new_type_object(frame->_module, clsName, clsBase); - while(true){ - PyVar fn = frame->pop_value(this); - if(fn == None) break; - const pkpy::Function_& f = PyFunction_AS_C(fn); - setattr(fn, __module__, frame->_module); - setattr(cls, f->name, fn); - } - } continue; + case OP_BUILD_CLASS: { + const Str& clsName = frame->co->names[byte.arg].first; + PyVar clsBase = frame->pop_value(this); + if(clsBase == None) clsBase = _t(tp_object); + check_type(clsBase, tp_type); + PyVar cls = new_type_object(frame->_module, clsName, clsBase); + while(true){ + PyVar fn = frame->pop_value(this); + if(fn == None) break; + const pkpy::Function_& f = PyFunction_AS_C(fn); + setattr(cls, f->name, fn); + } + } continue; case OP_RETURN_VALUE: return frame->pop_value(this); - case OP_PRINT_EXPR: - { - const PyVar expr = frame->top_value(this); - if(expr == None) continue; - *_stdout << PyStr_AS_C(asRepr(expr)) << '\n'; - } continue; + case OP_PRINT_EXPR: { + const PyVar expr = frame->top_value(this); + if(expr == None) continue; + *_stdout << PyStr_AS_C(asRepr(expr)) << '\n'; + } continue; case OP_POP_TOP: frame->_pop(); continue; - case OP_BINARY_OP: - { - pkpy::Args args(2); - args[1] = frame->pop_value(this); - args[0] = frame->top_value(this); - frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); - } continue; - case OP_BITWISE_OP: - { - pkpy::Args args(2); - args[1] = frame->pop_value(this); - args[0] = frame->top_value(this); - frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); - } continue; - case OP_INPLACE_BINARY_OP: - { - pkpy::Args args(2); - args[1] = frame->pop_value(this); - args[0] = frame->top_value(this); - PyVar ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); - PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); - frame->_pop(); - } continue; - case OP_INPLACE_BITWISE_OP: - { - pkpy::Args args(2); - args[1] = frame->pop_value(this); - args[0] = frame->top_value(this); - PyVar ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); - PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); - frame->_pop(); - } continue; - case OP_COMPARE_OP: - { - pkpy::Args args(2); - args[1] = frame->pop_value(this); - args[0] = frame->top_value(this); - frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args)); - } continue; - case OP_IS_OP: - { - PyVar rhs = frame->pop_value(this); - bool ret_c = rhs == frame->top_value(this); - if(byte.arg == 1) ret_c = !ret_c; - frame->top() = PyBool(ret_c); - } continue; - case OP_CONTAINS_OP: - { - PyVar rhs = frame->pop_value(this); - bool ret_c = PyBool_AS_C(call(rhs, __contains__, pkpy::one_arg(frame->pop_value(this)))); - if(byte.arg == 1) ret_c = !ret_c; - frame->push(PyBool(ret_c)); - } continue; + case OP_BINARY_OP: { + pkpy::Args args(2); + args[1] = frame->pop_value(this); + args[0] = frame->top_value(this); + frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); + } continue; + case OP_BITWISE_OP: { + pkpy::Args args(2); + args[1] = frame->pop_value(this); + args[0] = frame->top_value(this); + frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); + } continue; + case OP_INPLACE_BINARY_OP: { + pkpy::Args args(2); + args[1] = frame->pop_value(this); + args[0] = frame->top_value(this); + PyVar ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); + PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); + frame->_pop(); + } continue; + case OP_INPLACE_BITWISE_OP: { + pkpy::Args args(2); + args[1] = frame->pop_value(this); + args[0] = frame->top_value(this); + PyVar ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); + PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); + frame->_pop(); + } continue; + case OP_COMPARE_OP: { + pkpy::Args args(2); + args[1] = frame->pop_value(this); + args[0] = frame->top_value(this); + frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args)); + } continue; + case OP_IS_OP: { + PyVar rhs = frame->pop_value(this); + bool ret_c = rhs == frame->top_value(this); + if(byte.arg == 1) ret_c = !ret_c; + frame->top() = PyBool(ret_c); + } continue; + case OP_CONTAINS_OP: { + PyVar rhs = frame->pop_value(this); + bool ret_c = PyBool_AS_C(call(rhs, __contains__, pkpy::one_arg(frame->pop_value(this)))); + if(byte.arg == 1) ret_c = !ret_c; + frame->push(PyBool(ret_c)); + } continue; case OP_UNARY_NEGATIVE: frame->top() = num_negated(frame->top_value(this)); continue; - case OP_UNARY_NOT: - { - PyVar obj = frame->pop_value(this); - const PyVar& obj_bool = asBool(obj); - frame->push(PyBool(!PyBool_AS_C(obj_bool))); - } continue; + case OP_UNARY_NOT: { + PyVar obj = frame->pop_value(this); + const PyVar& obj_bool = asBool(obj); + frame->push(PyBool(!PyBool_AS_C(obj_bool))); + } continue; case OP_POP_JUMP_IF_FALSE: if(!PyBool_AS_C(asBool(frame->pop_value(this)))) frame->jump_abs(byte.arg); continue; @@ -187,61 +165,54 @@ PyVar VM::run_frame(Frame* frame){ case OP_LOAD_TRUE: frame->push(True); continue; case OP_LOAD_FALSE: frame->push(False); continue; case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); continue; - case OP_ASSERT: - { - PyVar _msg = frame->pop_value(this); - Str msg = PyStr_AS_C(asStr(_msg)); - PyVar expr = frame->pop_value(this); - if(asBool(expr) != True) _error("AssertionError", msg); - } continue; - case OP_EXCEPTION_MATCH: - { - const auto& _e = PyException_AS_C(frame->top()); - Str name = frame->co->names[byte.arg].first; - frame->push(PyBool(_e.match_type(name))); - } continue; - case OP_RAISE: - { - PyVar obj = frame->pop_value(this); - Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj)); - Str type = frame->co->names[byte.arg].first; - _error(type, msg); - } continue; + case OP_ASSERT: { + PyVar _msg = frame->pop_value(this); + Str msg = PyStr_AS_C(asStr(_msg)); + PyVar expr = frame->pop_value(this); + if(asBool(expr) != True) _error("AssertionError", msg); + } continue; + case OP_EXCEPTION_MATCH: { + const auto& e = PyException_AS_C(frame->top()); + Str name = frame->co->names[byte.arg].first; + frame->push(PyBool(e.match_type(name))); + } continue; + case OP_RAISE: { + PyVar obj = frame->pop_value(this); + Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj)); + Str type = frame->co->names[byte.arg].first; + _error(type, msg); + } continue; case OP_RE_RAISE: _raise(); continue; case OP_BUILD_LIST: - frame->push(PyList( - frame->pop_n_values_reversed(this, byte.arg).move_to_list())); + frame->push(PyList(frame->pop_n_values_reversed(this, byte.arg).move_to_list())); continue; - case OP_BUILD_MAP: - { - pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2); - PyVar obj = call(builtins->attr("dict")); - for(int i=0; ipush(obj); - } continue; - case OP_BUILD_SET: - { - PyVar list = PyList( - frame->pop_n_values_reversed(this, byte.arg).move_to_list() - ); - PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list)); - frame->push(obj); - } continue; + case OP_BUILD_MAP: { + pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2); + PyVar obj = call(builtins->attr("dict")); + for(int i=0; ipush(obj); + } continue; + case OP_BUILD_SET: { + PyVar list = PyList( + frame->pop_n_values_reversed(this, byte.arg).move_to_list() + ); + PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list)); + frame->push(obj); + } continue; case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); continue; - case OP_CALL: - { - int ARGC = byte.arg & 0xFFFF; - int KWARGC = (byte.arg >> 16) & 0xFFFF; - pkpy::Args kwargs(0); - if(KWARGC > 0) kwargs = frame->pop_n_values_reversed(this, KWARGC*2); - pkpy::Args args = frame->pop_n_values_reversed(this, ARGC); - PyVar callable = frame->pop_value(this); - PyVar ret = call(callable, std::move(args), kwargs, true); - if(ret == _py_op_call) return ret; - frame->push(std::move(ret)); - } continue; + case OP_CALL: { + int ARGC = byte.arg & 0xFFFF; + int KWARGC = (byte.arg >> 16) & 0xFFFF; + pkpy::Args kwargs(0); + if(KWARGC > 0) kwargs = frame->pop_n_values_reversed(this, KWARGC*2); + pkpy::Args args = frame->pop_n_values_reversed(this, ARGC); + PyVar callable = frame->pop_value(this); + PyVar ret = call(callable, std::move(args), kwargs, true); + if(ret == _py_op_call) return ret; + frame->push(std::move(ret)); + } continue; case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); continue; case OP_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); continue; case OP_GOTO: { @@ -250,87 +221,76 @@ PyVar VM::run_frame(Frame* frame){ if(target == nullptr) _error("KeyError", "label '" + label + "' not found"); frame->jump_abs_safe(*target); } continue; - case OP_GET_ITER: - { - PyVar obj = frame->pop_value(this); - PyVar iter_obj = asIter(obj); - PyVarRef var = frame->pop(); - check_type(var, tp_ref); - PyIter_AS_C(iter_obj)->var = var; - frame->push(std::move(iter_obj)); - } continue; - case OP_FOR_ITER: - { - // top() must be PyIter, so no need to try_deref() - auto& it = PyIter_AS_C(frame->top()); - PyVar obj = it->next(); - if(obj != nullptr){ - PyRef_AS_C(it->var)->set(this, frame, std::move(obj)); - }else{ - int blockEnd = frame->co->blocks[byte.block].end; - frame->jump_abs_safe(blockEnd); - } - } continue; - case OP_LOOP_CONTINUE: - { - int blockStart = frame->co->blocks[byte.block].start; - frame->jump_abs(blockStart); - } continue; - case OP_LOOP_BREAK: - { + case OP_GET_ITER: { + PyVar obj = frame->pop_value(this); + PyVar iter_obj = asIter(obj); + PyVarRef var = frame->pop(); + check_type(var, tp_ref); + PyIter_AS_C(iter_obj)->var = var; + frame->push(std::move(iter_obj)); + } continue; + case OP_FOR_ITER: { + auto& it = PyIter_AS_C(frame->top()); + PyVar obj = it->next(); + if(obj != nullptr){ + PyRef_AS_C(it->var)->set(this, frame, std::move(obj)); + }else{ int blockEnd = frame->co->blocks[byte.block].end; frame->jump_abs_safe(blockEnd); - } continue; - case OP_JUMP_IF_FALSE_OR_POP: - { - const PyVar expr = frame->top_value(this); - if(asBool(expr)==False) frame->jump_abs(byte.arg); - else frame->pop_value(this); - } continue; - case OP_JUMP_IF_TRUE_OR_POP: - { - const PyVar expr = frame->top_value(this); - if(asBool(expr)==True) frame->jump_abs(byte.arg); - else frame->pop_value(this); - } continue; - case OP_BUILD_SLICE: - { - PyVar stop = frame->pop_value(this); - PyVar start = frame->pop_value(this); - pkpy::Slice s; - if(start != None) {check_type(start, tp_int); s.start = (int)PyInt_AS_C(start);} - if(stop != None) {check_type(stop, tp_int); s.stop = (int)PyInt_AS_C(stop);} - frame->push(PySlice(s)); - } continue; - case OP_IMPORT_NAME: - { - const Str& name = frame->co->names[byte.arg].first; - auto it = _modules.find(name); - if(it == _modules.end()){ - auto it2 = _lazy_modules.find(name); - if(it2 == _lazy_modules.end()){ - _error("ImportError", "module '" + name + "' not found"); - }else{ - const Str& source = it2->second; - CodeObject_ code = compile(source, name, EXEC_MODE); - PyVar _m = new_module(name); - _exec(code, _m, pkpy::make_shared()); - frame->push(_m); - _lazy_modules.erase(it2); - } + } + } continue; + case OP_LOOP_CONTINUE: { + int blockStart = frame->co->blocks[byte.block].start; + frame->jump_abs(blockStart); + } continue; + case OP_LOOP_BREAK: { + int blockEnd = frame->co->blocks[byte.block].end; + frame->jump_abs_safe(blockEnd); + } continue; + case OP_JUMP_IF_FALSE_OR_POP: { + const PyVar expr = frame->top_value(this); + if(asBool(expr)==False) frame->jump_abs(byte.arg); + else frame->pop_value(this); + } continue; + case OP_JUMP_IF_TRUE_OR_POP: { + const PyVar expr = frame->top_value(this); + if(asBool(expr)==True) frame->jump_abs(byte.arg); + else frame->pop_value(this); + } continue; + case OP_BUILD_SLICE: { + PyVar stop = frame->pop_value(this); + PyVar start = frame->pop_value(this); + pkpy::Slice s; + if(start != None) {check_type(start, tp_int); s.start = (int)PyInt_AS_C(start);} + if(stop != None) {check_type(stop, tp_int); s.stop = (int)PyInt_AS_C(stop);} + frame->push(PySlice(s)); + } continue; + case OP_IMPORT_NAME: { + const Str& name = frame->co->names[byte.arg].first; + auto it = _modules.find(name); + if(it == _modules.end()){ + auto it2 = _lazy_modules.find(name); + if(it2 == _lazy_modules.end()){ + _error("ImportError", "module " + name.escape(true) + " not found"); }else{ - frame->push(it->second); + const Str& source = it2->second; + CodeObject_ code = compile(source, name, EXEC_MODE); + PyVar _m = new_module(name); + _exec(code, _m, pkpy::make_shared()); + frame->push(_m); + _lazy_modules.erase(it2); } - } continue; + }else{ + frame->push(it->second); + } + } continue; case OP_YIELD_VALUE: return _py_op_yield; // TODO: using "goto" inside with block may cause __exit__ not called case OP_WITH_ENTER: call(frame->pop_value(this), __enter__); continue; case OP_WITH_EXIT: call(frame->pop_value(this), __exit__); continue; case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); continue; case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); continue; - default: - throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented"); - continue; + default: throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented"); } } diff --git a/src/compiler.h b/src/compiler.h index da1f81c7..9121c780 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -5,7 +5,6 @@ #include "ceval.h" class Compiler; - typedef void (Compiler::*GrammarFn)(); typedef void (Compiler::*CompilerAction)(); @@ -28,6 +27,7 @@ class Compiler { CodeObject_ co() const{ return codes.top(); } CompileMode mode() const{ return parser->src->mode; } + NameScope name_scope() const { return codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL; } public: Compiler(VM* vm, const char* source, Str filename, CompileMode mode){ @@ -132,7 +132,7 @@ private: case 'n': buff.push_back('\n'); break; case 'r': buff.push_back('\r'); break; case 't': buff.push_back('\t'); break; - default: SyntaxError("invalid escape character"); + default: SyntaxError("invalid escape char"); } } else { buff.push_back(c); @@ -396,7 +396,7 @@ private: emit(OP_RETURN_VALUE); func->code->optimize(vm); this->codes.pop(); - emit(OP_LOAD_LAMBDA, co()->add_const(vm->PyFunction(func))); + emit(OP_LOAD_FUNCTION, co()->add_const(vm->PyFunction(func))); } void exprAssign() { @@ -612,10 +612,7 @@ __LISTCOMP: void _exprName(bool force_lvalue) { Token tkname = parser->prev; - int index = co()->add_name( - tkname.str(), - codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL - ); + int index = co()->add_name(tkname.str(), name_scope()); bool fast_load = !force_lvalue && co()->_rvalue; emit(fast_load ? OP_LOAD_NAME : OP_LOAD_NAME_REF, index); } @@ -719,7 +716,7 @@ __LISTCOMP: consume(TK("@id")); tkmodule = parser->prev; } - int index = co()->add_name(tkmodule.str(), NAME_GLOBAL); + int index = co()->add_name(tkmodule.str(), name_scope()); emit(OP_STORE_NAME, index); } while (match(TK(","))); consume_end_stmt(); @@ -739,7 +736,7 @@ __LISTCOMP: consume(TK("@id")); tkname = parser->prev; } - index = co()->add_name(tkname.str(), NAME_GLOBAL); + index = co()->add_name(tkname.str(), name_scope()); emit(OP_STORE_NAME, index); } while (match(TK(","))); emit(OP_POP_TOP); @@ -875,6 +872,12 @@ __LISTCOMP: compile_while_loop(); } else if (match(TK("for"))) { compile_for_loop(); + } else if (match(TK("import"))){ + compile_normal_import(); + } else if (match(TK("from"))){ + compile_from_import(); + } else if (match(TK("def"))){ + compile_function(); } else if (match(TK("try"))) { compile_try_except(); }else if(match(TK("assert"))){ @@ -888,10 +891,7 @@ __LISTCOMP: consume(TK("as")); consume(TK("@id")); Token tkname = parser->prev; - int index = co()->add_name( - tkname.str(), - codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL - ); + int index = co()->add_name(tkname.str(), name_scope()); emit(OP_STORE_NAME, index); emit(OP_LOAD_NAME_REF, index); emit(OP_WITH_ENTER); @@ -1009,23 +1009,19 @@ __LISTCOMP: pkpy::Function_ func = pkpy::make_shared(); consume(TK("@id")); func->name = parser->prev.str(); - consume(TK("(")); if (!match(TK(")"))) { _compile_f_args(func, true); consume(TK(")")); } - - // eat type hints - if(match(TK("->"))) consume(TK("@id")); - + if(match(TK("->"))) consume(TK("@id")); // eat type hints func->code = pkpy::make_shared(parser->src, func->name); this->codes.push(func->code); compile_block_body(); func->code->optimize(vm); this->codes.pop(); - emit(OP_LOAD_CONST, co()->add_const(vm->PyFunction(func))); - if(!is_compiling_class) emit(OP_STORE_FUNCTION); + emit(OP_LOAD_FUNCTION, co()->add_const(vm->PyFunction(func))); + if(!is_compiling_class) emit(OP_STORE_NAME, co()->add_name(func->name, name_scope())); } PyVarOrNull read_literal(){ @@ -1088,15 +1084,8 @@ public: } while (!match(TK("@eof"))) { - // compile top-level statement if (match(TK("class"))) { compile_class(); - } else if (match(TK("def"))) { - compile_function(); - } else if (match(TK("import"))) { - compile_normal_import(); - } else if (match(TK("from"))) { - compile_from_import(); } else { compile_stmt(); } diff --git a/src/frame.h b/src/frame.h index e82a391a..ee65af66 100644 --- a/src/frame.h +++ b/src/frame.h @@ -109,7 +109,7 @@ struct Frame { } int _exit_block(int i){ - if(co->blocks[i].type == FOR_LOOP) pop(); + if(co->blocks[i].type == FOR_LOOP) _pop(); else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit(); return co->blocks[i].parent; } diff --git a/src/opcodes.h b/src/opcodes.h index ef5460e7..c6d8d22b 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -48,7 +48,7 @@ OPCODE(LOAD_NONE) OPCODE(LOAD_TRUE) OPCODE(LOAD_FALSE) OPCODE(LOAD_EVAL_FN) -OPCODE(LOAD_LAMBDA) +OPCODE(LOAD_FUNCTION) OPCODE(LOAD_ELLIPSIS) OPCODE(LOAD_NAME) OPCODE(LOAD_NAME_REF)