diff options
| -rw-r--r-- | bootstrap/all.h | 7 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 6 | ||||
| -rw-r--r-- | bootstrap/parse.c | 45 | ||||
| -rw-r--r-- | bootstrap/test.cff | 7 |
4 files changed, 52 insertions, 13 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index bbe23b3..c2a8843 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -123,7 +123,7 @@ struct parser { } *curexpan; // macro expansions int expanno; const struct type *targty; - bool used_targetty; + bool used_targty; }; enum typetype { @@ -258,6 +258,7 @@ enum exprtype { Eenumval, Ezeroini, Eini, + Eget, }; struct blockstmt { @@ -307,6 +308,10 @@ struct expr { struct { slice_t(struct iniarg) args; } ini; + struct { + struct expr *lhs; + const char *fld; + } get; }; }; diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index fe937d6..faf7b6f 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -229,6 +229,9 @@ genexpr(struct expr *ex) { case Eini: pri("((%t)%n)", ty, ex); break; + case Eget: + pri("%e.%s", ex->get.lhs, ex->get.fld); + break; } } @@ -380,6 +383,9 @@ liftnestedex(struct expr *ex) { for (int i = 0; i < ex->ini.args.n; ++i) liftnestedex(&ex->ini.args.d[i].ex); break; + case Eget: + liftnestedex(ex->get.lhs); + break; } } diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 659f756..e473f23 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -666,6 +666,7 @@ parsestructini(struct parser *P, const struct type *ty) { } fld = structidx2fld(ty, idx++); + P->targty = fld->ty; e = parseexpr(P); if (!fld) fatal(P, e.span, @@ -713,6 +714,7 @@ parsearrini(struct parser *P, const struct type *ty) { lexexpect(P, '='); } + P->targty = ty->child; e = parseexpr(P); if (!typeof2(ty->child, e.ty)) fatal(P, e.span, "incompatible element type in array initializer"); @@ -737,7 +739,7 @@ pexprimary(struct parser *P) { struct expr ex = {0}; struct tok tok; - P->used_targetty = 0; + P->used_targty = 0; if (lexmatch(P, &tok, TKintlit) || lexmatch(P, &tok, TKchrlit)) { ex.t = Eintlit; @@ -785,6 +787,10 @@ pexprimary(struct parser *P) { lexexpect(P, ':'); P->targty = ty; goto enumlit; + } else if (ty->t == TYstruct || ty->t == TYenum) { + lexexpect(P, '{'); + P->targty = ty; + goto aggini; } else { goto experr; } @@ -819,7 +825,6 @@ pexprimary(struct parser *P) { struct stmt *last = &block.stmts.d[block.stmts.n - 1]; if (last->t == Sexpr) ex.ty = last->expr.ty; - } } else { ex = parseexpr(P); @@ -828,7 +833,7 @@ pexprimary(struct parser *P) { } else if (lexmatch(P, &tok, ':')) { const char *vname; int i; - enumlit: + enumlit: vname = (tok = lexexpect(P, TKident)).str; if (!(ex.ty = P->targty) || ex.ty->t != TYenum) fatal(P, tok.span, "cannot infer type for enum literal `:%s'", vname); @@ -838,12 +843,13 @@ pexprimary(struct parser *P) { fatal(P, tok.span, "enum `%s' contains no variant `%s'", ex.ty->enu.name, vname); found: - P->used_targetty = 1; + P->used_targty = 1; ex.t = Eenumval; ex.enu.vname = vname; ex.enu.i = ex.ty->enu.vals.d[i].i; } else if (lexmatch(P, &tok, '{')) { - P->used_targetty = 1; + aggini: + P->used_targty = 1; if (!P->targty) fatal(P, tok.span, "cannot infer type for compound initializer"); if (lexmatch(P, &tok, '}')) @@ -866,7 +872,7 @@ pexpostfix(struct parser *P) { struct expr ex = pexprimary(P); struct tok tok; - if (P->used_targetty) return ex; + if (P->used_targty) return ex; for (;;) if (lexmatch(P, &tok, '(')) { vec_t(struct expr) args = {0}; @@ -924,6 +930,23 @@ pexpostfix(struct parser *P) { tok.t, exprdup(ex) } }; + } else if (lexmatch(P, &tok, '.')) { + const char *fnam = (tok = lexexpect(P, TKident)).str; + if (ex.ty->t == TYstruct || ex.ty->t == TYunion) { + int idx = structfldnam2idx(ex.ty, fnam); + struct aggfield *fld = &ex.ty->agg.flds.d[idx]; + if (idx < 0) + fatal(P, tok.span, "no such field `%s'", fnam); + + ex.get.lhs = exprdup(ex); + ex.t = Eget; + ex.span = tok.span; + ex.ty = fld->ty; + ex.get.fld = fnam; + } else { + fatal(P, tok.span, "cannot acces `%s': left-hand-side is not an aggregate", + fnam); + } } else { break; } @@ -1054,7 +1077,7 @@ pexbitarith(struct parser *P) { int oret; ex = pexprefix(P); - if (P->used_targetty) return ex; + if (P->used_targty) return ex; if (!(oret = peeksbitarithop(P, &tok))) return ex; tokt = tok.t; @@ -1130,7 +1153,7 @@ pexcmp(struct parser *P) { struct tok tok; ex = pexbitarith(P); - if (P->used_targetty) return ex; + if (P->used_targty) return ex; if (matchcmpop(P, &tok)) { struct expr rhs = pexbitarith(P); if (!typeof2(ex.ty, rhs.ty)) @@ -1155,7 +1178,7 @@ pexlog(struct parser *P) { int tokt; ex = pexcmp(P); - if (P->used_targetty) return ex; + if (P->used_targty) return ex; tok = lexpeek(P); tokt = tok.t; if (tokt != TKkw_and && tokt != TKkw_or) @@ -1183,7 +1206,7 @@ pexcond(struct parser *P) { struct tok tok; ex = pexlog(P); - if (P->used_targetty) return ex; + if (P->used_targty) return ex; if (lexmatch(P, &tok, '?')) { struct expr ex2 = parseexpr(P); struct expr ex3; @@ -1228,7 +1251,7 @@ pexassign(struct parser *P) { int oret; ex = pexcond(P); - if (P->used_targetty) return ex; + if (P->used_targty) return ex; if ((oret = matchassignop(P, &tok))) { struct expr rhs = pexcond(P); if (!islvalue(&ex)) diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 651c2ce..f6deb67 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -11,12 +11,17 @@ union Val { y f64, } +enum Color { + Red, Green, Blue +} + static xs *void = {}; extern fn main (argc int, argv **u8) void { extern fn printf(fmt *const u8, ...) int; - let x Vec2f = { .y: 1, .x: 2.4 }; + let colors [3]Color = { :Red, :Green, :Blue } ; + let x = Vec2f { .y: 1, .x: 2.4 }; printf("v = { %g, %g }\n", x.x, x.y); let is [10]int = { [4] = 1, 2, [1 - 1] = 3 }; |