rename emit into emit_ to make QT happy

This commit is contained in:
blueloveTH 2023-10-16 13:56:07 +08:00
parent f3acafe44c
commit 901f702f00
3 changed files with 260 additions and 260 deletions

View File

@ -15,7 +15,7 @@ typedef std::unique_ptr<Expr> Expr_;
struct Expr{
int line = 0;
virtual ~Expr() = default;
virtual void emit(CodeEmitContext* ctx) = 0;
virtual void emit_(CodeEmitContext* ctx) = 0;
virtual bool is_literal() const { return false; }
virtual bool is_json_object() const { return false; }
virtual bool is_attrib() const { return false; }
@ -60,7 +60,7 @@ struct CodeEmitContext{
void exit_block();
void emit_expr(); // clear the expression stack and generate bytecode
std::string _log_s_expr();
int emit(Opcode opcode, uint16_t arg, int line);
int emit_(Opcode opcode, uint16_t arg, int line);
void patch_jump(int index);
bool add_label(StrName name);
int add_varname(StrName name);
@ -73,7 +73,7 @@ struct NameExpr: Expr{
StrName name;
NameScope scope;
NameExpr(StrName name, NameScope scope): name(name), scope(scope) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
bool is_name() const override { return true; }
@ -82,7 +82,7 @@ struct NameExpr: Expr{
struct InvertExpr: Expr{
Expr_ child;
InvertExpr(Expr_&& child): child(std::move(child)) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct StarredExpr: Expr{
@ -90,26 +90,26 @@ struct StarredExpr: Expr{
Expr_ child;
StarredExpr(int level, Expr_&& child): level(level), child(std::move(child)) {}
int star_level() const override { return level; }
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
};
struct NotExpr: Expr{
Expr_ child;
NotExpr(Expr_&& child): child(std::move(child)) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct AndExpr: Expr{
Expr_ lhs;
Expr_ rhs;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct OrExpr: Expr{
Expr_ lhs;
Expr_ rhs;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
// [None, True, False, ...]
@ -118,26 +118,26 @@ struct Literal0Expr: Expr{
Literal0Expr(TokenIndex token): token(token) {}
bool is_json_object() const override { return true; }
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct LongExpr: Expr{
Str s;
LongExpr(const Str& s): s(s) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct BytesExpr: Expr{
Str s;
BytesExpr(const Str& s): s(s) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
// @num, @str which needs to invoke OP_LOAD_CONST
struct LiteralExpr: Expr{
TokenValue value;
LiteralExpr(TokenValue value): value(value) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
bool is_literal() const override { return true; }
bool is_json_object() const override { return true; }
};
@ -145,7 +145,7 @@ struct LiteralExpr: Expr{
struct NegatedExpr: Expr{
Expr_ child;
NegatedExpr(Expr_&& child): child(std::move(child)) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
bool is_json_object() const override { return child->is_literal(); }
};
@ -153,14 +153,14 @@ struct SliceExpr: Expr{
Expr_ start;
Expr_ stop;
Expr_ step;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct DictItemExpr: Expr{
Expr_ key; // maybe nullptr if it is **kwargs
Expr_ value;
int star_level() const override { return value->star_level(); }
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct SequenceExpr: Expr{
@ -168,9 +168,9 @@ struct SequenceExpr: Expr{
SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {}
virtual Opcode opcode() const = 0;
void emit(CodeEmitContext* ctx) override {
for(auto& item: items) item->emit(ctx);
ctx->emit(opcode(), items.size(), line);
void emit_(CodeEmitContext* ctx) override {
for(auto& item: items) item->emit_(ctx);
ctx->emit_(opcode(), items.size(), line);
}
};
@ -223,7 +223,7 @@ struct CompExpr: Expr{
virtual Opcode op0() = 0;
virtual Opcode op1() = 0;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct ListCompExpr: CompExpr{
@ -246,9 +246,9 @@ struct LambdaExpr: Expr{
LambdaExpr(FuncDecl_ decl): decl(decl) {}
void emit(CodeEmitContext* ctx) override {
void emit_(CodeEmitContext* ctx) override {
int index = ctx->add_func_decl(decl);
ctx->emit(OP_LOAD_FUNCTION, index, line);
ctx->emit_(OP_LOAD_FUNCTION, index, line);
}
};
@ -256,13 +256,13 @@ struct FStringExpr: Expr{
Str src;
FStringExpr(const Str& src): src(src) {}
void _load_simple_expr(CodeEmitContext* ctx, Str expr);
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct SubscrExpr: Expr{
Expr_ a;
Expr_ b;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
};
@ -273,7 +273,7 @@ struct AttribExpr: Expr{
AttribExpr(Expr_ a, const Str& b): a(std::move(a)), b(b) {}
AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {}
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
void emit_method(CodeEmitContext* ctx);
@ -285,15 +285,15 @@ struct CallExpr: Expr{
std::vector<Expr_> args;
// **a will be interpreted as a special keyword argument: {"**": a}
std::vector<std::pair<Str, Expr_>> kwargs;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
struct GroupedExpr: Expr{
Expr_ a;
GroupedExpr(Expr_&& a): a(std::move(a)) {}
void emit(CodeEmitContext* ctx) override{
a->emit(ctx);
void emit_(CodeEmitContext* ctx) override{
a->emit_(ctx);
}
bool emit_del(CodeEmitContext* ctx) override {
@ -311,7 +311,7 @@ struct BinaryExpr: Expr{
Expr_ rhs;
bool is_compare() const override;
void _emit_compare(CodeEmitContext* ctx, std::vector<int>& jmps);
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};
@ -319,7 +319,7 @@ struct TernaryExpr: Expr{
Expr_ cond;
Expr_ true_expr;
Expr_ false_expr;
void emit(CodeEmitContext* ctx) override;
void emit_(CodeEmitContext* ctx) override;
};

View File

@ -30,8 +30,8 @@ namespace pkpy{
// add a `return None` in the end as a guard
// previously, we only do this if the last opcode is not a return
// however, this is buggy...since there may be a jump to the end (out of bound) even if the last opcode is a return
ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
// some check here
std::vector<Bytecode>& codes = ctx()->co->codes;
if(ctx()->co->varnames.size() > PK_MAX_CO_VARNAMES){
@ -215,7 +215,7 @@ namespace pkpy{
}
// https://github.com/blueloveTH/pocketpy/issues/37
parse_expression(PREC_LAMBDA + 1, false);
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
pop_context();
ctx()->s_expr.push(std::move(e));
}
@ -518,7 +518,7 @@ __SUBSCR_END:
do {
consume(TK("@id"));
Str name = prev().str();
ctx()->emit(OP_IMPORT_PATH, ctx()->add_const(VAR(name)), prev().line);
ctx()->emit_(OP_IMPORT_PATH, ctx()->add_const(VAR(name)), prev().line);
if (match(TK("as"))) {
consume(TK("@id"));
name = prev().str();
@ -570,29 +570,29 @@ __EAT_DOTS_END:
}
}
ctx()->emit(OP_IMPORT_PATH, ctx()->add_const(VAR(ss.str())), prev().line);
ctx()->emit_(OP_IMPORT_PATH, ctx()->add_const(VAR(ss.str())), prev().line);
consume(TK("import"));
if (match(TK("*"))) {
if(name_scope() != NAME_GLOBAL) SyntaxError("from <module> import * can only be used in global scope");
// pop the module and import __all__
ctx()->emit(OP_POP_IMPORT_STAR, BC_NOARG, prev().line);
ctx()->emit_(OP_POP_IMPORT_STAR, BC_NOARG, prev().line);
consume_end_stmt();
return;
}
do {
ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
consume(TK("@id"));
Str name = prev().str();
ctx()->emit(OP_LOAD_ATTR, StrName(name).index, prev().line);
ctx()->emit_(OP_LOAD_ATTR, StrName(name).index, prev().line);
if (match(TK("as"))) {
consume(TK("@id"));
name = prev().str();
}
ctx()->emit_store_name(name_scope(), StrName(name), prev().line);
} while (match(TK(",")));
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
consume_end_stmt();
}
@ -618,15 +618,15 @@ __EAT_DOTS_END:
void Compiler::compile_if_stmt() {
EXPR(false); // condition
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
compile_block_body();
if (match(TK("elif"))) {
int exit_patch = ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
int exit_patch = ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
ctx()->patch_jump(patch);
compile_if_stmt();
ctx()->patch_jump(exit_patch);
} else if (match(TK("else"))) {
int exit_patch = ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
int exit_patch = ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line);
ctx()->patch_jump(patch);
compile_block_body();
ctx()->patch_jump(exit_patch);
@ -638,9 +638,9 @@ __EAT_DOTS_END:
void Compiler::compile_while_loop() {
CodeBlock* block = ctx()->enter_block(WHILE_LOOP);
EXPR(false); // condition
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
compile_block_body();
ctx()->emit(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
ctx()->patch_jump(patch);
ctx()->exit_block();
// optional else clause
@ -654,13 +654,13 @@ __EAT_DOTS_END:
Expr_ vars = EXPR_VARS();
consume(TK("in"));
EXPR_TUPLE(false);
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
CodeBlock* block = ctx()->enter_block(FOR_LOOP);
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
bool ok = vars->emit_store(ctx());
if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
compile_block_body();
ctx()->emit(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
ctx()->exit_block();
// optional else clause
if (match(TK("else"))) {
@ -673,25 +673,25 @@ __EAT_DOTS_END:
ctx()->enter_block(TRY_EXCEPT);
compile_block_body();
std::vector<int> patches = {
ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
};
ctx()->exit_block();
do {
consume(TK("except"));
if(match(TK("@id"))){
ctx()->emit(OP_EXCEPTION_MATCH, StrName(prev().sv()).index, prev().line);
ctx()->emit_(OP_EXCEPTION_MATCH, StrName(prev().sv()).index, prev().line);
}else{
ctx()->emit(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
}
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
// pop the exception on match
ctx()->emit(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
compile_block_body();
patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
patches.push_back(ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
ctx()->patch_jump(patch);
}while(curr().type == TK("except"));
// no match, re-raise
ctx()->emit(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
for (int patch : patches) ctx()->patch_jump(patch);
}
@ -720,7 +720,7 @@ __EAT_DOTS_END:
EXPR_TUPLE();
e->rhs = ctx()->s_expr.popx();
if(e->is_starred()) SyntaxError();
e->emit(ctx());
e->emit_(ctx());
bool ok = lhs_p->emit_store(ctx());
if(!ok) SyntaxError();
} return true;
@ -739,8 +739,8 @@ __EAT_DOTS_END:
}
// stack size is n+1
Expr_ val = ctx()->s_expr.popx();
val->emit(ctx());
for(int j=1; j<n; j++) ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
val->emit_(ctx());
for(int j=1; j<n; j++) ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
for(int j=0; j<n; j++){
auto e = ctx()->s_expr.popx();
if(e->is_starred()) SyntaxError();
@ -759,12 +759,12 @@ __EAT_DOTS_END:
switch(prev().type){
case TK("break"):
if (curr_loop_block < 0) SyntaxError("'break' outside loop");
ctx()->emit(OP_LOOP_BREAK, curr_loop_block, kw_line);
ctx()->emit_(OP_LOOP_BREAK, curr_loop_block, kw_line);
consume_end_stmt();
break;
case TK("continue"):
if (curr_loop_block < 0) SyntaxError("'continue' not properly in loop");
ctx()->emit(OP_LOOP_CONTINUE, curr_loop_block, kw_line);
ctx()->emit_(OP_LOOP_CONTINUE, curr_loop_block, kw_line);
consume_end_stmt();
break;
case TK("yield"):
@ -772,7 +772,7 @@ __EAT_DOTS_END:
EXPR_TUPLE(false);
// if yield present, mark the function as generator
ctx()->co->is_generator = true;
ctx()->emit(OP_YIELD_VALUE, BC_NOARG, kw_line);
ctx()->emit_(OP_YIELD_VALUE, BC_NOARG, kw_line);
consume_end_stmt();
break;
case TK("yield from"):
@ -780,23 +780,23 @@ __EAT_DOTS_END:
EXPR_TUPLE(false);
// if yield from present, mark the function as generator
ctx()->co->is_generator = true;
ctx()->emit(OP_GET_ITER, BC_NOARG, kw_line);
ctx()->emit_(OP_GET_ITER, BC_NOARG, kw_line);
ctx()->enter_block(FOR_LOOP);
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_YIELD_VALUE, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_YIELD_VALUE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
ctx()->exit_block();
consume_end_stmt();
break;
case TK("return"):
if (contexts.size() <= 1) SyntaxError("'return' outside function");
if(match_end_stmt()){
ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line);
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, kw_line);
}else{
EXPR_TUPLE(false);
consume_end_stmt();
}
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, kw_line);
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, kw_line);
break;
/*************************************************/
case TK("if"): compile_if_stmt(); break;
@ -817,10 +817,10 @@ __EAT_DOTS_END:
if(is_global) scope = NAME_GLOBAL;
switch(scope){
case NAME_LOCAL:
ctx()->emit(OP_INC_FAST, ctx()->add_varname(name), prev().line);
ctx()->emit_(OP_INC_FAST, ctx()->add_varname(name), prev().line);
break;
case NAME_GLOBAL:
ctx()->emit(OP_INC_GLOBAL, name.index, prev().line);
ctx()->emit_(OP_INC_GLOBAL, name.index, prev().line);
break;
default: SyntaxError(); break;
}
@ -832,10 +832,10 @@ __EAT_DOTS_END:
StrName name(prev().sv());
switch(name_scope()){
case NAME_LOCAL:
ctx()->emit(OP_DEC_FAST, ctx()->add_varname(name), prev().line);
ctx()->emit_(OP_DEC_FAST, ctx()->add_varname(name), prev().line);
break;
case NAME_GLOBAL:
ctx()->emit(OP_DEC_GLOBAL, name.index, prev().line);
ctx()->emit_(OP_DEC_GLOBAL, name.index, prev().line);
break;
default: SyntaxError(); break;
}
@ -844,13 +844,13 @@ __EAT_DOTS_END:
}
case TK("assert"):{
EXPR(false); // condition
int index = ctx()->emit(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
int index = ctx()->emit_(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
int has_msg = 0;
if(match(TK(","))){
EXPR(false); // message
has_msg = 1;
}
ctx()->emit(OP_RAISE_ASSERT, has_msg, kw_line);
ctx()->emit_(OP_RAISE_ASSERT, has_msg, kw_line);
ctx()->patch_jump(index);
consume_end_stmt();
break;
@ -868,9 +868,9 @@ __EAT_DOTS_END:
if(match(TK("(")) && !match(TK(")"))){
EXPR(false); consume(TK(")"));
}else{
ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line);
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, kw_line);
}
ctx()->emit(OP_RAISE, dummy_t, kw_line);
ctx()->emit_(OP_RAISE, dummy_t, kw_line);
consume_end_stmt();
} break;
case TK("del"): {
@ -887,11 +887,11 @@ __EAT_DOTS_END:
Expr_ e = make_expr<NameExpr>(prev().str(), name_scope());
bool ok = e->emit_store(ctx());
if(!ok) SyntaxError();
e->emit(ctx());
ctx()->emit(OP_WITH_ENTER, BC_NOARG, prev().line);
e->emit_(ctx());
ctx()->emit_(OP_WITH_ENTER, BC_NOARG, prev().line);
compile_block_body();
e->emit(ctx());
ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line);
e->emit_(ctx());
ctx()->emit_(OP_WITH_EXIT, BC_NOARG, prev().line);
} break;
/*************************************************/
case TK("=="): {
@ -905,7 +905,7 @@ __EAT_DOTS_END:
case TK("->"):
consume(TK("@id"));
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
ctx()->emit(OP_GOTO, StrName(prev().sv()).index, prev().line);
ctx()->emit_(OP_GOTO, StrName(prev().sv()).index, prev().line);
consume_end_stmt();
break;
/*************************************************/
@ -929,9 +929,9 @@ __EAT_DOTS_END:
if(!is_typed_name){
ctx()->emit_expr();
if((mode()==CELL_MODE || mode()==REPL_MODE) && name_scope()==NAME_GLOBAL){
ctx()->emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
}else{
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
}
}else{
PK_ASSERT(ctx()->s_expr.size() == 1)
@ -960,15 +960,15 @@ __EAT_DOTS_END:
consume(TK(")"));
}
if(base == nullptr){
ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
ctx()->emit_(OP_LOAD_NONE, BC_NOARG, prev().line);
}else {
base->emit(ctx());
base->emit_(ctx());
}
ctx()->emit(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
ctx()->emit_(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
ctx()->is_compiling_class = true;
compile_block_body();
ctx()->is_compiling_class = false;
ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_END_CLASS, BC_NOARG, BC_KEEPLINE);
}
void Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints){
@ -1062,22 +1062,22 @@ __EAT_DOTS_END:
if(docstring != nullptr){
decl->docstring = PK_OBJ_GET(Str, docstring);
}
ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
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_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_ROT_TWO, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_CALL, 1, (*it)->line);
(*it)->emit_(ctx());
ctx()->emit_(OP_ROT_TWO, BC_NOARG, (*it)->line);
ctx()->emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_ROT_TWO, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_CALL, 1, (*it)->line);
}
if(!ctx()->is_compiling_class){
auto e = make_expr<NameExpr>(decl_name, name_scope());
e->emit_store(ctx());
}else{
int index = StrName(decl_name).index;
ctx()->emit(OP_STORE_CLASS_ATTR, index, prev().line);
ctx()->emit_(OP_STORE_CLASS_ATTR, index, prev().line);
}
}
@ -1143,7 +1143,7 @@ __EAT_DOTS_END:
if(mode()==EVAL_MODE) {
EXPR_TUPLE(false);
consume(TK("@eof"));
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
pop_context();
return code;
}else if(mode()==JSON_MODE){
@ -1151,8 +1151,8 @@ __EAT_DOTS_END:
Expr_ e = ctx()->s_expr.popx();
if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array");
consume(TK("@eof"));
e->emit(ctx());
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
e->emit_(ctx());
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
pop_context();
return code;
}

View File

@ -30,7 +30,7 @@ namespace pkpy{
if(curr_type == FOR_LOOP){
// add a no op here to make block check work
emit(OP_NO_OP, BC_NOARG, BC_KEEPLINE);
emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE);
}
}
@ -40,7 +40,7 @@ namespace pkpy{
throw std::runtime_error("s_expr.size() != 1\n" + _log_s_expr());
}
Expr_ expr = s_expr.popx();
expr->emit(this);
expr->emit_(this);
}
std::string CodeEmitContext::_log_s_expr(){
@ -49,7 +49,7 @@ namespace pkpy{
return ss.str();
}
int CodeEmitContext::emit(Opcode opcode, uint16_t arg, int line) {
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line) {
co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
co->iblocks.push_back(curr_block_i);
co->lines.push_back(line);
@ -108,41 +108,41 @@ namespace pkpy{
void CodeEmitContext::emit_store_name(NameScope scope, StrName name, int line){
switch(scope){
case NAME_LOCAL:
emit(OP_STORE_FAST, add_varname(name), line);
emit_(OP_STORE_FAST, add_varname(name), line);
break;
case NAME_GLOBAL:
emit(OP_STORE_GLOBAL, StrName(name).index, line);
emit_(OP_STORE_GLOBAL, StrName(name).index, line);
break;
case NAME_GLOBAL_UNKNOWN:
emit(OP_STORE_NAME, StrName(name).index, line);
emit_(OP_STORE_NAME, StrName(name).index, line);
break;
default: FATAL_ERROR(); break;
}
}
void NameExpr::emit(CodeEmitContext* ctx) {
void NameExpr::emit_(CodeEmitContext* ctx) {
int index = ctx->co->varnames_inv.try_get(name);
if(scope == NAME_LOCAL && index >= 0){
ctx->emit(OP_LOAD_FAST, index, line);
ctx->emit_(OP_LOAD_FAST, index, line);
}else{
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
// we cannot determine the scope when calling exec()/eval()
if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
ctx->emit(op, StrName(name).index, line);
ctx->emit_(op, StrName(name).index, line);
}
}
bool NameExpr::emit_del(CodeEmitContext* ctx) {
switch(scope){
case NAME_LOCAL:
ctx->emit(OP_DELETE_FAST, ctx->add_varname(name), line);
ctx->emit_(OP_DELETE_FAST, ctx->add_varname(name), line);
break;
case NAME_GLOBAL:
ctx->emit(OP_DELETE_GLOBAL, StrName(name).index, line);
ctx->emit_(OP_DELETE_GLOBAL, StrName(name).index, line);
break;
case NAME_GLOBAL_UNKNOWN:
ctx->emit(OP_DELETE_NAME, StrName(name).index, line);
ctx->emit_(OP_DELETE_NAME, StrName(name).index, line);
break;
default: FATAL_ERROR(); break;
}
@ -151,21 +151,21 @@ namespace pkpy{
bool NameExpr::emit_store(CodeEmitContext* ctx) {
if(ctx->is_compiling_class){
ctx->emit(OP_STORE_CLASS_ATTR, name.index, line);
ctx->emit_(OP_STORE_CLASS_ATTR, name.index, line);
return true;
}
ctx->emit_store_name(scope, name, line);
return true;
}
void InvertExpr::emit(CodeEmitContext* ctx) {
child->emit(ctx);
ctx->emit(OP_UNARY_INVERT, BC_NOARG, line);
void InvertExpr::emit_(CodeEmitContext* ctx) {
child->emit_(ctx);
ctx->emit_(OP_UNARY_INVERT, BC_NOARG, line);
}
void StarredExpr::emit(CodeEmitContext* ctx) {
child->emit(ctx);
ctx->emit(OP_UNARY_STAR, level, line);
void StarredExpr::emit_(CodeEmitContext* ctx) {
child->emit_(ctx);
ctx->emit_(OP_UNARY_STAR, level, line);
}
bool StarredExpr::emit_store(CodeEmitContext* ctx) {
@ -174,54 +174,54 @@ namespace pkpy{
return child->emit_store(ctx);
}
void NotExpr::emit(CodeEmitContext* ctx) {
child->emit(ctx);
ctx->emit(OP_UNARY_NOT, BC_NOARG, line);
void NotExpr::emit_(CodeEmitContext* ctx) {
child->emit_(ctx);
ctx->emit_(OP_UNARY_NOT, BC_NOARG, line);
}
void AndExpr::emit(CodeEmitContext* ctx) {
lhs->emit(ctx);
int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
rhs->emit(ctx);
void AndExpr::emit_(CodeEmitContext* ctx) {
lhs->emit_(ctx);
int patch = ctx->emit_(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
rhs->emit_(ctx);
ctx->patch_jump(patch);
}
void OrExpr::emit(CodeEmitContext* ctx) {
lhs->emit(ctx);
int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
rhs->emit(ctx);
void OrExpr::emit_(CodeEmitContext* ctx) {
lhs->emit_(ctx);
int patch = ctx->emit_(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
rhs->emit_(ctx);
ctx->patch_jump(patch);
}
void Literal0Expr::emit(CodeEmitContext* ctx){
void Literal0Expr::emit_(CodeEmitContext* ctx){
switch (token) {
case TK("None"): ctx->emit(OP_LOAD_NONE, BC_NOARG, line); break;
case TK("True"): ctx->emit(OP_LOAD_TRUE, BC_NOARG, line); break;
case TK("False"): ctx->emit(OP_LOAD_FALSE, BC_NOARG, line); break;
case TK("..."): ctx->emit(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
case TK("None"): ctx->emit_(OP_LOAD_NONE, BC_NOARG, line); break;
case TK("True"): ctx->emit_(OP_LOAD_TRUE, BC_NOARG, line); break;
case TK("False"): ctx->emit_(OP_LOAD_FALSE, BC_NOARG, line); break;
case TK("..."): ctx->emit_(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
default: FATAL_ERROR();
}
}
void LongExpr::emit(CodeEmitContext* ctx) {
void LongExpr::emit_(CodeEmitContext* ctx) {
VM* vm = ctx->vm;
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
ctx->emit(OP_BUILD_LONG, BC_NOARG, line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
ctx->emit_(OP_BUILD_LONG, BC_NOARG, line);
}
void BytesExpr::emit(CodeEmitContext* ctx) {
void BytesExpr::emit_(CodeEmitContext* ctx) {
VM* vm = ctx->vm;
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
ctx->emit(OP_BUILD_BYTES, BC_NOARG, line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
ctx->emit_(OP_BUILD_BYTES, BC_NOARG, line);
}
void LiteralExpr::emit(CodeEmitContext* ctx) {
void LiteralExpr::emit_(CodeEmitContext* ctx) {
VM* vm = ctx->vm;
PyObject* obj = nullptr;
if(std::holds_alternative<i64>(value)){
i64 _val = std::get<i64>(value);
if(_val >= INT16_MIN && _val <= INT16_MAX){
ctx->emit(OP_LOAD_INTEGER, (uint16_t)_val, line);
ctx->emit_(OP_LOAD_INTEGER, (uint16_t)_val, line);
return;
}
obj = VAR(_val);
@ -233,10 +233,10 @@ namespace pkpy{
obj = VAR(std::get<Str>(value));
}
if(obj == nullptr) FATAL_ERROR();
ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(obj), line);
}
void NegatedExpr::emit(CodeEmitContext* ctx){
void NegatedExpr::emit_(CodeEmitContext* ctx){
VM* vm = ctx->vm;
// if child is a int of float, do constant folding
if(child->is_literal()){
@ -244,53 +244,53 @@ namespace pkpy{
if(std::holds_alternative<i64>(lit->value)){
i64 _val = -std::get<i64>(lit->value);
if(_val >= INT16_MIN && _val <= INT16_MAX){
ctx->emit(OP_LOAD_INTEGER, (uint16_t)_val, line);
ctx->emit_(OP_LOAD_INTEGER, (uint16_t)_val, line);
}else{
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
}
return;
}
if(std::holds_alternative<f64>(lit->value)){
PyObject* obj = VAR(-std::get<f64>(lit->value));
ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(obj), line);
return;
}
}
child->emit(ctx);
ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
child->emit_(ctx);
ctx->emit_(OP_UNARY_NEGATIVE, BC_NOARG, line);
}
void SliceExpr::emit(CodeEmitContext* ctx){
void SliceExpr::emit_(CodeEmitContext* ctx){
if(start){
start->emit(ctx);
start->emit_(ctx);
}else{
ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
}
if(stop){
stop->emit(ctx);
stop->emit_(ctx);
}else{
ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
}
if(step){
step->emit(ctx);
step->emit_(ctx);
}else{
ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
}
ctx->emit(OP_BUILD_SLICE, BC_NOARG, line);
ctx->emit_(OP_BUILD_SLICE, BC_NOARG, line);
}
void DictItemExpr::emit(CodeEmitContext* ctx) {
void DictItemExpr::emit_(CodeEmitContext* ctx) {
if(is_starred()){
PK_ASSERT(key == nullptr);
value->emit(ctx);
value->emit_(ctx);
}else{
value->emit(ctx);
key->emit(ctx); // reverse order
ctx->emit(OP_BUILD_TUPLE, 2, line);
value->emit_(ctx);
key->emit_(ctx); // reverse order
ctx->emit_(OP_BUILD_TUPLE, 2, line);
}
}
@ -311,7 +311,7 @@ namespace pkpy{
prev.op = OP_NO_OP;
prev.arg = BC_NOARG;
}else{
ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
}
}else{
// starred assignment target must be in a tuple
@ -320,7 +320,7 @@ namespace pkpy{
if(starred_i != items.size()-1) return false;
// a,*b = [1,2,3]
// stack is [1,2,3] -> [1,[2,3]]
ctx->emit(OP_UNPACK_EX, items.size()-1, line);
ctx->emit_(OP_UNPACK_EX, items.size()-1, line);
}
// do reverse emit
for(int i=items.size()-1; i>=0; i--){
@ -338,26 +338,26 @@ namespace pkpy{
return true;
}
void CompExpr::emit(CodeEmitContext* ctx){
ctx->emit(op0(), 0, line);
iter->emit(ctx);
ctx->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
void CompExpr::emit_(CodeEmitContext* ctx){
ctx->emit_(op0(), 0, line);
iter->emit_(ctx);
ctx->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
ctx->enter_block(FOR_LOOP);
ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
ctx->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
bool ok = vars->emit_store(ctx);
// this error occurs in `vars` instead of this line, but...nevermind
PK_ASSERT(ok); // TODO: raise a SyntaxError instead
if(cond){
cond->emit(ctx);
int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
expr->emit(ctx);
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
cond->emit_(ctx);
int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
expr->emit_(ctx);
ctx->emit_(op1(), BC_NOARG, BC_KEEPLINE);
ctx->patch_jump(patch);
}else{
expr->emit(ctx);
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
expr->emit_(ctx);
ctx->emit_(op1(), BC_NOARG, BC_KEEPLINE);
}
ctx->emit(OP_LOOP_CONTINUE, ctx->get_loop(), BC_KEEPLINE);
ctx->emit_(OP_LOOP_CONTINUE, ctx->get_loop(), BC_KEEPLINE);
ctx->exit_block();
}
@ -376,24 +376,24 @@ namespace pkpy{
if(std::regex_match(expr.str(), pattern)){
int dot = expr.index(".");
if(dot < 0){
ctx->emit(OP_LOAD_NAME, StrName(expr.sv()).index, line);
ctx->emit_(OP_LOAD_NAME, StrName(expr.sv()).index, line);
}else{
StrName name(expr.substr(0, dot).sv());
StrName attr(expr.substr(dot+1).sv());
ctx->emit(OP_LOAD_NAME, name.index, line);
ctx->emit(OP_LOAD_ATTR, attr.index, line);
ctx->emit_(OP_LOAD_NAME, name.index, line);
ctx->emit_(OP_LOAD_ATTR, attr.index, line);
}
}else{
int index = ctx->add_const(py_var(ctx->vm, expr));
ctx->emit(OP_LOAD_CONST, index, line);
ctx->emit(OP_EVAL, BC_NOARG, line);
ctx->emit_(OP_LOAD_CONST, index, line);
ctx->emit_(OP_EVAL, BC_NOARG, line);
}
if(repr){
ctx->emit(OP_REPR, BC_NOARG, line);
ctx->emit_(OP_REPR, BC_NOARG, line);
}
}
void FStringExpr::emit(CodeEmitContext* ctx){
void FStringExpr::emit_(CodeEmitContext* ctx){
VM* vm = ctx->vm;
PK_LOCAL_STATIC const std::regex pattern(R"(\{(.*?)\})");
std::cregex_iterator begin(src.begin(), src.end(), pattern);
@ -404,7 +404,7 @@ namespace pkpy{
std::cmatch m = *it;
if (i < m.position()) {
Str literal = src.substr(i, m.position() - i);
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
size++;
}
Str expr = m[1].str();
@ -412,7 +412,7 @@ namespace pkpy{
if(conon >= 0){
_load_simple_expr(ctx, expr.substr(0, conon));
Str spec = expr.substr(conon+1);
ctx->emit(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
ctx->emit_(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
}else{
_load_simple_expr(ctx, expr);
}
@ -421,60 +421,60 @@ namespace pkpy{
}
if (i < src.length()) {
Str literal = src.substr(i, src.length() - i);
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
size++;
}
ctx->emit(OP_BUILD_STRING, size, line);
ctx->emit_(OP_BUILD_STRING, size, line);
}
void SubscrExpr::emit(CodeEmitContext* ctx){
a->emit(ctx);
b->emit(ctx);
ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line);
void SubscrExpr::emit_(CodeEmitContext* ctx){
a->emit_(ctx);
b->emit_(ctx);
ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line);
}
bool SubscrExpr::emit_del(CodeEmitContext* ctx){
a->emit(ctx);
b->emit(ctx);
ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line);
a->emit_(ctx);
b->emit_(ctx);
ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line);
return true;
}
bool SubscrExpr::emit_store(CodeEmitContext* ctx){
a->emit(ctx);
b->emit(ctx);
ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line);
a->emit_(ctx);
b->emit_(ctx);
ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
return true;
}
void AttribExpr::emit(CodeEmitContext* ctx){
a->emit(ctx);
void AttribExpr::emit_(CodeEmitContext* ctx){
a->emit_(ctx);
int index = StrName(b).index;
ctx->emit(OP_LOAD_ATTR, index, line);
ctx->emit_(OP_LOAD_ATTR, index, line);
}
bool AttribExpr::emit_del(CodeEmitContext* ctx) {
a->emit(ctx);
a->emit_(ctx);
int index = StrName(b).index;
ctx->emit(OP_DELETE_ATTR, index, line);
ctx->emit_(OP_DELETE_ATTR, index, line);
return true;
}
bool AttribExpr::emit_store(CodeEmitContext* ctx){
a->emit(ctx);
a->emit_(ctx);
int index = StrName(b).index;
ctx->emit(OP_STORE_ATTR, index, line);
ctx->emit_(OP_STORE_ATTR, index, line);
return true;
}
void AttribExpr::emit_method(CodeEmitContext* ctx) {
a->emit(ctx);
a->emit_(ctx);
int index = StrName(b).index;
ctx->emit(OP_LOAD_METHOD, index, line);
ctx->emit_(OP_LOAD_METHOD, index, line);
}
void CallExpr::emit(CodeEmitContext* ctx) {
void CallExpr::emit_(CodeEmitContext* ctx) {
bool vargs = false;
bool vkwargs = false;
for(auto& arg: args) if(arg->is_starred()) vargs = true;
@ -485,43 +485,43 @@ namespace pkpy{
auto p = static_cast<AttribExpr*>(callable.get());
p->emit_method(ctx); // OP_LOAD_METHOD
}else{
callable->emit(ctx);
ctx->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
callable->emit_(ctx);
ctx->emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
}
if(vargs || vkwargs){
for(auto& item: args) item->emit(ctx);
ctx->emit(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
for(auto& item: args) item->emit_(ctx);
ctx->emit_(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
if(!kwargs.empty()){
for(auto& item: kwargs){
if(item.second->is_starred()){
if(item.second->star_level() != 2) FATAL_ERROR();
item.second->emit(ctx);
item.second->emit_(ctx);
}else{
// k=v
int index = ctx->add_const(py_var(ctx->vm, item.first));
ctx->emit(OP_LOAD_CONST, index, line);
item.second->emit(ctx);
ctx->emit(OP_BUILD_TUPLE, 2, line);
ctx->emit_(OP_LOAD_CONST, index, line);
item.second->emit_(ctx);
ctx->emit_(OP_BUILD_TUPLE, 2, line);
}
}
ctx->emit(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
ctx->emit(OP_CALL_TP, 1, line);
ctx->emit_(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
ctx->emit_(OP_CALL_TP, 1, line);
}else{
ctx->emit(OP_CALL_TP, 0, line);
ctx->emit_(OP_CALL_TP, 0, line);
}
}else{
// vectorcall protocal
for(auto& item: args) item->emit(ctx);
for(auto& item: args) item->emit_(ctx);
for(auto& item: kwargs){
uint16_t index = StrName(item.first.sv()).index;
ctx->emit(OP_LOAD_INTEGER, index, line);
item.second->emit(ctx);
ctx->emit_(OP_LOAD_INTEGER, index, line);
item.second->emit_(ctx);
}
int KWARGC = kwargs.size();
int ARGC = args.size();
ctx->emit(OP_CALL, (KWARGC<<8)|ARGC, line);
ctx->emit_(OP_CALL, (KWARGC<<8)|ARGC, line);
}
}
@ -538,26 +538,26 @@ namespace pkpy{
if(lhs->is_compare()){
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
}else{
lhs->emit(ctx); // [a]
lhs->emit_(ctx); // [a]
}
rhs->emit(ctx); // [a, b]
ctx->emit(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
ctx->emit(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
rhs->emit_(ctx); // [a, b]
ctx->emit_(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
ctx->emit_(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
switch(op){
case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
default: UNREACHABLE();
}
// [b, RES]
int index = ctx->emit(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
int index = ctx->emit_(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
jmps.push_back(index);
}
void BinaryExpr::emit(CodeEmitContext* ctx) {
void BinaryExpr::emit_(CodeEmitContext* ctx) {
std::vector<int> jmps;
if(is_compare() && lhs->is_compare()){
// (a < b) < c
@ -565,51 +565,51 @@ namespace pkpy{
// [b, RES]
}else{
// (1 + 2) < c
lhs->emit(ctx);
lhs->emit_(ctx);
}
rhs->emit(ctx);
rhs->emit_(ctx);
switch (op) {
case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
case TK("-"): ctx->emit(OP_BINARY_SUB, BC_NOARG, line); break;
case TK("*"): ctx->emit(OP_BINARY_MUL, BC_NOARG, line); break;
case TK("/"): ctx->emit(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
case TK("//"): ctx->emit(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
case TK("%"): ctx->emit(OP_BINARY_MOD, BC_NOARG, line); break;
case TK("**"): ctx->emit(OP_BINARY_POW, BC_NOARG, line); break;
case TK("+"): ctx->emit_(OP_BINARY_ADD, BC_NOARG, line); break;
case TK("-"): ctx->emit_(OP_BINARY_SUB, BC_NOARG, line); break;
case TK("*"): ctx->emit_(OP_BINARY_MUL, BC_NOARG, line); break;
case TK("/"): ctx->emit_(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
case TK("//"): ctx->emit_(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
case TK("%"): ctx->emit_(OP_BINARY_MOD, BC_NOARG, line); break;
case TK("**"): ctx->emit_(OP_BINARY_POW, BC_NOARG, line); break;
case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break;
case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break;
case TK("is"): ctx->emit(OP_IS_OP, 0, line); break;
case TK("is not"): ctx->emit(OP_IS_OP, 1, line); break;
case TK("in"): ctx->emit_(OP_CONTAINS_OP, 0, line); break;
case TK("not in"): ctx->emit_(OP_CONTAINS_OP, 1, line); break;
case TK("is"): ctx->emit_(OP_IS_OP, 0, line); break;
case TK("is not"): ctx->emit_(OP_IS_OP, 1, line); break;
case TK("<<"): ctx->emit(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
case TK(">>"): ctx->emit(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
case TK("&"): ctx->emit(OP_BITWISE_AND, BC_NOARG, line); break;
case TK("|"): ctx->emit(OP_BITWISE_OR, BC_NOARG, line); break;
case TK("^"): ctx->emit(OP_BITWISE_XOR, BC_NOARG, line); break;
case TK("<<"): ctx->emit_(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
case TK(">>"): ctx->emit_(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
case TK("&"): ctx->emit_(OP_BITWISE_AND, BC_NOARG, line); break;
case TK("|"): ctx->emit_(OP_BITWISE_OR, BC_NOARG, line); break;
case TK("^"): ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break;
case TK("@"): ctx->emit(OP_BINARY_MATMUL, BC_NOARG, line); break;
case TK("@"): ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break;
default: FATAL_ERROR();
}
for(int i: jmps) ctx->patch_jump(i);
}
void TernaryExpr::emit(CodeEmitContext* ctx){
cond->emit(ctx);
int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
true_expr->emit(ctx);
int patch_2 = ctx->emit(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
void TernaryExpr::emit_(CodeEmitContext* ctx){
cond->emit_(ctx);
int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
true_expr->emit_(ctx);
int patch_2 = ctx->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
ctx->patch_jump(patch);
false_expr->emit(ctx);
false_expr->emit_(ctx);
ctx->patch_jump(patch_2);
}