aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-07 11:13:51 +0200
committerlemon <lsof@mailbox.org>2022-08-07 11:21:42 +0200
commit0a4f81e86d21d056329a2b7b2186152e9b9c2375 (patch)
tree6452e0943a8a81b92aa5a697a8f6b4fb27eb8b1d /bootstrap
parentf97e08b3da14c79f7f78e439d06988753c79384b (diff)
recursive datatypes without forward declaring first
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/parse.c90
-rw-r--r--bootstrap/test2.cff6
-rw-r--r--bootstrap/types.c3
3 files changed, 53 insertions, 46 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 0a1db86..7ec725d 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -2308,17 +2308,36 @@ parseagg(struct parser *P, const char *name, int kind, struct decl **retdecl) {
const struct type *pty = NULL;
static int id = 0;
size_t size = 0, align = 1;
+ bool decls = 0;
vec_t(struct aggfield) flds = {0};
- *retdecl = NULL;
-
+ ty.agg.name = name;
if (lexmatch(P, &tok, ';')) {
ty.agg.fwd = 1;
+ ty.agg.id = id++;
+ return interntype(ty);
} else {
- lexexpect(P, '{');
+ if (name) {
+ int iid;
+ struct env env_noparent = *P->curenv;
+ env_noparent.parent = NULL;
+ struct decl *decl = (struct decl *)envfind(&env_noparent, name);
+ if (decl && decl->ty->t == kind)
+ iid = decl->ty->agg.id;
+ else
+ iid = id++;
+ pty = interntype((struct type) {
+ kind, .agg.name = name, .agg.id = iid
+ });
+ *retdecl = decl = putdecl(P, P->tokspan, &(struct decl) {
+ Dtype, name, .span = P->tokspan, .ty = pty });
+ }
+ tok = lexexpect(P, '{');
while (!lexmatch(P, &tok, '}')) {
- if (isdecltokt(lexpeek(P).t))
- goto decls;
+ if (isdecltokt(lexpeek(P).t)) {
+ decls = 1;
+ break;
+ }
const char *fnam = (tok = lexexpect(P, TKident)).str;
const struct type *ty = parsetype(P);
@@ -2348,49 +2367,32 @@ parseagg(struct parser *P, const char *name, int kind, struct decl **retdecl) {
break;
}
}
- }
- if (0)
-decls: {
- vec_t(struct decl *) decls = {0};
- struct env env = {.parent = P->curenv};
- struct decl *decl;
-
- ty.size = ALIGNUP(size, align);
- ty.align = align;
- ty.agg.name = name;
- vec_slice_cpy(&ty.agg.flds, &flds);
- ty.agg.id = id++;
- pty = interntype(ty);
- if (name) {
- decl = putdecl(P, tok.span,
- &(struct decl){Dtype, name, .span = tok.span, .ty = pty});
- if (decl->ty != pty)
- uninterntype(pty);
- pty = decl->ty;
- }
+ struct type *ppty = (struct type *)pty;
+ ppty->size = ALIGNUP(size, align);
+ ppty->align = align;
+ vec_slice_cpy(&ppty->agg.flds, &flds);
+ if (!decls)
+ return pty;
+ else {
+ vec_t(struct decl *) decls = {0};
+ struct env env = {.parent = P->curenv};
- struct aggdeclyarg yarg = {
- (void *)&decls, P, pty
- };
+ struct aggdeclyarg yarg = {
+ (void *)&decls, P, pty
+ };
- pushenv(P, &env);
- while (!lexmatch(P, &tok, '}')) {
- vec_slice_cpy(&((struct type *)pty)->agg.decls, &decls);
- parsedecl(aggdeclyield, &yarg, P, 0);
- }
+ pushenv(P, &env);
+ while (!lexmatch(P, &tok, '}')) {
+ ppty->agg.decls.d = decls.data;
+ ppty->agg.decls.n = decls.length;
+ parsedecl(aggdeclyield, &yarg, P, 0);
+ }
- vec_slice_cpy(&((struct type *)pty)->agg.decls, &decls);
- popenv(P);
- *retdecl = decl;
- return decl->ty;
+ vec_slice_cpy(&ppty->agg.decls, &decls);
+ popenv(P);
+ return pty;
+ }
}
-
- ty.size = ALIGNUP(size, align);
- ty.align = align;
- ty.agg.name = name;
- vec_slice_cpy(&ty.agg.flds, &flds);
- ty.agg.id = id++;
- return interntype(ty);
}
static struct comfile
diff --git a/bootstrap/test2.cff b/bootstrap/test2.cff
new file mode 100644
index 0000000..ee24d45
--- /dev/null
+++ b/bootstrap/test2.cff
@@ -0,0 +1,6 @@
+import "libc.hff";
+
+struct Node {
+ next *Node,
+ value int,
+}
diff --git a/bootstrap/types.c b/bootstrap/types.c
index 4b4e5be..38d75d0 100644
--- a/bootstrap/types.c
+++ b/bootstrap/types.c
@@ -156,13 +156,12 @@ const struct type *
interntype(struct type ty) {
static int id;
if (!ty.align)
- ty.align = ty.size;
+ ty.align = ty.size ? ty.size : 1;
const struct type *ty2 = typesfind(&ty);
if (ty2)
return ty2;
ty._id = id++;
ty2 = typesput(&ty);
- // epri("new %t, h = %d. %d\n", ty2, hashtype(ty2), ty2->agg.id);
assert(ty2);
return ty2;
}