From 0a4f81e86d21d056329a2b7b2186152e9b9c2375 Mon Sep 17 00:00:00 2001 From: lemon Date: Sun, 7 Aug 2022 11:13:51 +0200 Subject: recursive datatypes without forward declaring first --- bootstrap/parse.c | 90 +++++++++++++++++++++++++++-------------------------- bootstrap/test2.cff | 6 ++++ bootstrap/types.c | 3 +- 3 files changed, 53 insertions(+), 46 deletions(-) create mode 100644 bootstrap/test2.cff 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; } -- cgit v1.2.3