blueloveTH 1 год назад
Родитель
Сommit
62420dade1
5 измененных файлов с 251 добавлено и 58 удалено
  1. 0 3
      include/pocketpy/compiler/compiler.h
  2. 29 1
      include/pocketpy/compiler/expr.h
  3. 48 52
      src/compiler/compiler.c
  4. 174 0
      src/compiler/expr.c
  5. 0 2
      src/public/vm.c

+ 0 - 3
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

+ 29 - 1
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

+ 48 - 52
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
-}
+    [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 }
+};

+ 174 - 0
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;
 }

+ 0 - 2
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();
 }