some refactor

This commit is contained in:
blueloveTH 2023-02-19 01:34:18 +08:00
parent 18cc83414d
commit c4321b8f4b
4 changed files with 199 additions and 250 deletions

View File

@ -12,7 +12,7 @@ PyVar VM::run_frame(Frame* frame){
{ {
case OP_NO_OP: continue; case OP_NO_OP: continue;
case OP_LOAD_CONST: frame->push(frame->co->consts[byte.arg]); 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]; PyVar obj = frame->co->consts[byte.arg];
setattr(obj, __module__, frame->_module); setattr(obj, __module__, frame->_module);
frame->push(obj); frame->push(obj);
@ -54,12 +54,11 @@ PyVar VM::run_frame(Frame* frame){
PyVarRef r = frame->pop(); PyVarRef r = frame->pop();
PyRef_AS_C(r)->set(this, frame, std::move(obj)); PyRef_AS_C(r)->set(this, frame, std::move(obj));
} continue; } continue;
case OP_DELETE_REF: { case OP_DELETE_REF:
PyVarRef r = frame->pop(); PyRef_AS_C(frame->top())->del(this, frame);
PyRef_AS_C(r)->del(this, frame); frame->_pop();
} continue; continue;
case OP_BUILD_SMART_TUPLE: case OP_BUILD_SMART_TUPLE: {
{
pkpy::Args items = frame->pop_n_reversed(byte.arg); pkpy::Args items = frame->pop_n_reversed(byte.arg);
bool done = false; bool done = false;
for(int i=0; i<items.size(); i++){ for(int i=0; i<items.size(); i++){
@ -72,114 +71,93 @@ PyVar VM::run_frame(Frame* frame){
} }
if(!done) frame->push(PyRef(TupleRef(std::move(items)))); if(!done) frame->push(PyRef(TupleRef(std::move(items))));
} continue; } continue;
case OP_BUILD_STRING: case OP_BUILD_STRING: {
{
pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg); pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg);
StrStream ss; StrStream ss;
for(int i=0; i<items.size(); i++) ss << PyStr_AS_C(asStr(items[i])); for(int i=0; i<items.size(); i++) ss << PyStr_AS_C(asStr(items[i]));
frame->push(PyStr(ss.str())); frame->push(PyStr(ss.str()));
} continue; } continue;
case OP_LOAD_EVAL_FN: { case OP_LOAD_EVAL_FN: frame->push(builtins->attr(m_eval)); continue;
frame->push(builtins->attr(m_eval));
} continue;
case OP_LIST_APPEND: { case OP_LIST_APPEND: {
pkpy::Args args(2); pkpy::Args args(2);
args[1] = frame->pop_value(this); // obj args[1] = frame->pop_value(this); // obj
args[0] = frame->top_value_offset(this, -2); // list args[0] = frame->top_value_offset(this, -2); // list
fast_call(m_append, std::move(args)); fast_call(m_append, std::move(args));
} continue; } continue;
case OP_STORE_FUNCTION: case OP_BUILD_CLASS: {
{ const Str& clsName = frame->co->names[byte.arg].first;
PyVar obj = frame->pop_value(this); PyVar clsBase = frame->pop_value(this);
const pkpy::Function_& fn = PyFunction_AS_C(obj); if(clsBase == None) clsBase = _t(tp_object);
setattr(obj, __module__, frame->_module); check_type(clsBase, tp_type);
frame->f_globals()[fn->name] = obj; PyVar cls = new_type_object(frame->_module, clsName, clsBase);
} continue; while(true){
case OP_BUILD_CLASS: PyVar fn = frame->pop_value(this);
{ if(fn == None) break;
const Str& clsName = frame->co->names[byte.arg].first; const pkpy::Function_& f = PyFunction_AS_C(fn);
PyVar clsBase = frame->pop_value(this); setattr(cls, f->name, fn);
if(clsBase == None) clsBase = _t(tp_object); }
check_type(clsBase, tp_type); } continue;
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_RETURN_VALUE: return frame->pop_value(this); case OP_RETURN_VALUE: return frame->pop_value(this);
case OP_PRINT_EXPR: case OP_PRINT_EXPR: {
{ const PyVar expr = frame->top_value(this);
const PyVar expr = frame->top_value(this); if(expr == None) continue;
if(expr == None) continue; *_stdout << PyStr_AS_C(asRepr(expr)) << '\n';
*_stdout << PyStr_AS_C(asRepr(expr)) << '\n'; } continue;
} continue;
case OP_POP_TOP: frame->_pop(); continue; case OP_POP_TOP: frame->_pop(); continue;
case OP_BINARY_OP: case OP_BINARY_OP: {
{ pkpy::Args args(2);
pkpy::Args args(2); args[1] = frame->pop_value(this);
args[1] = frame->pop_value(this); args[0] = frame->top_value(this);
args[0] = frame->top_value(this); frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); } continue;
} continue; case OP_BITWISE_OP: {
case OP_BITWISE_OP: pkpy::Args args(2);
{ args[1] = frame->pop_value(this);
pkpy::Args args(2); args[0] = frame->top_value(this);
args[1] = frame->pop_value(this); frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
args[0] = frame->top_value(this); } continue;
frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); case OP_INPLACE_BINARY_OP: {
} continue; pkpy::Args args(2);
case OP_INPLACE_BINARY_OP: args[1] = frame->pop_value(this);
{ args[0] = frame->top_value(this);
pkpy::Args args(2); PyVar ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
args[1] = frame->pop_value(this); PyRef_AS_C(frame->top())->set(this, frame, std::move(ret));
args[0] = frame->top_value(this); frame->_pop();
PyVar ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); } continue;
PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); case OP_INPLACE_BITWISE_OP: {
frame->_pop(); pkpy::Args args(2);
} continue; args[1] = frame->pop_value(this);
case OP_INPLACE_BITWISE_OP: args[0] = frame->top_value(this);
{ PyVar ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
pkpy::Args args(2); PyRef_AS_C(frame->top())->set(this, frame, std::move(ret));
args[1] = frame->pop_value(this); frame->_pop();
args[0] = frame->top_value(this); } continue;
PyVar ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); case OP_COMPARE_OP: {
PyRef_AS_C(frame->top())->set(this, frame, std::move(ret)); pkpy::Args args(2);
frame->_pop(); args[1] = frame->pop_value(this);
} continue; args[0] = frame->top_value(this);
case OP_COMPARE_OP: frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args));
{ } continue;
pkpy::Args args(2); case OP_IS_OP: {
args[1] = frame->pop_value(this); PyVar rhs = frame->pop_value(this);
args[0] = frame->top_value(this); bool ret_c = rhs == frame->top_value(this);
frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args)); if(byte.arg == 1) ret_c = !ret_c;
} continue; frame->top() = PyBool(ret_c);
case OP_IS_OP: } continue;
{ case OP_CONTAINS_OP: {
PyVar rhs = frame->pop_value(this); PyVar rhs = frame->pop_value(this);
bool ret_c = rhs == frame->top_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; if(byte.arg == 1) ret_c = !ret_c;
frame->top() = PyBool(ret_c); frame->push(PyBool(ret_c));
} continue; } 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: case OP_UNARY_NEGATIVE:
frame->top() = num_negated(frame->top_value(this)); frame->top() = num_negated(frame->top_value(this));
continue; continue;
case OP_UNARY_NOT: case OP_UNARY_NOT: {
{ PyVar obj = frame->pop_value(this);
PyVar obj = frame->pop_value(this); const PyVar& obj_bool = asBool(obj);
const PyVar& obj_bool = asBool(obj); frame->push(PyBool(!PyBool_AS_C(obj_bool)));
frame->push(PyBool(!PyBool_AS_C(obj_bool))); } continue;
} continue;
case OP_POP_JUMP_IF_FALSE: case OP_POP_JUMP_IF_FALSE:
if(!PyBool_AS_C(asBool(frame->pop_value(this)))) frame->jump_abs(byte.arg); if(!PyBool_AS_C(asBool(frame->pop_value(this)))) frame->jump_abs(byte.arg);
continue; continue;
@ -187,61 +165,54 @@ PyVar VM::run_frame(Frame* frame){
case OP_LOAD_TRUE: frame->push(True); continue; case OP_LOAD_TRUE: frame->push(True); continue;
case OP_LOAD_FALSE: frame->push(False); continue; case OP_LOAD_FALSE: frame->push(False); continue;
case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); continue; case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); continue;
case OP_ASSERT: case OP_ASSERT: {
{ PyVar _msg = frame->pop_value(this);
PyVar _msg = frame->pop_value(this); Str msg = PyStr_AS_C(asStr(_msg));
Str msg = PyStr_AS_C(asStr(_msg)); PyVar expr = frame->pop_value(this);
PyVar expr = frame->pop_value(this); if(asBool(expr) != True) _error("AssertionError", msg);
if(asBool(expr) != True) _error("AssertionError", msg); } continue;
} continue; case OP_EXCEPTION_MATCH: {
case OP_EXCEPTION_MATCH: const auto& e = PyException_AS_C(frame->top());
{ Str name = frame->co->names[byte.arg].first;
const auto& _e = PyException_AS_C(frame->top()); frame->push(PyBool(e.match_type(name)));
Str name = frame->co->names[byte.arg].first; } continue;
frame->push(PyBool(_e.match_type(name))); case OP_RAISE: {
} continue; PyVar obj = frame->pop_value(this);
case OP_RAISE: Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj));
{ Str type = frame->co->names[byte.arg].first;
PyVar obj = frame->pop_value(this); _error(type, msg);
Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj)); } continue;
Str type = frame->co->names[byte.arg].first;
_error(type, msg);
} continue;
case OP_RE_RAISE: _raise(); continue; case OP_RE_RAISE: _raise(); continue;
case OP_BUILD_LIST: case OP_BUILD_LIST:
frame->push(PyList( frame->push(PyList(frame->pop_n_values_reversed(this, byte.arg).move_to_list()));
frame->pop_n_values_reversed(this, byte.arg).move_to_list()));
continue; continue;
case OP_BUILD_MAP: case OP_BUILD_MAP: {
{ pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2);
pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2); PyVar obj = call(builtins->attr("dict"));
PyVar obj = call(builtins->attr("dict")); for(int i=0; i<items.size(); i+=2){
for(int i=0; i<items.size(); i+=2){ call(obj, __setitem__, pkpy::two_args(items[i], items[i+1]));
call(obj, __setitem__, pkpy::two_args(items[i], items[i+1])); }
} frame->push(obj);
frame->push(obj); } continue;
} continue; case OP_BUILD_SET: {
case OP_BUILD_SET: PyVar list = PyList(
{ frame->pop_n_values_reversed(this, byte.arg).move_to_list()
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);
PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list)); } continue;
frame->push(obj);
} continue;
case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); 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 ARGC = byte.arg & 0xFFFF; int KWARGC = (byte.arg >> 16) & 0xFFFF;
int KWARGC = (byte.arg >> 16) & 0xFFFF; pkpy::Args kwargs(0);
pkpy::Args kwargs(0); if(KWARGC > 0) kwargs = frame->pop_n_values_reversed(this, KWARGC*2);
if(KWARGC > 0) kwargs = frame->pop_n_values_reversed(this, KWARGC*2); pkpy::Args args = frame->pop_n_values_reversed(this, ARGC);
pkpy::Args args = frame->pop_n_values_reversed(this, ARGC); PyVar callable = frame->pop_value(this);
PyVar callable = frame->pop_value(this); PyVar ret = call(callable, std::move(args), kwargs, true);
PyVar ret = call(callable, std::move(args), kwargs, true); if(ret == _py_op_call) return ret;
if(ret == _py_op_call) return ret; frame->push(std::move(ret));
frame->push(std::move(ret)); } continue;
} continue;
case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); 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_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); continue;
case OP_GOTO: { case OP_GOTO: {
@ -250,87 +221,76 @@ PyVar VM::run_frame(Frame* frame){
if(target == nullptr) _error("KeyError", "label '" + label + "' not found"); if(target == nullptr) _error("KeyError", "label '" + label + "' not found");
frame->jump_abs_safe(*target); frame->jump_abs_safe(*target);
} continue; } continue;
case OP_GET_ITER: case OP_GET_ITER: {
{ PyVar obj = frame->pop_value(this);
PyVar obj = frame->pop_value(this); PyVar iter_obj = asIter(obj);
PyVar iter_obj = asIter(obj); PyVarRef var = frame->pop();
PyVarRef var = frame->pop(); check_type(var, tp_ref);
check_type(var, tp_ref); PyIter_AS_C(iter_obj)->var = var;
PyIter_AS_C(iter_obj)->var = var; frame->push(std::move(iter_obj));
frame->push(std::move(iter_obj)); } continue;
} continue; case OP_FOR_ITER: {
case OP_FOR_ITER: auto& it = PyIter_AS_C(frame->top());
{ PyVar obj = it->next();
// top() must be PyIter, so no need to try_deref() if(obj != nullptr){
auto& it = PyIter_AS_C(frame->top()); PyRef_AS_C(it->var)->set(this, frame, std::move(obj));
PyVar obj = it->next(); }else{
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:
{
int blockEnd = frame->co->blocks[byte.block].end; int blockEnd = frame->co->blocks[byte.block].end;
frame->jump_abs_safe(blockEnd); frame->jump_abs_safe(blockEnd);
} continue; }
case OP_JUMP_IF_FALSE_OR_POP: } continue;
{ case OP_LOOP_CONTINUE: {
const PyVar expr = frame->top_value(this); int blockStart = frame->co->blocks[byte.block].start;
if(asBool(expr)==False) frame->jump_abs(byte.arg); frame->jump_abs(blockStart);
else frame->pop_value(this); } continue;
} continue; case OP_LOOP_BREAK: {
case OP_JUMP_IF_TRUE_OR_POP: int blockEnd = frame->co->blocks[byte.block].end;
{ frame->jump_abs_safe(blockEnd);
const PyVar expr = frame->top_value(this); } continue;
if(asBool(expr)==True) frame->jump_abs(byte.arg); case OP_JUMP_IF_FALSE_OR_POP: {
else frame->pop_value(this); const PyVar expr = frame->top_value(this);
} continue; if(asBool(expr)==False) frame->jump_abs(byte.arg);
case OP_BUILD_SLICE: else frame->pop_value(this);
{ } continue;
PyVar stop = frame->pop_value(this); case OP_JUMP_IF_TRUE_OR_POP: {
PyVar start = frame->pop_value(this); const PyVar expr = frame->top_value(this);
pkpy::Slice s; if(asBool(expr)==True) frame->jump_abs(byte.arg);
if(start != None) {check_type(start, tp_int); s.start = (int)PyInt_AS_C(start);} else frame->pop_value(this);
if(stop != None) {check_type(stop, tp_int); s.stop = (int)PyInt_AS_C(stop);} } continue;
frame->push(PySlice(s)); case OP_BUILD_SLICE: {
} continue; PyVar stop = frame->pop_value(this);
case OP_IMPORT_NAME: PyVar start = frame->pop_value(this);
{ pkpy::Slice s;
const Str& name = frame->co->names[byte.arg].first; if(start != None) {check_type(start, tp_int); s.start = (int)PyInt_AS_C(start);}
auto it = _modules.find(name); if(stop != None) {check_type(stop, tp_int); s.stop = (int)PyInt_AS_C(stop);}
if(it == _modules.end()){ frame->push(PySlice(s));
auto it2 = _lazy_modules.find(name); } continue;
if(it2 == _lazy_modules.end()){ case OP_IMPORT_NAME: {
_error("ImportError", "module '" + name + "' not found"); const Str& name = frame->co->names[byte.arg].first;
}else{ auto it = _modules.find(name);
const Str& source = it2->second; if(it == _modules.end()){
CodeObject_ code = compile(source, name, EXEC_MODE); auto it2 = _lazy_modules.find(name);
PyVar _m = new_module(name); if(it2 == _lazy_modules.end()){
_exec(code, _m, pkpy::make_shared<pkpy::NameDict>()); _error("ImportError", "module " + name.escape(true) + " not found");
frame->push(_m);
_lazy_modules.erase(it2);
}
}else{ }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<pkpy::NameDict>());
frame->push(_m);
_lazy_modules.erase(it2);
} }
} continue; }else{
frame->push(it->second);
}
} continue;
case OP_YIELD_VALUE: return _py_op_yield; case OP_YIELD_VALUE: return _py_op_yield;
// TODO: using "goto" inside with block may cause __exit__ not called // 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_ENTER: call(frame->pop_value(this), __enter__); continue;
case OP_WITH_EXIT: call(frame->pop_value(this), __exit__); 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_ENTER: frame->on_try_block_enter(); continue;
case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); continue; case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); continue;
default: default: throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
continue;
} }
} }

