diff options
| author | 2022-08-06 18:10:56 +0200 | |
|---|---|---|
| committer | 2022-08-06 18:10:56 +0200 | |
| commit | 09baa8201a5422b8fa3d9d96bbfe7ceb3e12736b (patch) | |
| tree | 7db3c6804beef789ca13b0fc3e2ce6a575fcae07 /bootstrap | |
| parent | 0c6330ce7ee50c1fa241793588fa83a3c00bc3c1 (diff) | |
.#len operator
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/parse.c | 47 | ||||
| -rw-r--r-- | bootstrap/test.cff | 5 |
2 files changed, 33 insertions, 19 deletions
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; diff --git a/bootstrap/test.cff b/bootstrap/test.cff index be6cb95..95ee7bf 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -10,9 +10,8 @@ enum Color { Red, Green, Blue } -defmacro arraylength(ary) [ (sizeof(ary)/sizeof(ary[0])) ] defmacro each(i, x, arr, ...body) [ - for let i = 0; i < arraylength(arr); ++i { + for let i = 0; i < arr.#len; ++i { let x = arr[i]; { body } } @@ -60,7 +59,7 @@ extern fn main (argc int, argv **u8) int { printf("mag = %g\n", (&x)->mag()); let is []int = { [4] = 1, 2, [1 - 1] = 3 }; - isort(is, arraylength(is)); + isort(is, is.#len); each(i, x, is, printf("%d\n", x); ) |