diff options
| author | 2022-08-08 09:16:13 +0200 | |
|---|---|---|
| committer | 2022-08-08 09:16:13 +0200 | |
| commit | f8a8add7d0e74d20304b3194e836752a9986ddc3 (patch) | |
| tree | d4c72f796c9b97c229f299b1632c6a5c9ffc3e37 /bootstrap | |
| parent | 0a57a8979a75ce5398b34817c86a55c6d0552bca (diff) | |
direct access of eunion fields
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/all.h | 3 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 10 | ||||
| -rw-r--r-- | bootstrap/parse.c | 22 | ||||
| -rw-r--r-- | bootstrap/test2.cff | 6 | ||||
| -rw-r--r-- | 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; |