blueloveTH 1 rok temu
rodzic
commit
0963929a30
1 zmienionych plików z 191 dodań i 14 usunięć
  1. 191 14
      src/compiler/compiler.c

+ 191 - 14
src/compiler/compiler.c

@@ -1047,7 +1047,7 @@ bool SubscrExpr__emit_del(Expr* self_, Ctx* ctx) {
     return true;
 }
 
-SubscrExpr* SubscrExpr__new(int line, Expr* lhs, Expr* rhs) {
+SubscrExpr* SubscrExpr__new(int line) {
     const static ExprVt Vt = {
         .dtor = SubscrExpr__dtor,
         .emit_ = SubscrExpr__emit_,
@@ -1061,8 +1061,8 @@ SubscrExpr* SubscrExpr__new(int line, Expr* lhs, Expr* rhs) {
     SubscrExpr* self = PoolExpr_alloc();
     self->vt = &Vt;
     self->line = line;
-    self->lhs = lhs;
-    self->rhs = rhs;
+    self->lhs = NULL;
+    self->rhs = NULL;
     return self;
 }
 
@@ -1132,7 +1132,7 @@ typedef struct CallExpr {
     EXPR_COMMON_HEADER
     Expr* callable;
     c11_vector /*T=Expr* */ args;
-    // **a will be interpreted as a special keyword argument: {"**": a}
+    // **a will be interpreted as a special keyword argument: {{0}: a}
     c11_vector /*T=CallExprKwArg */ kwargs;
 } CallExpr;
 
@@ -1178,7 +1178,7 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
                 if(e->val->vt->is_starred) {
                     // **kwargs
                     StarredExpr* se = (StarredExpr*)e->val;
-                    assert(se->level == 2);
+                    assert(se->level == 2 && e->key == 0);
                     vtemit_(e->val, ctx);
                 } else {
                     // k=v
@@ -1431,7 +1431,7 @@ static Error* EXPR_VARS(Compiler* self) {
     // if(count > 1){
     //     TupleExpr* e = make_expr<TupleExpr>(count);
     //     for(int i=count-1; i>=0; i--)
-    //         e->items[i] = ctx()->s_popx();
+    //         e->items[i] = Ctx__s_popx(ctx());
     //     ctx()->s_push(e);
     // }
     return NULL;
@@ -1680,12 +1680,189 @@ static Error* exprLiteral0(Compiler* self) {
     return NULL;
 }
 
-static Error* exprList(Compiler* self);
-static Error* exprMap(Compiler* self);
-static Error* exprCall(Compiler* self);
-static Error* exprSlice0(Compiler* self);
-static Error* exprSlice1(Compiler* self);
-static Error* exprSubscr(Compiler* self);
+static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) {
+    // [expr]
+    Error* err;
+    int line = prev()->line;
+    bool has_cond = false;
+    check(EXPR_VARS(self));  // [expr, vars]
+    consume(TK_IN);
+    check(parse_expression(self, PREC_TERNARY + 1, false));  // [expr, vars, iter]
+    check_newlines_repl();
+    if(match(TK_IF)) {
+        check(parse_expression(self, PREC_TERNARY + 1, false));  // [expr, vars, iter, cond]
+        has_cond = true;
+    }
+    CompExpr* ce = CompExpr__new(line, op0, op1);
+    if(has_cond) ce->cond = Ctx__s_popx(ctx());
+    ce->iter = Ctx__s_popx(ctx());
+    ce->vars = Ctx__s_popx(ctx());
+    ce->expr = Ctx__s_popx(ctx());
+    Ctx__s_push(ctx(), (Expr*)ce);
+    check_newlines_repl();
+    return NULL;
+}
+
+static Error* exprList(Compiler* self) {
+    Error* err;
+    int line = prev()->line;
+    int count = 0;
+    do {
+        check_newlines_repl();
+        if(curr()->type == TK_RBRACKET) break;
+        check(EXPR(self));
+        count += 1;
+        check_newlines_repl();
+        if(count == 1 && match(TK_FOR)) {
+            check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND));
+            consume(TK_RBRACKET);
+            return NULL;
+        }
+        check_newlines_repl();
+    } while(match(TK_COMMA));
+    consume(TK_RBRACKET);
+    SequenceExpr* e = ListExpr__new(line, count);
+    for(int i = count - 1; i >= 0; i--) {
+        c11__setitem(Expr*, &e->items, i, Ctx__s_popx(ctx()));
+    }
+    Ctx__s_push(ctx(), (Expr*)e);
+    return NULL;
+}
+
+static Error* exprMap(Compiler* self) {
+    Error* err;
+    int line = prev()->line;
+    bool parsing_dict = false;  // {...} may be dict or set
+    int count = 0;
+    do {
+        check_newlines_repl();
+        if(curr()->type == TK_RBRACE) break;
+        check(EXPR(self));  // [key]
+        if(curr()->type == TK_COLON) { parsing_dict = true; }
+        if(parsing_dict) {
+            consume(TK_COLON);
+            check(EXPR(self));  // [key, value]
+        }
+        count += 1;  // key-value pair count
+        check_newlines_repl();
+        if(count == 1 && match(TK_FOR)) {
+            if(parsing_dict) {
+                check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD));
+            } else {
+                check(consume_comp(self, OP_BUILD_SET, OP_SET_ADD));
+            }
+            consume(TK_RBRACE);
+            return NULL;
+        }
+        check_newlines_repl();
+    } while(match(TK_COMMA));
+    consume(TK_RBRACE);
+
+    SequenceExpr* se;
+    if(count == 0 || parsing_dict) {
+        count *= 2;  // key + value
+        se = DictExpr__new(line, count);
+    } else {
+        se = SetExpr__new(line, count);
+    }
+    for(int i = count - 1; i >= 0; i--) {
+        c11__setitem(Expr*, &se->items, i, Ctx__s_popx(ctx()));
+    }
+    Ctx__s_push(ctx(), (Expr*)se);
+    return NULL;
+}
+
+static Error* exprCall(Compiler* self) {
+    Error* err;
+    CallExpr* e = CallExpr__new(prev()->line, Ctx__s_popx(ctx()));
+    Ctx__s_push(ctx(), (Expr*)e);  // push onto the stack in advance
+    do {
+        check_newlines_repl();
+        if(curr()->type == TK_RPAREN) break;
+        if(curr()->type == TK_ID && next()->type == TK_ASSIGN) {
+            consume(TK_ID);
+            StrName key = pk_StrName__map2(Token__sv(prev()));
+            consume(TK_ASSIGN);
+            check(EXPR(self));
+            CallExprKwArg kw = {key, Ctx__s_popx(ctx())};
+            c11_vector__push(CallExprKwArg, &e->kwargs, kw);
+        } else {
+            check(EXPR(self));
+            int star_level = 0;
+            Expr* top = Ctx__s_top(ctx());
+            if(top->vt->is_starred) star_level = ((StarredExpr*)top)->level;
+            if(star_level == 2) {
+                // **kwargs
+                CallExprKwArg kw = {0, Ctx__s_popx(ctx())};
+                c11_vector__push(CallExprKwArg, &e->kwargs, kw);
+            } else {
+                // positional argument
+                if(e->kwargs.count > 0) {
+                    return SyntaxError("positional argument follows keyword argument");
+                }
+                c11_vector__push(Expr*, &e->args, Ctx__s_popx(ctx()));
+            }
+        }
+        check_newlines_repl();
+    } while(match(TK_COMMA));
+    consume(TK_RPAREN);
+    return NULL;
+}
+
+static Error* exprSlice0(Compiler* self) {
+    Error* err;
+    SliceExpr* slice = SliceExpr__new(prev()->line);
+    Ctx__s_push(ctx(), (Expr*)slice);  // push onto the stack in advance
+    if(is_expression(self, false)) {   // :<stop>
+        check(EXPR(self));
+        slice->stop = Ctx__s_popx(ctx());
+        // try optional step
+        if(match(TK_COLON)) {  // :<stop>:<step>
+            check(EXPR(self));
+            slice->step = Ctx__s_popx(ctx());
+        }
+    } else if(match(TK_COLON)) {
+        if(is_expression(self, false)) {  // ::<step>
+            check(EXPR(self));
+            slice->step = Ctx__s_popx(ctx());
+        }  // else ::
+    }      // else :
+    return NULL;
+}
+
+static Error* exprSlice1(Compiler* self) {
+    Error* err;
+    SliceExpr* slice = SliceExpr__new(prev()->line);
+    slice->start = Ctx__s_popx(ctx());
+    Ctx__s_push(ctx(), (Expr*)slice);  // push onto the stack in advance
+    if(is_expression(self, false)) {   // <start>:<stop>
+        check(EXPR(self));
+        slice->stop = Ctx__s_popx(ctx());
+        // try optional step
+        if(match(TK_COLON)) {  // <start>:<stop>:<step>
+            check(EXPR(self));
+            slice->step = Ctx__s_popx(ctx());
+        }
+    } else if(match(TK_COLON)) {  // <start>::<step>
+        check(EXPR(self));
+        slice->step = Ctx__s_popx(ctx());
+    }  // else <start>:
+    return NULL;
+}
+
+static Error* exprSubscr(Compiler* self) {
+    Error* err;
+    int line = prev()->line;
+    check_newlines_repl();
+    check(EXPR_TUPLE_ALLOW_SLICE(self, true));
+    check_newlines_repl();
+    consume(TK_RBRACKET);  // [lhs, rhs]
+    SubscrExpr* e = SubscrExpr__new(line);
+    e->rhs = Ctx__s_popx(ctx());  // [lhs]
+    e->lhs = Ctx__s_popx(ctx());  // []
+    Ctx__s_push(ctx(), (Expr*)e);
+    return NULL;
+}
 
 /////////////////////////////////////////////////////////////////
 
@@ -1710,8 +1887,8 @@ Error* Compiler__compile(Compiler* self, CodeObject* out) {
         return NULL;
     }
     // } else if(mode() == JSON_MODE) {
-    //     check(EXPR());
-    //     Expr* e = ctx()->s_popx();
+    //     check(EXPR(self));
+    //     Expr* e = Ctx__s_popx(ctx());
     //     if(!e->is_json_object()){
     //         return SyntaxError("expect a JSON object, literal or array");
     //     }