From 62420dade1773f4556f8eb946aacffb0f48173de Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 29 Jun 2024 11:21:52 +0800 Subject: [PATCH] some fix --- include/pocketpy/compiler/compiler.h | 3 - include/pocketpy/compiler/expr.h | 30 ++++- src/compiler/compiler.c | 100 ++++++++------- src/compiler/expr.c | 174 +++++++++++++++++++++++++++ src/public/vm.c | 2 - 5 files changed, 251 insertions(+), 58 deletions(-) diff --git a/include/pocketpy/compiler/compiler.h b/include/pocketpy/compiler/compiler.h index 956a4d80..33ae8e67 100644 --- a/include/pocketpy/compiler/compiler.h +++ b/include/pocketpy/compiler/compiler.h @@ -11,9 +11,6 @@ extern "C" { Error* pk_compile(pk_SourceData_ src, CodeObject* out); -void pk_Compiler__initialize(); -#define pk_Compiler__finalize() // do nothing - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/include/pocketpy/compiler/expr.h b/include/pocketpy/compiler/expr.h index 2301e404..10644e65 100644 --- a/include/pocketpy/compiler/expr.h +++ b/include/pocketpy/compiler/expr.h @@ -58,7 +58,7 @@ typedef struct pk_StarredExpr{ int level; } pk_StarredExpr; -// InvertExpr, NotExpr, AndExpr, OrExpr, NegatedExpr +// InvertExpr, NotExpr, NegatedExpr // NOTE: NegatedExpr always contains a non-const child. Should not generate -1 or -0.1 typedef struct pk_UnaryExpr{ COMMON_HEADER @@ -118,6 +118,34 @@ typedef struct pk_FStringExpr{ c11_string src; } pk_FStringExpr; +// AndExpr, OrExpr +typedef struct pk_LogicBinaryExpr{ + COMMON_HEADER + pk_Expr* lhs; + pk_Expr* rhs; + Opcode opcode; +} pk_LogicBinaryExpr; + +typedef struct pk_GroupedExpr{ + COMMON_HEADER + pk_Expr* child; +} pk_GroupedExpr; + +typedef struct pk_BinaryExpr{ + COMMON_HEADER + pk_Expr* lhs; + pk_Expr* rhs; + TokenIndex op; + bool inplace; +} pk_BinaryExpr; + +typedef struct pk_TernaryExpr{ + COMMON_HEADER + pk_Expr* cond; + pk_Expr* true_expr; + pk_Expr* false_expr; +} pk_TernaryExpr; + #ifdef __cplusplus } #endif diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 1879e274..5412ca55 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -12,7 +12,7 @@ typedef struct PrattRule { enum Precedence precedence; } PrattRule; -static PrattRule rules[TK__COUNT__]; +const static PrattRule rules[TK__COUNT__]; typedef struct pk_Compiler { pk_SourceData_ src; // weakref @@ -251,56 +251,52 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out){ return err; } -void pk_Compiler__initialize(){ +const static PrattRule rules[TK__COUNT__] = { // clang-format off // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ - rules[TK_DOT] = (PrattRule){ NULL, exprAttrib, PREC_PRIMARY }; - rules[TK_LPAREN] = (PrattRule){ exprGroup, exprCall, PREC_PRIMARY }; - rules[TK_LBRACKET] = (PrattRule){ exprList, exprSubscr, PREC_PRIMARY }; - rules[TK_MOD] = (PrattRule){ NULL, exprBinaryOp, PREC_FACTOR }; - rules[TK_ADD] = (PrattRule){ NULL, exprBinaryOp, PREC_TERM }; - rules[TK_SUB] = (PrattRule){ exprUnaryOp, exprBinaryOp, PREC_TERM }; - rules[TK_MUL] = (PrattRule){ exprUnaryOp, exprBinaryOp, PREC_FACTOR }; - rules[TK_INVERT] = (PrattRule){ exprUnaryOp, NULL, PREC_UNARY }; - rules[TK_DIV] = (PrattRule){ NULL, exprBinaryOp, PREC_FACTOR }; - rules[TK_FLOORDIV] = (PrattRule){ NULL, exprBinaryOp, PREC_FACTOR }; - rules[TK_POW] = (PrattRule){ exprUnaryOp, exprBinaryOp, PREC_EXPONENT }; - rules[TK_GT] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_LT] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_EQ] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_NE] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_GE] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_LE] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_IN] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_IS] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_LSHIFT] = (PrattRule){ NULL, exprBinaryOp, PREC_BITWISE_SHIFT }; - rules[TK_RSHIFT] = (PrattRule){ NULL, exprBinaryOp, PREC_BITWISE_SHIFT }; - rules[TK_AND] = (PrattRule){ NULL, exprBinaryOp, PREC_BITWISE_AND }; - rules[TK_OR] = (PrattRule){ NULL, exprBinaryOp, PREC_BITWISE_OR }; - rules[TK_XOR] = (PrattRule){ NULL, exprBinaryOp, PREC_BITWISE_XOR }; - rules[TK_DECORATOR] = (PrattRule){ NULL, exprBinaryOp, PREC_FACTOR }; - rules[TK_IF] = (PrattRule){ NULL, exprTernary, PREC_TERNARY }; - rules[TK_NOT_IN] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_IS_NOT] = (PrattRule){ NULL, exprBinaryOp, PREC_COMPARISION }; - rules[TK_AND_KW ] = (PrattRule){ NULL, exprAnd, PREC_LOGICAL_AND }; - rules[TK_OR_KW] = (PrattRule){ NULL, exprOr, PREC_LOGICAL_OR }; - rules[TK_NOT_KW] = (PrattRule){ exprNot, NULL, PREC_LOGICAL_NOT }; - rules[TK_TRUE] = (PrattRule){ exprLiteral0 }; - rules[TK_FALSE] = (PrattRule){ exprLiteral0 }; - rules[TK_NONE] = (PrattRule){ exprLiteral0 }; - rules[TK_DOTDOTDOT] = (PrattRule){ exprLiteral0 }; - rules[TK_LAMBDA] = (PrattRule){ exprLambda, }; - rules[TK_ID] = (PrattRule){ exprName, }; - rules[TK_NUM] = (PrattRule){ exprLiteral, }; - rules[TK_STR] = (PrattRule){ exprLiteral, }; - rules[TK_FSTR] = (PrattRule){ exprFString, }; - rules[TK_LONG] = (PrattRule){ exprLong, }; - rules[TK_IMAG] = (PrattRule){ exprImag, }; - rules[TK_BYTES] = (PrattRule){ exprBytes, }; - rules[TK_LBRACE] = (PrattRule){ exprMap }; - rules[TK_COLON] = (PrattRule){ exprSlice0, exprSlice1, PREC_PRIMARY }; - -#undef PK_METHOD -#undef PK_NO_INFIX - // clang-format on -} \ No newline at end of file + [TK_DOT] = { NULL, exprAttrib, PREC_PRIMARY }, + [TK_LPAREN] = { exprGroup, exprCall, PREC_PRIMARY }, + [TK_LBRACKET] = { exprList, exprSubscr, PREC_PRIMARY }, + [TK_MOD] = { NULL, exprBinaryOp, PREC_FACTOR }, + [TK_ADD] = { NULL, exprBinaryOp, PREC_TERM }, + [TK_SUB] = { exprUnaryOp, exprBinaryOp, PREC_TERM }, + [TK_MUL] = { exprUnaryOp, exprBinaryOp, PREC_FACTOR }, + [TK_INVERT] = { exprUnaryOp, NULL, PREC_UNARY }, + [TK_DIV] = { NULL, exprBinaryOp, PREC_FACTOR }, + [TK_FLOORDIV] = { NULL, exprBinaryOp, PREC_FACTOR }, + [TK_POW] = { exprUnaryOp, exprBinaryOp, PREC_EXPONENT }, + [TK_GT] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_LT] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_EQ] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_NE] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_GE] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_LE] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_IN] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_IS] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_LSHIFT] = { NULL, exprBinaryOp, PREC_BITWISE_SHIFT }, + [TK_RSHIFT] = { NULL, exprBinaryOp, PREC_BITWISE_SHIFT }, + [TK_AND] = { NULL, exprBinaryOp, PREC_BITWISE_AND }, + [TK_OR] = { NULL, exprBinaryOp, PREC_BITWISE_OR }, + [TK_XOR] = { NULL, exprBinaryOp, PREC_BITWISE_XOR }, + [TK_DECORATOR] = { NULL, exprBinaryOp, PREC_FACTOR }, + [TK_IF] = { NULL, exprTernary, PREC_TERNARY }, + [TK_NOT_IN] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_IS_NOT] = { NULL, exprBinaryOp, PREC_COMPARISION }, + [TK_AND_KW ] = { NULL, exprAnd, PREC_LOGICAL_AND }, + [TK_OR_KW] = { NULL, exprOr, PREC_LOGICAL_OR }, + [TK_NOT_KW] = { exprNot, NULL, PREC_LOGICAL_NOT }, + [TK_TRUE] = { exprLiteral0 }, + [TK_FALSE] = { exprLiteral0 }, + [TK_NONE] = { exprLiteral0 }, + [TK_DOTDOTDOT] = { exprLiteral0 }, + [TK_LAMBDA] = { exprLambda, }, + [TK_ID] = { exprName, }, + [TK_NUM] = { exprLiteral, }, + [TK_STR] = { exprLiteral, }, + [TK_FSTR] = { exprFString, }, + [TK_LONG] = { exprLong, }, + [TK_IMAG] = { exprImag, }, + [TK_BYTES] = { exprBytes, }, + [TK_LBRACE] = { exprMap }, + [TK_COLON] = { exprSlice0, exprSlice1, PREC_PRIMARY } +}; \ No newline at end of file diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 06ede9c9..213bb3f9 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -594,6 +594,168 @@ pk_FStringExpr* pk_FStringExpr__new(c11_string src){ return self; } +static pk_ExprVt LogicBinaryExpr; + +pk_LogicBinaryExpr* pk_LogicBinaryExpr__new(pk_Expr* lhs, pk_Expr* rhs, Opcode opcode){ + static_assert_expr_size(pk_LogicBinaryExpr); + pk_LogicBinaryExpr* self = PoolExpr_alloc(); + self->vt = &LogicBinaryExpr; + self->line = -1; + self->lhs = lhs; + self->rhs = rhs; + self->opcode = opcode; + return self; +} + +void pk_LogicBinaryExpr__dtor(pk_Expr* self_){ + pk_LogicBinaryExpr* self = (pk_LogicBinaryExpr*)self_; + pk_Expr__delete(self->lhs); + pk_Expr__delete(self->rhs); +} + +void pk_LogicBinaryExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) { + pk_LogicBinaryExpr* self = (pk_LogicBinaryExpr*)self_; + self->lhs->vt->emit_(self->lhs, ctx); + int patch = pk_CodeEmitContext__emit_(ctx, self->opcode, BC_NOARG, self->line); + self->rhs->vt->emit_(self->rhs, ctx); + pk_CodeEmitContext__patch_jump(ctx, patch); +} + +static pk_ExprVt GroupedExprVt; + +void pk_GroupedExpr__dtor(pk_Expr* self_){ + pk_GroupedExpr* self = (pk_GroupedExpr*)self_; + pk_Expr__delete(self->child); +} + +void pk_GroupedExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) { + pk_GroupedExpr* self = (pk_GroupedExpr*)self_; + self->child->vt->emit_(self->child, ctx); +} + +bool pk_GroupedExpr__emit_del(pk_Expr* self_, pk_CodeEmitContext* ctx) { + pk_GroupedExpr* self = (pk_GroupedExpr*)self_; + return self->child->vt->emit_del(self->child, ctx); +} + +bool pk_GroupedExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) { + pk_GroupedExpr* self = (pk_GroupedExpr*)self_; + return self->child->vt->emit_store(self->child, ctx); +} + +pk_GroupedExpr* pk_GroupedExpr__new(pk_Expr* child){ + static_assert_expr_size(pk_GroupedExpr); + pk_GroupedExpr* self = PoolExpr_alloc(); + self->vt = &GroupedExprVt; + self->line = -1; + self->child = child; + return self; +} + +static pk_ExprVt BinaryExprVt; + +static void pk_BinaryExpr__dtor(pk_Expr* self_){ + pk_BinaryExpr* self = (pk_BinaryExpr*)self_; + pk_Expr__delete(self->lhs); + pk_Expr__delete(self->rhs); +} + +static pk_BinaryExpr__is_compare(pk_Expr* self_){ + pk_BinaryExpr* self = (pk_BinaryExpr*)self_; + switch(self->op) { + case TK_LT: + case TK_LE: + case TK_EQ: + case TK_NE: + case TK_GT: + case TK_GE: return true; + default: return false; + } +} + +static void _emit_compare(pk_BinaryExpr* self, pk_CodeEmitContext* ctx, c11_vector* jmps) { + if(self->lhs->vt->is_compare(self->lhs)) { + pk_BinaryExpr* lhs = (pk_BinaryExpr*)lhs; + _emit_compare(lhs, ctx, jmps); + } else { + self->lhs->vt->emit_(self->lhs, ctx); // [a] + } + self->rhs->vt->emit_(self->rhs, ctx); // [a, b] + pk_CodeEmitContext__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b] + pk_CodeEmitContext__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b] + Opcode opcode; + switch(self->op) { + case TK_LT: opcode = OP_COMPARE_LT; break; + case TK_LE: opcode = OP_COMPARE_LE; break; + case TK_EQ: opcode = OP_COMPARE_EQ; break; + case TK_NE: opcode = OP_COMPARE_NE; break; + case TK_GT: opcode = OP_COMPARE_GT; break; + case TK_GE: opcode = OP_COMPARE_GE; break; + default: PK_UNREACHABLE() + } + pk_CodeEmitContext__emit_(ctx, opcode, BC_NOARG, self->line); + // [b, RES] + int index = pk_CodeEmitContext__emit_(ctx, OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, self->line); + c11_vector__push(int, jmps, index); +} + +static void pk_BinaryExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) { + pk_BinaryExpr* self = (pk_BinaryExpr*)self_; + c11_vector/*T=int*/ jmps; + c11_vector__ctor(&jmps, sizeof(int)); + if(self->vt->is_compare(self_) && self->lhs->vt->is_compare(self->lhs)) { + // (a < b) < c + pk_BinaryExpr* e = (pk_BinaryExpr*)self->lhs; + _emit_compare(e, ctx, &jmps); + // [b, RES] + } else { + // (1 + 2) < c + if(self->inplace) { + self->lhs->vt->emit_inplace(self->lhs, ctx); + } else { + self->lhs->vt->emit_(self->lhs, ctx); + } + } + + self->rhs->vt->emit_(self->rhs, ctx); + Opcode opcode; + switch(self->op) { + case TK_ADD: opcode = OP_BINARY_ADD; break; + case TK_SUB: opcode = OP_BINARY_SUB; break; + case TK_MUL: opcode = OP_BINARY_MUL; break; + case TK_DIV: opcode = OP_BINARY_TRUEDIV; break; + case TK_FLOORDIV: opcode = OP_BINARY_FLOORDIV; break; + case TK_MOD: opcode = OP_BINARY_MOD; break; + case TK_POW: opcode = OP_BINARY_POW; break; + + case TK_LT: opcode = OP_COMPARE_LT; break; + case TK_LE: opcode = OP_COMPARE_LE; break; + case TK_EQ: opcode = OP_COMPARE_EQ; break; + case TK_NE: opcode = OP_COMPARE_NE; break; + case TK_GT: opcode = OP_COMPARE_GT; break; + case TK_GE: opcode = OP_COMPARE_GE; 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, BC_NOARG, line); break; + // case TK_IS_NOT: ctx->emit_(OP_IS_NOT_OP, BC_NOARG, line); break; + + case TK_LSHIFT: ctx->emit_(OP_BITWISE_LSHIFT, BC_NOARG, line); break; + case TK_RSHIFT: ctx->emit_(OP_BITWISE_RSHIFT, BC_NOARG, line); break; + case TK_AND: ctx->emit_(OP_BITWISE_AND, BC_NOARG, line); break; + case TK_OR: ctx->emit_(OP_BITWISE_OR, BC_NOARG, line); break; + case TK_XOR: ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break; + + case TK_DECORATOR: ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break; + default: PK_FATAL_ERROR("unknown binary operator: %s\n", pk_TokenSymbols[op]); + } + + for(int i: jmps) + ctx->patch_jump(i); +} + +static pk_ExprVt TernaryExprVt; + ///////////////////////////////////////////// void pk_Expr__initialize(){ pk_ExprVt__ctor(&NameExprVt); @@ -660,4 +822,16 @@ void pk_Expr__initialize(){ pk_ExprVt__ctor(&FStringExprVt); vt = &FStringExprVt; vt->emit_ = pk_FStringExpr__emit_; + + pk_ExprVt__ctor(&LogicBinaryExpr); + vt = &LogicBinaryExpr; + vt->dtor = pk_LogicBinaryExpr__dtor; + vt->emit_ = pk_LogicBinaryExpr__emit_; + + pk_ExprVt__ctor(&GroupedExprVt); + vt = &GroupedExprVt; + vt->dtor = pk_GroupedExpr__dtor; + vt->emit_ = pk_GroupedExpr__emit_; + vt->emit_del = pk_GroupedExpr__emit_del; + vt->emit_store = pk_GroupedExpr__emit_store; } diff --git a/src/public/vm.c b/src/public/vm.c index 0459780b..f761a700 100644 --- a/src/public/vm.c +++ b/src/public/vm.c @@ -12,7 +12,6 @@ static pk_VM pk_default_vm; void py_initialize() { pk_MemoryPools__initialize(); pk_StrName__initialize(); - pk_Compiler__initialize(); pk_current_vm = &pk_default_vm; pk_VM__ctor(&pk_default_vm); } @@ -20,7 +19,6 @@ void py_initialize() { void py_finalize() { pk_VM__dtor(&pk_default_vm); pk_current_vm = NULL; - pk_Compiler__finalize(); pk_StrName__finalize(); pk_MemoryPools__finalize(); }