This commit is contained in:
blueloveTH 2023-06-04 21:03:14 +08:00
parent 8e104627cb
commit 919d7a465c
5 changed files with 71 additions and 11 deletions

View File

@ -69,6 +69,12 @@ __NEXT_STEP:;
TARGET(POP_TOP) POP(); DISPATCH(); TARGET(POP_TOP) POP(); DISPATCH();
TARGET(DUP_TOP) PUSH(TOP()); DISPATCH(); TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH(); TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
TARGET(ROT_THREE)
_0 = TOP();
TOP() = SECOND();
SECOND() = THIRD();
THIRD() = _0;
DISPATCH();
TARGET(PRINT_EXPR) TARGET(PRINT_EXPR)
if(TOP() != None) _stdout(this, CAST(Str&, py_repr(TOP())) + "\n"); if(TOP() != None) _stdout(this, CAST(Str&, py_repr(TOP())) + "\n");
POP(); POP();
@ -408,6 +414,12 @@ __NEXT_STEP:;
if(py_bool(TOP()) == false) frame->jump_abs(byte.arg); if(py_bool(TOP()) == false) frame->jump_abs(byte.arg);
else POP(); else POP();
DISPATCH(); DISPATCH();
TARGET(SHORTCUT_IF_FALSE_OR_POP)
if(py_bool(TOP()) == false){ // [b, False]
STACK_SHRINK(2); // []
PUSH(vm->False); // [False]
frame->jump_abs(byte.arg);
} else POP(); // [b]
TARGET(LOOP_CONTINUE) TARGET(LOOP_CONTINUE)
frame->jump_abs(co_blocks[byte.block].start); frame->jump_abs(co_blocks[byte.block].start);
DISPATCH(); DISPATCH();

View File

@ -93,12 +93,12 @@ class Compiler {
rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT }; rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT };
rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT };
rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT };
rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND }; rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND };
@ -107,8 +107,8 @@ class Compiler {
rules[TK("@")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; rules[TK("@")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("if")] = { nullptr, METHOD(exprTernary), PREC_TERNARY }; rules[TK("if")] = { nullptr, METHOD(exprTernary), PREC_TERNARY };
rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE }; rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE };
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND }; rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR }; rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
rules[TK("not")] = { METHOD(exprNot), nullptr, PREC_LOGICAL_NOT }; rules[TK("not")] = { METHOD(exprNot), nullptr, PREC_LOGICAL_NOT };

View File

@ -23,6 +23,7 @@ struct Expr{
virtual bool is_literal() const { return false; } virtual bool is_literal() const { return false; }
virtual bool is_json_object() const { return false; } virtual bool is_json_object() const { return false; }
virtual bool is_attrib() const { return false; } virtual bool is_attrib() const { return false; }
virtual bool is_compare() const { return false; }
// for OP_DELETE_XXX // for OP_DELETE_XXX
[[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; } [[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; }
@ -683,8 +684,50 @@ struct BinaryExpr: Expr{
Expr_ rhs; Expr_ rhs;
std::string str() const override { return TK_STR(op); } std::string str() const override { return TK_STR(op); }
bool is_compare() const override {
switch(op){
case TK("<"): case TK("<="): case TK("=="):
case TK("!="): case TK(">"): case TK(">="): return true;
default: return false;
}
}
void _emit_compare(CodeEmitContext* ctx, std::vector<int>& jmps){
if(lhs->is_compare()){
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
}else{
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]
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;
default: UNREACHABLE();
}
// [b, RES]
int index = ctx->emit(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
jmps.push_back(index);
}
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
lhs->emit(ctx);
if(is_compare() && lhs->is_compare()){
// (a < b) < c
std::vector<int> jmps;
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
// [b, RES]
for(int i: jmps) ctx->patch_jump(i);
}else{
// (1 + 2) < c
lhs->emit(ctx);
}
rhs->emit(ctx); rhs->emit(ctx);
switch (op) { switch (op) {
case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break; case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;

View File

@ -79,9 +79,12 @@ enum Precedence {
PREC_LOGICAL_OR, // or PREC_LOGICAL_OR, // or
PREC_LOGICAL_AND, // and PREC_LOGICAL_AND, // and
PREC_LOGICAL_NOT, // not PREC_LOGICAL_NOT, // not
PREC_EQUALITY, // == != /* https://docs.python.org/3/reference/expressions.html#comparisons
PREC_TEST, // in / is / is not / not in * Unlike C, all comparison operations in Python have the same priority,
PREC_COMPARISION, // < > <= >= * which is lower than that of any arithmetic, shifting or bitwise operation.
* Also unlike C, expressions like a < b < c have the interpretation that is conventional in mathematics.
*/
PREC_COMPARISION, // < > <= >= != ==, in / is / is not / not in
PREC_BITWISE_OR, // | PREC_BITWISE_OR, // |
PREC_BITWISE_XOR, // ^ PREC_BITWISE_XOR, // ^
PREC_BITWISE_AND, // & PREC_BITWISE_AND, // &

View File

@ -6,6 +6,7 @@ OPCODE(NO_OP)
OPCODE(POP_TOP) OPCODE(POP_TOP)
OPCODE(DUP_TOP) OPCODE(DUP_TOP)
OPCODE(ROT_TWO) OPCODE(ROT_TWO)
OPCODE(ROT_THREE)
OPCODE(PRINT_EXPR) OPCODE(PRINT_EXPR)
/**************************/ /**************************/
OPCODE(LOAD_CONST) OPCODE(LOAD_CONST)
@ -75,6 +76,7 @@ OPCODE(JUMP_ABSOLUTE)
OPCODE(POP_JUMP_IF_FALSE) OPCODE(POP_JUMP_IF_FALSE)
OPCODE(JUMP_IF_TRUE_OR_POP) OPCODE(JUMP_IF_TRUE_OR_POP)
OPCODE(JUMP_IF_FALSE_OR_POP) OPCODE(JUMP_IF_FALSE_OR_POP)
OPCODE(SHORTCUT_IF_FALSE_OR_POP)
OPCODE(LOOP_CONTINUE) OPCODE(LOOP_CONTINUE)
OPCODE(LOOP_BREAK) OPCODE(LOOP_BREAK)
OPCODE(GOTO) OPCODE(GOTO)