aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-07 09:35:07 +0200
committerlemon <lsof@mailbox.org>2022-08-07 09:35:07 +0200
commitf97e08b3da14c79f7f78e439d06988753c79384b (patch)
treef4d51145f057a38c99bc304d15a422546dc766ef
parent59988a43079d0097151f57f941ea8f01a0b714d7 (diff)
many decl bugfixes
-rw-r--r--bootstrap/all.h8
-rw-r--r--bootstrap/cgen.c4
-rw-r--r--bootstrap/dump.c5
-rw-r--r--bootstrap/env.c29
-rw-r--r--bootstrap/parse.c87
-rw-r--r--bootstrap/test.cff25
-rw-r--r--bootstrap/types.c3
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;