mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30: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(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();
|
||||||
|
@ -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 };
|
||||||
|
45
src/expr.h
45
src/expr.h
@ -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;
|
||||||
|
@ -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, // &
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user