View File

@ -5,7 +5,6 @@
#include "ceval.h" #include "ceval.h"
class Compiler; class Compiler;
typedef void (Compiler::*GrammarFn)(); typedef void (Compiler::*GrammarFn)();
typedef void (Compiler::*CompilerAction)(); typedef void (Compiler::*CompilerAction)();
@ -28,6 +27,7 @@ class Compiler {
CodeObject_ co() const{ return codes.top(); } CodeObject_ co() const{ return codes.top(); }
CompileMode mode() const{ return parser->src->mode; } CompileMode mode() const{ return parser->src->mode; }
NameScope name_scope() const { return codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL; }
public: public:
Compiler(VM* vm, const char* source, Str filename, CompileMode mode){ Compiler(VM* vm, const char* source, Str filename, CompileMode mode){
@ -132,7 +132,7 @@ private:
case 'n': buff.push_back('\n'); break; case 'n': buff.push_back('\n'); break;
case 'r': buff.push_back('\r'); break; case 'r': buff.push_back('\r'); break;
case 't': buff.push_back('\t'); break; case 't': buff.push_back('\t'); break;
default: SyntaxError("invalid escape character"); default: SyntaxError("invalid escape char");
} }
} else { } else {
buff.push_back(c); buff.push_back(c);
@ -396,7 +396,7 @@ private:
emit(OP_RETURN_VALUE); emit(OP_RETURN_VALUE);
func->code->optimize(vm); func->code->optimize(vm);
this->codes.pop(); 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() { void exprAssign() {
@ -612,10 +612,7 @@ __LISTCOMP:
void _exprName(bool force_lvalue) { void _exprName(bool force_lvalue) {
Token tkname = parser->prev; Token tkname = parser->prev;
int index = co()->add_name( int index = co()->add_name(tkname.str(), name_scope());
tkname.str(),
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
);
bool fast_load = !force_lvalue && co()->_rvalue; bool fast_load = !force_lvalue && co()->_rvalue;
emit(fast_load ? OP_LOAD_NAME : OP_LOAD_NAME_REF, index); emit(fast_load ? OP_LOAD_NAME : OP_LOAD_NAME_REF, index);
} }
@ -719,7 +716,7 @@ __LISTCOMP:
consume(TK("@id")); consume(TK("@id"));
tkmodule = parser->prev; 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); emit(OP_STORE_NAME, index);
} while (match(TK(","))); } while (match(TK(",")));
consume_end_stmt(); consume_end_stmt();
@ -739,7 +736,7 @@ __LISTCOMP:
consume(TK("@id")); consume(TK("@id"));
tkname = parser->prev; tkname = parser->prev;
} }
index = co()->add_name(tkname.str(), NAME_GLOBAL); index = co()->add_name(tkname.str(), name_scope());
emit(OP_STORE_NAME, index); emit(OP_STORE_NAME, index);
} while (match(TK(","))); } while (match(TK(",")));
emit(OP_POP_TOP); emit(OP_POP_TOP);
@ -875,6 +872,12 @@ __LISTCOMP:
compile_while_loop(); compile_while_loop();
} else if (match(TK("for"))) { } else if (match(TK("for"))) {
compile_for_loop(); 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"))) { } else if (match(TK("try"))) {
compile_try_except(); compile_try_except();
}else if(match(TK("assert"))){ }else if(match(TK("assert"))){
@ -888,10 +891,7 @@ __LISTCOMP:
consume(TK("as")); consume(TK("as"));
consume(TK("@id")); consume(TK("@id"));
Token tkname = parser->prev; Token tkname = parser->prev;
int index = co()->add_name( int index = co()->add_name(tkname.str(), name_scope());
tkname.str(),
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
);
emit(OP_STORE_NAME, index); emit(OP_STORE_NAME, index);
emit(OP_LOAD_NAME_REF, index); emit(OP_LOAD_NAME_REF, index);
emit(OP_WITH_ENTER); emit(OP_WITH_ENTER);
@ -1009,23 +1009,19 @@ __LISTCOMP:
pkpy::Function_ func = pkpy::make_shared<pkpy::Function>(); pkpy::Function_ func = pkpy::make_shared<pkpy::Function>();
consume(TK("@id")); consume(TK("@id"));
func->name = parser->prev.str(); func->name = parser->prev.str();
consume(TK("(")); consume(TK("("));
if (!match(TK(")"))) { if (!match(TK(")"))) {
_compile_f_args(func, true); _compile_f_args(func, true);
consume(TK(")")); consume(TK(")"));
} }
if(match(TK("->"))) consume(TK("@id")); // eat type hints
// eat type hints
if(match(TK("->"))) consume(TK("@id"));
func->code = pkpy::make_shared<CodeObject>(parser->src, func->name); func->code = pkpy::make_shared<CodeObject>(parser->src, func->name);
this->codes.push(func->code); this->codes.push(func->code);
compile_block_body(); compile_block_body();
func->code->optimize(vm); func->code->optimize(vm);
this->codes.pop(); this->codes.pop();
emit(OP_LOAD_CONST, co()->add_const(vm->PyFunction(func))); emit(OP_LOAD_FUNCTION, co()->add_const(vm->PyFunction(func)));
if(!is_compiling_class) emit(OP_STORE_FUNCTION); if(!is_compiling_class) emit(OP_STORE_NAME, co()->add_name(func->name, name_scope()));
} }
PyVarOrNull read_literal(){ PyVarOrNull read_literal(){
@ -1088,15 +1084,8 @@ public:
} }
while (!match(TK("@eof"))) { while (!match(TK("@eof"))) {
// compile top-level statement
if (match(TK("class"))) { if (match(TK("class"))) {
compile_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 { } else {
compile_stmt(); compile_stmt();
} }

View File

@ -109,7 +109,7 @@ struct Frame {
} }
int _exit_block(int i){ 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(); else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit();
return co->blocks[i].parent; return co->blocks[i].parent;
} }

View File

@ -48,7 +48,7 @@ OPCODE(LOAD_NONE)
OPCODE(LOAD_TRUE) OPCODE(LOAD_TRUE)
OPCODE(LOAD_FALSE) OPCODE(LOAD_FALSE)
OPCODE(LOAD_EVAL_FN) OPCODE(LOAD_EVAL_FN)
OPCODE(LOAD_LAMBDA) OPCODE(LOAD_FUNCTION)
OPCODE(LOAD_ELLIPSIS) OPCODE(LOAD_ELLIPSIS)
OPCODE(LOAD_NAME) OPCODE(LOAD_NAME)
OPCODE(LOAD_NAME_REF) OPCODE(LOAD_NAME_REF)