aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/all.h7
-rw-r--r--bootstrap/cgen.c6
-rw-r--r--bootstrap/parse.c45
-rw-r--r--bootstrap/test.cff7
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 };