diff options
Diffstat (limited to 'bootstrap/parse.c')
| -rw-r--r-- | bootstrap/parse.c | 87 |
1 files changed, 52 insertions, 35 deletions
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); |