aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-06 16:11:26 +0200
committerlemon <lsof@mailbox.org>2022-08-06 16:11:26 +0200
commit0c6330ce7ee50c1fa241793588fa83a3c00bc3c1 (patch)
tree3c8c42804a8056a61b267d690a13688d6580630a /bootstrap
parentc53e17496d97a2fb638544cee414de97d81770fc (diff)
inferred length array init
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/all.h3
-rw-r--r--bootstrap/cgen.c9
-rw-r--r--bootstrap/parse.c16
-rw-r--r--bootstrap/test.cff7
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);
)