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/parse.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'bootstrap/parse.c') 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, '=')) { -- cgit v1.2.3