From f8a8add7d0e74d20304b3194e836752a9986ddc3 Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 8 Aug 2022 09:16:13 +0200 Subject: direct access of eunion fields --- bootstrap/all.h | 3 ++- bootstrap/cgen.c | 10 ++++++++-- bootstrap/parse.c | 22 ++++++++++++++++++---- bootstrap/test2.cff | 6 +++--- bootstrap/types.c | 1 + 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; -- cgit v1.2.3