diff options
| -rw-r--r-- | bootstrap/all.h | 8 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 4 | ||||
| -rw-r--r-- | bootstrap/dump.c | 5 | ||||
| -rw-r--r-- | bootstrap/env.c | 29 | ||||
| -rw-r--r-- | bootstrap/parse.c | 87 | ||||
| -rw-r--r-- | bootstrap/test.cff | 25 | ||||
| -rw-r--r-- | bootstrap/types.c | 3 |
7 files changed, 93 insertions, 68 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index 2f7f070..8c80fe4 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -177,7 +177,7 @@ struct type { const char *name; const struct type *ty; }) flds; - slice_t(struct decl) decls; + slice_t(struct decl *) decls; bool fwd; int id; } agg; @@ -382,12 +382,8 @@ struct stmt { }; }; -struct declsl { - slice_t(struct decl); -}; - struct comfile { - struct declsl decls; + slice_t(struct decl *) decls; }; /************/ diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 0bd8bcb..91429ee 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -625,7 +625,7 @@ defctype(const struct type *ty, void *_) { pri("_Static_assert(__alignof__(%s) == %U);\n", *cname, (u64)ty->align); } for (int i = 0; i < ty->agg.decls.n; ++i) - liftdecl(&ty->agg.decls.d[i]); + liftdecl(ty->agg.decls.d[i]); break; case TYeunion: break; @@ -650,6 +650,6 @@ cgen(FILE *fp, const struct comfile *cf) { visittypes(defctype, NULL); for (int i = 0; i < cf->decls.n; ++i) { - gendecl(&cf->decls.d[i], 1); + gendecl(cf->decls.d[i], 1); } } diff --git a/bootstrap/dump.c b/bootstrap/dump.c index 8bec36d..84c4bbe 100644 --- a/bootstrap/dump.c +++ b/bootstrap/dump.c @@ -201,6 +201,9 @@ vepri(const char *fmt, va_list ap) { case 's': fprintf(stderr, "%s", va_arg(ap, const char *)); break; + case 'p': + fprintf(stderr, "%p", va_arg(ap, void *)); + break; case 'q': S = va_arg(ap, const char *); pristring(S, strlen(S)); @@ -420,5 +423,5 @@ dumpdecl(const struct decl *decl, int ws) { void dumpcomfile(const struct comfile *cf) { for (int i = 0; i < cf->decls.n; ++i) - dumpdecl(&cf->decls.d[i], 0); + dumpdecl(cf->decls.d[i], 0); } diff --git a/bootstrap/env.c b/bootstrap/env.c index 477c267..ddd06b2 100644 --- a/bootstrap/env.c +++ b/bootstrap/env.c @@ -14,20 +14,7 @@ envfind(const struct env *env, const char *name) { static bool declsshadowable(const struct decl *a, const struct decl *b) { - return b->t == Dlet; -} - -static bool -declscompatible(const struct decl *a, const struct decl *b) { - if (a->t != b->t) - return 0; - if (a->t == Dfn && a->externp == b->externp && a->fn.selfty == b->fn.selfty && !a->fn.body) - return 1; - if (a->t == Dstatic && a->externp == b->externp && a->var.ty == b->var.ty && !a->var.ini) - return 1; - if (a->t == Dtype && a->ty == b->ty) - return 1; - return 0; + return a->t == Dlet && b->t == Dlet; } struct decl * @@ -38,10 +25,10 @@ envput(struct env *env, const struct decl *decl) { }; struct decl *d0; if ((d0 = envfind(&env_noparent, decl->name))) { + // modify existing forward declarations? for (int kind = TYstruct; kind <= TYunion; ++kind) { if (d0->t == Dtype && d0->ty->t == kind && decl->t == Dtype && decl->ty->t == kind && d0->ty->agg.fwd) { - // modify existing forward declaration *(size_t *)&d0->ty->size = decl->ty->size; *(size_t *)&d0->ty->align = decl->ty->align; *(bool *)&d0->ty->agg.fwd = 0; @@ -53,7 +40,17 @@ envput(struct env *env, const struct decl *decl) { return d0; } } - if (!declsshadowable(d0, decl) && !declscompatible(d0, decl)) { + if (d0->t == Dfn && d0->externp == decl->externp && d0->fn.selfty == decl->fn.selfty && !d0->fn.body && decl->fn.body) { + d0->fn.body = decl->fn.body; + return d0; + } + if (d0->t == Dfn && d0->externp == decl->externp && d0->fn.selfty == decl->fn.selfty && !d0->fn.body) + return d0; + if (d0->t == Dstatic && d0->externp == decl->externp && d0->var.ty == decl->var.ty && !d0->var.ini) + return d0; + if (d0->t == Dtype && d0->ty == decl->ty) + return d0; + if (!declsshadowable(d0, decl)) { return NULL; } } diff --git a/bootstrap/parse.c b/bootstrap/parse.c index f286631..0a1db86 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -588,9 +588,10 @@ static const struct type * parsetype(struct parser *P) { struct tok tok; if (lexmatch(P, &tok, '*')) { + const struct type *child = parsetype(P); return interntype((struct type) { - TYptr, g_targ.ptrsize, - .child = parsetype(P) + TYptr, g_targ.ptrsize, g_targ.ptrsize, + .child = child, }); } else if (lexmatch(P, &tok, '[')) { i64 length = -1; @@ -719,8 +720,8 @@ static struct decl * findaggdecl(const struct type *ty, const char *name) { assert(name); for (int i = 0; i < ty->agg.decls.n; ++i) - if (!strcmp(name, ty->agg.decls.d[i].name)) - return &ty->agg.decls.d[i]; + if (!strcmp(name, ty->agg.decls.d[i]->name)) + return ty->agg.decls.d[i]; return NULL; } @@ -902,8 +903,8 @@ pexprimary(struct parser *P) { if (lexmatch(P, &tok, ':')) { const char *nam = (tok = lexexpect(P, TKident)).str; for (int i = 0; i < ty->agg.decls.n; ++i) { - if (!strcmp(ty->agg.decls.d[i].name, nam)) { - decl = &ty->agg.decls.d[i]; + if (!strcmp(ty->agg.decls.d[i]->name, nam)) { + decl = ty->agg.decls.d[i]; goto decl; } } @@ -1634,7 +1635,7 @@ parsevardecl(decl_yielder_t yield, void *yarg, struct parser *P, bool let, bool decl.var.ini = ini; decl.var.id = id++; decl.var.fnid = P->curfn ? P->curfn->id : -1; - yield(&decl, yarg); + yield(memcpy(xmalloc(sizeof decl), &decl, sizeof decl), yarg); if (!lexmatch(P, &tok, ',')) { lexexpect(P, ';'); break; @@ -2106,6 +2107,7 @@ parsefn(struct decl *decl, struct parser *P) { popenv(P); } } + fn->selfty = fntype(fn); } static struct macrocase @@ -2281,8 +2283,26 @@ parseenum(struct parser *P, const char *name) { return interntype(ty); } +struct aggdeclyarg { + vec_t(struct decl *) *decls; + struct parser *P; + const struct type *aggty; +}; + +static void +aggdeclyield(struct decl *decl, void *arg) { + struct aggdeclyarg *a = arg; + + if (decl->t == Dtype && decl->ty == a->aggty) + ; + else if (decl->t == Dfn && !decl->externp) + vec_push(a->decls, decl); + else + fatal(a->P, decl->span, "this kind of declaration is disallowed inside aggregates"); +} + static const struct type * -parseagg(struct parser *P, const char *name, int kind, bool *put) { +parseagg(struct parser *P, const char *name, int kind, struct decl **retdecl) { struct tok tok; struct type ty = {kind}; const struct type *pty = NULL; @@ -2290,7 +2310,7 @@ parseagg(struct parser *P, const char *name, int kind, bool *put) { size_t size = 0, align = 1; vec_t(struct aggfield) flds = {0}; - *put = 1; + *retdecl = NULL; if (lexmatch(P, &tok, ';')) { ty.agg.fwd = 1; @@ -2331,7 +2351,7 @@ parseagg(struct parser *P, const char *name, int kind, bool *put) { } if (0) decls: { - vec_t(struct decl) decls = {0}; + vec_t(struct decl *) decls = {0}; struct env env = {.parent = P->curenv}; struct decl *decl; @@ -2349,22 +2369,19 @@ decls: { pty = decl->ty; } + struct aggdeclyarg yarg = { + (void *)&decls, P, pty + }; + pushenv(P, &env); - while (!lexmatch(P, &tok, '}')) - parsedecl(NULL, NULL, P, 0); - for (struct decls *ds = env.decls, *next; ds; ds = next) { - if (ds->decl.t == Dtype && ds->decl.ty == pty) - ; - else if (ds->decl.t == Dfn && !ds->decl.externp && ds->decl.fn.body) - vec_push(&decls, ds->decl); - else - fatal(P, ds->decl.span, "this kind of declaration is disallowed inside aggregates"); - next = ds->next; - free(ds); + while (!lexmatch(P, &tok, '}')) { + vec_slice_cpy(&((struct type *)pty)->agg.decls, &decls); + parsedecl(aggdeclyield, &yarg, P, 0); } - vec_slice_cpy(&((struct type *)decl->ty)->agg.decls, &decls); + + vec_slice_cpy(&((struct type *)pty)->agg.decls, &decls); popenv(P); - *put = 0; + *retdecl = decl; return decl->ty; } @@ -2415,10 +2432,10 @@ staticvaryield(struct decl *decl, void *arg) { decl->span = a->espan; if (!a->toplevel && !a->externp && !decl->var.ini) fatal(a->P, decl->span, - "static variable inside function cannot be forward-declared"); + "static variable not in toplevel cannot be forward-declared"); if (!a->toplevel && a->externp && decl->var.ini) fatal(a->P, decl->span, - "extern static variable inside function cannot be initialized"); + "extern static variable not in toplevel cannot be initialized"); if (a->P->is_header && a->externp && decl->var.ini) fatal(a->P, decl->span, "cannot define extern variable in header"); @@ -2433,6 +2450,7 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { const char *name; int kind; struct decl decl = {0}; + struct decl* decl2 = NULL; if (lexmatch(P, &tok, TKkw_extern)) externp = 1; @@ -2473,13 +2491,12 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { decl.name = lexexpects(P, TKident, "enum name").str; decl.ty = parseenum(P, decl.name); } else if (lexmatch(P, &tok, TKkw_struct)) { - bool put; kind = TYstruct; if (externp) fatal(P, tok.span, "struct cannot be `extern'"); agg: decl.name = lexexpects(P, TKident, "struct name").str; - decl.ty = parseagg(P, decl.name, kind, &put); - if (!put) goto noput; + decl.ty = parseagg(P, decl.name, kind, &decl2); + if (decl2) goto noput; } else if (lexmatch(P, &tok, TKkw_union)) { if (externp) fatal(P, tok.span, "union cannot be `extern'"); kind = TYunion; @@ -2491,9 +2508,9 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { path = lexexpect(P, TKstrlit).str; cf = doimport(P, path); for (int i = 0; i < cf.decls.n; ++i) { - putdecl(P, tok.span, &cf.decls.d[i]); + struct decl *decl = putdecl(P, tok.span, cf.decls.d[i]); if (yield) - yield(&cf.decls.d[i], yarg); + yield(decl, yarg); } free(cf.decls.d); lexexpect(P, ';'); @@ -2503,21 +2520,21 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { tok2str(tok)); } - decl = *putdecl(P, tok.span, &decl); + decl2 = putdecl(P, tok.span, &decl); noput: if (yield) - yield(&decl, yarg); + yield(decl2 ? decl2 : &decl, yarg); } static void yieldexdecl(struct decl *decl, void *arg) { - vec_t(struct decl) *decls = arg; - vec_push(decls, *decl); + vec_t(struct decl *) *decls = arg; + vec_push(decls, decl); } void parse(struct comfile *cf, struct parser *P) { - vec_t(struct decl) decls = {0}; + vec_t(struct decl *) decls = {0}; while (!P->eof && lexpeek(P).t != TKeof) parsedecl(yieldexdecl, &decls, P, 1); vec_slice_cpy(&cf->decls, &decls); diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 4d1393b..14d489e 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -1,5 +1,4 @@ import "libc.hff"; -import "libc.hff"; union Val { u u32, @@ -18,10 +17,9 @@ defmacro each(i, x, arr, ...body) [ } ] -static xs *void = {}, - ok = 6; +static xs *void = {}; -fn isort(xs *int, n usize) void { +fn isort(xs *int, n usize) void { fn icmp(lhs *const void, rhs *const void, _ *void) int { let lhs = *as(*int)lhs, rhs = *as(*int)rhs; @@ -34,6 +32,23 @@ fn isort(xs *int, n usize) void { x(); } +struct List; +struct List { + next *List, + val int, + + fn ok(l List) void; + + fn length(l *List) usize { + let n = 0z; + ok(*l); + for ; l; l = l.next { ++n; } + return n; + } + + fn ok(l List) void {} +} + struct Vec2f; struct Vec2f { x f32, @@ -51,7 +66,7 @@ struct Vec2f { fn spanz(cstr *const u8) [#]const u8 { extern fn strlen(s *const u8) usize; - return cstr[0::strlen(cstr) + 1]; + return cstr[0 :: strlen(cstr)]; } defmacro transmute(Type, x) [ diff --git a/bootstrap/types.c b/bootstrap/types.c index f826f9d..4b4e5be 100644 --- a/bootstrap/types.c +++ b/bootstrap/types.c @@ -45,7 +45,6 @@ hashtype(const struct type *ty) { break; case TYptr: case TYslice: - assert(ty->child->size || ty->align == 1); h = fnv1ai(h, ty->child->_id); break; case TYarr: @@ -158,8 +157,6 @@ interntype(struct type ty) { static int id; if (!ty.align) ty.align = ty.size; - if ((ty.t == TYptr || ty.t == TYarr) && !ty.child->size) - ty.align = 1; const struct type *ty2 = typesfind(&ty); if (ty2) return ty2; |