This commit is contained in:
blueloveTH 2023-04-05 19:25:43 +08:00
parent 14433b1210
commit cf5fadd3b0
4 changed files with 61 additions and 52 deletions

View File

@ -238,6 +238,7 @@ __NEXT_STEP:;
frame->push(std::move(ret));
} DISPATCH();
case OP_RETURN_VALUE: return frame->popx();
case OP_YIELD_VALUE: return _py_op_yield;
/*****************************************/
case OP_LIST_APPEND: {
PyObject* obj = frame->popx();
@ -352,35 +353,39 @@ __NEXT_STEP:;
cls->attr().set(name, obj);
} DISPATCH();
/*****************************************/
/*****************************************/
/*****************************************/
// case OP_SETUP_DECORATOR: DISPATCH();
// case OP_ASSERT: {
// PyObject* _msg = frame->pop_value(this);
// Str msg = CAST(Str, asStr(_msg));
// PyObject* expr = frame->pop_value(this);
// if(asBool(expr) != True) _error("AssertionError", msg);
// } DISPATCH();
// case OP_EXCEPTION_MATCH: {
// const auto& e = CAST(Exception&, frame->top());
// StrName name = frame->co->names[byte.arg].first;
// frame->push(VAR(e.match_type(name)));
// } DISPATCH();
// case OP_RAISE: {
// PyObject* obj = frame->pop_value(this);
// Str msg = obj == None ? "" : CAST(Str, asStr(obj));
// StrName type = frame->co->names[byte.arg].first;
// _error(type, msg);
// } DISPATCH();
// case OP_RE_RAISE: _raise(); DISPATCH();
// 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__, no_arg()); DISPATCH();
// case OP_WITH_EXIT: call(frame->pop_value(this), __exit__, no_arg()); DISPATCH();
// case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); DISPATCH();
// case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); DISPATCH();
default: throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
/*****************************************/
case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); DISPATCH();
case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); DISPATCH();
/*****************************************/
case OP_ASSERT: {
PyObject* obj = frame->top();
Str msg;
if(is_type(obj, tp_tuple)){
auto& t = CAST(Tuple&, obj);
if(t.size() != 2) ValueError("assert tuple must have 2 elements");
obj = t[0];
msg = CAST(Str&, asStr(t[1]));
}
bool ok = asBool(obj);
frame->pop();
if(!ok) _error("AssertionError", msg);
} DISPATCH();
case OP_EXCEPTION_MATCH: {
const auto& e = CAST(Exception&, frame->top());
StrName name = frame->co->names[byte.arg];
frame->push(VAR(e.match_type(name)));
} DISPATCH();
case OP_RAISE: {
PyObject* obj = frame->popx();
Str msg = obj == None ? "" : CAST(Str, asStr(obj));
StrName type = frame->co->names[byte.arg];
_error(type, msg);
} DISPATCH();
case OP_RE_RAISE: _raise(); DISPATCH();
default: throw std::runtime_error(OP_NAMES[byte.op] + std::string(" is not implemented"));
}
UNREACHABLE();
}

View File

@ -578,13 +578,14 @@ class Compiler {
}
void compile_decorated(){
EXPR(false);
// TODO: support multiple decorator
// use a while loop to consume '@'
if(!match_newlines_repl()) SyntaxError();
ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line);
std::vector<Expr_> decorators;
do{
EXPR();
decorators.push_back(ctx()->s_expr.popx());
if(!match_newlines_repl()) SyntaxError();
}while(match(TK("@")));
consume(TK("def"));
compile_function();
compile_function(decorators);
}
bool try_compile_assignment(){
@ -593,6 +594,7 @@ class Compiler {
switch (curr().type) {
case TK("+="): case TK("-="): case TK("*="): case TK("/="): case TK("//="): case TK("%="):
case TK("<<="): case TK(">>="): case TK("&="): case TK("|="): case TK("^="): {
if(ctx()->is_compiling_class) SyntaxError();
inplace = true;
advance();
auto e = make_expr<BinaryExpr>();
@ -802,7 +804,7 @@ class Compiler {
} while (match(TK(",")));
}
void compile_function(){
void compile_function(const std::vector<Expr_>& decorators={}){
// TODO: bug, if there are multiple decorators, will cause error
FuncDecl_ decl = make_sp<FuncDecl>();
StrName obj_name;
@ -825,6 +827,12 @@ class Compiler {
compile_block_body();
pop_context();
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
// add decorators
for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){
(*it)->emit(ctx());
ctx()->emit(OP_ROT_TWO, BC_NOARG, (*it)->line);
ctx()->emit(OP_CALL, 1, (*it)->line);
}
if(!ctx()->is_compiling_class){
if(obj_name.empty()){
auto e = make_expr<NameExpr>(decl->name, name_scope());

View File

@ -140,6 +140,10 @@ struct NameExpr: Expr{
bool emit_store(CodeEmitContext* ctx) override {
int index = ctx->add_name(name);
if(ctx->is_compiling_class){
ctx->emit(OP_STORE_CLASS_ATTR, index, line);
return true;
}
switch(scope){
case NAME_LOCAL:
ctx->emit(OP_STORE_LOCAL, index, line);

View File

@ -1,23 +1,5 @@
#ifdef OPCODE
/**************************/
OPCODE(WITH_ENTER)
OPCODE(WITH_EXIT)
OPCODE(ASSERT)
OPCODE(EXCEPTION_MATCH)
OPCODE(RAISE)
OPCODE(RE_RAISE)
OPCODE(STORE_FUNCTION)
OPCODE(TRY_BLOCK_ENTER)
OPCODE(TRY_BLOCK_EXIT)
OPCODE(YIELD_VALUE)
OPCODE(SETUP_DECORATOR)
/**************************/
OPCODE(NO_OP)
/**************************/
@ -74,6 +56,7 @@ OPCODE(CALL_UNPACK)
OPCODE(CALL_KWARGS)
OPCODE(CALL_KWARGS_UNPACK)
OPCODE(RETURN_VALUE)
OPCODE(YIELD_VALUE)
/**************************/
OPCODE(LIST_APPEND)
OPCODE(DICT_ADD)
@ -92,9 +75,18 @@ OPCODE(IMPORT_STAR)
OPCODE(UNPACK_SEQUENCE)
OPCODE(UNPACK_EX)
/**************************/
// TODO: examine this
OPCODE(BEGIN_CLASS)
OPCODE(END_CLASS)
OPCODE(STORE_CLASS_ATTR)
/**************************/
OPCODE(WITH_ENTER)
OPCODE(WITH_EXIT)
/**************************/
OPCODE(TRY_BLOCK_ENTER)
OPCODE(TRY_BLOCK_EXIT)
OPCODE(ASSERT)
OPCODE(EXCEPTION_MATCH)
OPCODE(RAISE)
OPCODE(RE_RAISE)
/**************************/
#endif