From 0c6330ce7ee50c1fa241793588fa83a3c00bc3c1 Mon Sep 17 00:00:00 2001 From: lemon Date: Sat, 6 Aug 2022 16:11:26 +0200 Subject: inferred length array init --- bootstrap/all.h | 3 ++- bootstrap/cgen.c | 9 +++++---- bootstrap/parse.c | 16 ++++++++++++++++ bootstrap/test.cff | 7 ++++--- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/bootstrap/all.h b/bootstrap/all.h index 3410d1f..8b57d94 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -313,6 +313,7 @@ struct expr { } enu; struct { slice_t(struct iniarg) args; + i64 maxn; } ini; struct { struct expr *lhs; @@ -327,7 +328,7 @@ struct expr { struct iniarg { union { - size_t idx; + i64 idx; const char *fld; }; struct expr ex; diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 9fa954c..8a01e09 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -554,10 +554,11 @@ defctype(const struct type *ty, void *_) { defctype(ty->child, NULL); break; case TYarr: - assert(ty->length >= 0); - defctype(ty->child, NULL); - *cname = xasprintf("__ty%d", id++); - pri("typedef %t %s[%U];\n", ty->child, *cname, ty->length); + if (ty->length >= 0) { + defctype(ty->child, NULL); + *cname = xasprintf("__ty%d", id++); + pri("typedef %t %s[%U];\n", ty->child, *cname, ty->length); + } break; case TYslice: defctype(ty->child, NULL); diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 9ab1b53..e32a2a3 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -786,6 +786,7 @@ parsearrini(struct parser *P, const struct type *ty) { fatal(P, e.span, "excess elements in array initializer"); vec_push(&args, ((struct iniarg) { .idx = iota++, e })); + ex.ini.maxn = MAX(ex.ini.maxn, iota - 1); if (!lexmatch(P, &tok, ',')) { lexexpect(P, '}'); @@ -1511,6 +1512,21 @@ parsevardecl(decl_yielder_t yield, void *yarg, struct parser *P) { fatal(P, tok.span, "incompatible initializer type (%t, expected %t)", ini->ty, ty); + if (ty->t == TYarr && ty->length < 0) { + struct type ty2 = *ty; + if (ini->t == Ezeroini) { + ty2.length = 0; + } else if (ini->t == Eini) { + ty2.length = ini->ini.maxn + 1; + } else { + fatal(P, ini->span, + "initializer of inferred-length array must be compound literal"); + } + ty2.size = ty->child->size * ty2.length; + ty2.align = ty->child->align; + ty = interntype(ty2); + } + if (!completetype(ty)) fatal(P, tok.span, "let `%s': variable type %t is incomplete", name, ty); diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 7a6b7ce..be6cb95 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -10,8 +10,9 @@ enum Color { Red, Green, Blue } +defmacro arraylength(ary) [ (sizeof(ary)/sizeof(ary[0])) ] defmacro each(i, x, arr, ...body) [ - for let i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i { + for let i = 0; i < arraylength(arr); ++i { let x = arr[i]; { body } } @@ -58,8 +59,8 @@ extern fn main (argc int, argv **u8) int { x->zero(); printf("mag = %g\n", (&x)->mag()); - let is [10]int = { [4] = 1, 2, [1 - 1] = 3 }; - isort(is, 10); + let is []int = { [4] = 1, 2, [1 - 1] = 3 }; + isort(is, arraylength(is)); each(i, x, is, printf("%d\n", x); ) -- cgit v1.2.3