mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 04:50:17 +00:00
some refactor
This commit is contained in:
parent
18cc83414d
commit
c4321b8f4b
114
src/ceval.h
114
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; i<items.size(); i++){
|
||||
@ -72,31 +71,20 @@ PyVar VM::run_frame(Frame* frame){
|
||||
}
|
||||
if(!done) frame->push(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; i<items.size(); i++) ss << PyStr_AS_C(asStr(items[i]));
|
||||
frame->push(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:
|
||||
{
|
||||
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);
|
||||
@ -106,34 +94,29 @@ PyVar VM::run_frame(Frame* frame){
|
||||
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_RETURN_VALUE: return frame->pop_value(this);
|
||||
case OP_PRINT_EXPR:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
case OP_INPLACE_BINARY_OP: {
|
||||
pkpy::Args args(2);
|
||||
args[1] = frame->pop_value(this);
|
||||
args[0] = frame->top_value(this);
|
||||
@ -141,8 +124,7 @@ PyVar VM::run_frame(Frame* frame){
|
||||
PyRef_AS_C(frame->top())->set(this, frame, std::move(ret));
|
||||
frame->_pop();
|
||||
} continue;
|
||||
case OP_INPLACE_BITWISE_OP:
|
||||
{
|
||||
case OP_INPLACE_BITWISE_OP: {
|
||||
pkpy::Args args(2);
|
||||
args[1] = frame->pop_value(this);
|
||||
args[0] = frame->top_value(this);
|
||||
@ -150,22 +132,19 @@ PyVar VM::run_frame(Frame* frame){
|
||||
PyRef_AS_C(frame->top())->set(this, frame, std::move(ret));
|
||||
frame->_pop();
|
||||
} continue;
|
||||
case OP_COMPARE_OP:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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;
|
||||
@ -174,8 +153,7 @@ PyVar VM::run_frame(Frame* frame){
|
||||
case OP_UNARY_NEGATIVE:
|
||||
frame->top() = num_negated(frame->top_value(this));
|
||||
continue;
|
||||
case OP_UNARY_NOT:
|
||||
{
|
||||
case OP_UNARY_NOT: {
|
||||
PyVar obj = frame->pop_value(this);
|
||||
const PyVar& obj_bool = asBool(obj);
|
||||
frame->push(PyBool(!PyBool_AS_C(obj_bool)));
|
||||
@ -187,21 +165,18 @@ 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:
|
||||
{
|
||||
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());
|
||||
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)));
|
||||
frame->push(PyBool(e.match_type(name)));
|
||||
} continue;
|
||||
case OP_RAISE:
|
||||
{
|
||||
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;
|
||||
@ -209,11 +184,9 @@ PyVar VM::run_frame(Frame* frame){
|
||||
} 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:
|
||||
{
|
||||
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; i<items.size(); i+=2){
|
||||
@ -221,8 +194,7 @@ PyVar VM::run_frame(Frame* frame){
|
||||
}
|
||||
frame->push(obj);
|
||||
} continue;
|
||||
case OP_BUILD_SET:
|
||||
{
|
||||
case OP_BUILD_SET: {
|
||||
PyVar list = PyList(
|
||||
frame->pop_n_values_reversed(this, byte.arg).move_to_list()
|
||||
);
|
||||
@ -230,8 +202,7 @@ PyVar VM::run_frame(Frame* frame){
|
||||
frame->push(obj);
|
||||
} continue;
|
||||
case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); continue;
|
||||
case OP_CALL:
|
||||
{
|
||||
case OP_CALL: {
|
||||
int ARGC = byte.arg & 0xFFFF;
|
||||
int KWARGC = (byte.arg >> 16) & 0xFFFF;
|
||||
pkpy::Args kwargs(0);
|
||||
@ -250,8 +221,7 @@ 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:
|
||||
{
|
||||
case OP_GET_ITER: {
|
||||
PyVar obj = frame->pop_value(this);
|
||||
PyVar iter_obj = asIter(obj);
|
||||
PyVarRef var = frame->pop();
|
||||
@ -259,9 +229,7 @@ PyVar VM::run_frame(Frame* frame){
|
||||
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()
|
||||
case OP_FOR_ITER: {
|
||||
auto& it = PyIter_AS_C(frame->top());
|
||||
PyVar obj = it->next();
|
||||
if(obj != nullptr){
|
||||
@ -271,30 +239,25 @@ PyVar VM::run_frame(Frame* frame){
|
||||
frame->jump_abs_safe(blockEnd);
|
||||
}
|
||||
} continue;
|
||||
case OP_LOOP_CONTINUE:
|
||||
{
|
||||
case OP_LOOP_CONTINUE: {
|
||||
int blockStart = frame->co->blocks[byte.block].start;
|
||||
frame->jump_abs(blockStart);
|
||||
} continue;
|
||||
case OP_LOOP_BREAK:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
case OP_BUILD_SLICE: {
|
||||
PyVar stop = frame->pop_value(this);
|
||||
PyVar start = frame->pop_value(this);
|
||||
pkpy::Slice s;
|
||||
@ -302,14 +265,13 @@ PyVar VM::run_frame(Frame* frame){
|
||||
if(stop != None) {check_type(stop, tp_int); s.stop = (int)PyInt_AS_C(stop);}
|
||||
frame->push(PySlice(s));
|
||||
} continue;
|
||||
case OP_IMPORT_NAME:
|
||||
{
|
||||
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");
|
||||
_error("ImportError", "module " + name.escape(true) + " not found");
|
||||
}else{
|
||||
const Str& source = it2->second;
|
||||
CodeObject_ code = compile(source, name, EXEC_MODE);
|
||||
@ -328,9 +290,7 @@ PyVar VM::run_frame(Frame* frame){
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<pkpy::Function>();
|
||||
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<CodeObject>(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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user