aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap/parse.c')
-rw-r--r--bootstrap/parse.c87
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);