From 09baa8201a5422b8fa3d9d96bbfe7ceb3e12736b Mon Sep 17 00:00:00 2001 From: lemon Date: Sat, 6 Aug 2022 18:10:56 +0200 Subject: .#len operator --- bootstrap/parse.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) (limited to 'bootstrap/parse.c') diff --git a/bootstrap/parse.c b/bootstrap/parse.c index e32a2a3..c48d1eb 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -344,6 +344,8 @@ lex(struct parser *P) { tok.t = TKnullit; } else if (!strcmp(s, "##")) { tok.t = '##'; + } else if (!strcmp(s, "#len")) { + tok.t = '#len'; } else if (c == '#') { fatal(P, P->tokspan, "identifier cannot start with '#'"); } else if (c == '$') { @@ -1044,24 +1046,37 @@ pexpostfix(struct parser *P) { } }; } else if (lexmatch(P, &tok, '.')) { - 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) { - 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); - - ex.get.lhs = exprdup(ex); - ex.t = Eget; + if (lexmatch(P, &tok, '#len')) { + const struct type *ty = ex.ty; + if (ty->t == TYptr) + ty = ty->child; + if (ty->t != TYarr) + fatal(P, ex.span, "invalid operand to `.#len' (%t)", ex.ty); + assert(ty->length >= 0); + ex.t = Eintlit; + ex.ty = ty_usize; ex.span = tok.span; - ex.ty = fld->ty; - ex.get.fld = fnam; + ex.i = ty->length; } else { - fatal(P, tok.span, "cannot access `%s': left-hand-side is not an aggregate (%t)", - fnam, ex.ty); + 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) { + 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); + + 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 access `%s': left-hand-side is not an aggregate (%t)", + fnam, ex.ty); + } } } else if (lexmatch(P, &tok, '->')) { const char *fnam = (tok = lexexpect(P, TKident)).str; -- cgit v1.2.3