mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
...
This commit is contained in:
parent
8e104627cb
commit
919d7a465c
12
src/ceval.h
12
src/ceval.h
@ -69,6 +69,12 @@ __NEXT_STEP:;
|
||||
TARGET(POP_TOP) POP(); DISPATCH();
|
||||
TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
|
||||
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
|
||||
TARGET(ROT_THREE)
|
||||
_0 = TOP();
|
||||
TOP() = SECOND();
|
||||
SECOND() = THIRD();
|
||||
THIRD() = _0;
|
||||
DISPATCH();
|
||||
TARGET(PRINT_EXPR)
|
||||
if(TOP() != None) _stdout(this, CAST(Str&, py_repr(TOP())) + "\n");
|
||||
POP();
|
||||
@ -408,6 +414,12 @@ __NEXT_STEP:;
|
||||
if(py_bool(TOP()) == false) frame->jump_abs(byte.arg);
|
||||
else POP();
|
||||
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)
|
||||
frame->jump_abs(co_blocks[byte.block].start);
|
||||
DISPATCH();
|
||||
|
@ -93,12 +93,12 @@ class Compiler {
|
||||
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_EQUALITY };
|
||||
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("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||
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_AND };
|
||||
@ -107,8 +107,8 @@ class Compiler {
|
||||
rules[TK("@")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
||||
rules[TK("if")] = { nullptr, METHOD(exprTernary), PREC_TERNARY };
|
||||
rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE };
|
||||
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||
rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
|
||||
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
|
||||
rules[TK("not")] = { METHOD(exprNot), nullptr, PREC_LOGICAL_NOT };
|
||||
|
47
src/expr.h
47
src/expr.h
@ -23,6 +23,7 @@ struct Expr{
|
||||
virtual bool is_literal() const { return false; }
|
||||
virtual bool is_json_object() const { return false; }
|
||||
virtual bool is_attrib() const { return false; }
|
||||
virtual bool is_compare() const { return false; }
|
||||
|
||||
// for OP_DELETE_XXX
|
||||
[[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; }
|
||||
@ -683,8 +684,50 @@ struct BinaryExpr: Expr{
|
||||
Expr_ rhs;
|
||||
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 {
|
||||
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);
|
||||
switch (op) {
|
||||
case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
|
||||
@ -701,7 +744,7 @@ struct BinaryExpr: Expr{
|
||||
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;
|
||||
|
@ -79,9 +79,12 @@ enum Precedence {
|
||||
PREC_LOGICAL_OR, // or
|
||||
PREC_LOGICAL_AND, // and
|
||||
PREC_LOGICAL_NOT, // not
|
||||
PREC_EQUALITY, // == !=
|
||||
PREC_TEST, // in / is / is not / not in
|
||||
PREC_COMPARISION, // < > <= >=
|
||||
/* https://docs.python.org/3/reference/expressions.html#comparisons
|
||||
* Unlike C, all comparison operations in Python have the same priority,
|
||||
* 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_XOR, // ^
|
||||
PREC_BITWISE_AND, // &
|
||||
|
@ -6,6 +6,7 @@ OPCODE(NO_OP)
|
||||
OPCODE(POP_TOP)
|
||||
OPCODE(DUP_TOP)
|
||||
OPCODE(ROT_TWO)
|
||||
OPCODE(ROT_THREE)
|
||||
OPCODE(PRINT_EXPR)
|
||||
/**************************/
|
||||
OPCODE(LOAD_CONST)
|
||||
@ -75,6 +76,7 @@ OPCODE(JUMP_ABSOLUTE)
|
||||
OPCODE(POP_JUMP_IF_FALSE)
|
||||
OPCODE(JUMP_IF_TRUE_OR_POP)
|
||||
OPCODE(JUMP_IF_FALSE_OR_POP)
|
||||
OPCODE(SHORTCUT_IF_FALSE_OR_POP)
|
||||
OPCODE(LOOP_CONTINUE)
|
||||
OPCODE(LOOP_BREAK)
|
||||
OPCODE(GOTO)
|
||||
|
Loading…
x
Reference in New Issue
Block a user