aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap/all.h3
-rw-r--r--bootstrap/cgen.c10
-rw-r--r--bootstrap/parse.c22
-rw-r--r--bootstrap/test2.cff6
-rw-r--r--bootstrap/types.c1
5 files changed, 32 insertions, 10 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h
index 1629455..373aac9 100644
--- a/bootstrap/all.h
+++ b/bootstrap/all.h
@@ -312,6 +312,7 @@ enum exprtype {
Eslice,
Elen,
Eeuini,
+ Eeutag,
};
struct blockstmt {
@@ -353,7 +354,7 @@ struct expr {
struct expr *lhs, *rhs;
} index;
struct blockstmt block;
- struct expr *child; // cast, len
+ struct expr *child; // cast, len, eutag
struct {
i64 i;
const char *vname;
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 433a5a0..f54eccc 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -249,7 +249,10 @@ genexpr(struct expr *ex) {
pri("((%t)%n)", ty, ex);
break;
case Eget:
- pri("%e%s%s", ex->get.lhs, ex->get.lhs->ty->t == TYptr ? "->" : ".", ex->get.fld);
+ pri("%e%s%s%s", ex->get.lhs, ex->get.lhs->ty->t == TYptr ? "->" : ".",
+ (ex->get.lhs->ty->t == TYeunion
+ || (ex->get.lhs->ty->t == TYptr && ex->get.lhs->ty->child->t == TYeunion) ? "u." : ""),
+ ex->get.fld);
break;
case Emcall:
decl = container_of(ex->mcall.met, struct decl, fn);
@@ -273,6 +276,9 @@ genexpr(struct expr *ex) {
case Elen:
pri("%e.len", ex->child);
break;
+ case Eeutag:
+ pri("%e%st", ex->child, ex->child->ty->t == TYptr ? "->" : ".");
+ break;
case Eeuini:
pri("((%t)", ty);
geneuiniex(ex);
@@ -470,7 +476,7 @@ liftnestedex(struct expr *ex) {
case Eblock:
liftnested(blocktostmt(ex->block));
break;
- case Eas: case Elen:
+ case Eas: case Elen: case Eeutag:
liftnestedex(ex->child);
break;
case Eini:
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 93a3afb..3e14dc3 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -371,6 +371,8 @@ lex(struct parser *P) {
tok.t = '##';
} else if (!strcmp(s, "#len")) {
tok.t = '#len';
+ } else if (!strcmp(s, "#tag")) {
+ tok.t = '#tag';
} else if (!strcmp(s, "#?")) {
tok.t = '#?';
} else if (!strncmp(s, "#:", 2)) {
@@ -1284,27 +1286,39 @@ pexpostfix(struct parser *P) {
if (ty->t == TYarr) {
assert(ty->length >= 0);
ex.t = Eintlit;
- ex.ty = ty_usize;
+ ex.ty = ty->konst ? constify(ty_usize) : ty_usize;
ex.span = tok.span;
ex.i = ty->length;
} else if (ty->t == TYslice) {
ex.child = exprdup(ex);
ex.t = Elen;
- ex.ty = ty_usize;
+ ex.ty = ty->konst ? constify(ty_usize) : ty_usize;
ex.span = tok.span;
} else {
fatal(P, ex.span, "invalid operand to `.#len' (%t)", ex.ty);
}
+ } else if (lexmatch (P, &tok, '#tag')) {
+ const struct type *ty = ex.ty;
+ if (ty->t == TYptr)
+ ty = ty->child;
+ if (ty->t != TYeunion)
+ fatal(P, ex.span, "invalid operand to `.#tag' (%t)", ex.ty);
+ ex.child = exprdup(ex);
+ ex.t = Eeutag;
+ ex.ty = ty->konst ? constify(ty->agg.enumty) : ty->agg.enumty;
+ ex.span = tok.span;
} else {
const char *fnam = (tok = lexexpect(P, TKident)).str;
const struct type *ty = ex.ty;
if (ty->t == TYptr)
ty = ty->child;
- if (ty->t == TYstruct || ty->t == TYunion) {
+ if (ty->t == TYstruct || ty->t == TYunion || ty->t == TYeunion) {
int idx = structfldnam2idx(ty, fnam);
struct aggfield *fld = &ty->agg.flds.d[idx];
if (idx < 0)
fatal(P, tok.span, "%t has no such field `%s'", ty, fnam);
+ if (!fld->ty)
+ fatal(P, tok.span, "%t variant `%s' is empty", ty, fnam);
ex.get.lhs = exprdup(ex);
ex.t = Eget;
@@ -1748,7 +1762,7 @@ parsevardecl(decl_yielder_t yield, void *yarg, struct parser *P, bool let, bool
if (lexmatch(P, NULL, '=')) {
ini = exprdup(parseexpr(P));
- ty = ini->ty;
+ ty = unconstify(ini->ty);
} else {
ty = parsetype(P);
if (lexmatch(P, NULL, '=')) {
diff --git a/bootstrap/test2.cff b/bootstrap/test2.cff
index fdb30cb..ec5fcb0 100644
--- a/bootstrap/test2.cff
+++ b/bootstrap/test2.cff
@@ -36,15 +36,15 @@ extern fn main() void {
let x int #?;
x = X + 1 + Y;
- let v= Value:None;
- v = :Int 3;
+ let const v= Value:None;
switch (v) {
case None;
case Int i;
i;
case Flo *f;
- *f += 1.0f;
}
+ let t = v.#tag;
+ let i = v.Int;
#:outer for let i = 0; i++ < 10; {
printf("%d\n", i);
diff --git a/bootstrap/types.c b/bootstrap/types.c
index 38d75d0..78a3df0 100644
--- a/bootstrap/types.c
+++ b/bootstrap/types.c
@@ -313,6 +313,7 @@ arraydecay(const struct type *ty) {
int
numtype2rank(const struct type *a) {
+ a = unconstify(a);
if (a->t == TYint) {
if (a->size < g_targ.intsize || a == ty_int)
return 0;