aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-07 07:19:07 +0200
committerlemon <lsof@mailbox.org>2022-08-07 07:19:07 +0200
commit59988a43079d0097151f57f941ea8f01a0b714d7 (patch)
tree20932bdc821a013efaa06966ec88500ff33e6fc7
parente26df7d77f923108ac121f1d6c9c3160a6855109 (diff)
Type:decl syntax and fix some diagnostics
-rw-r--r--bootstrap/cgen.c2
-rw-r--r--bootstrap/parse.c42
-rw-r--r--bootstrap/test.cff3
3 files changed, 37 insertions, 10 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 2d83044..0bd8bcb 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -624,6 +624,8 @@ defctype(const struct type *ty, void *_) {
pri("_Static_assert(sizeof(%s) == %U);\n", *cname, (u64)ty->size);
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]);
break;
case TYeunion:
break;
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index ace9e68..f286631 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -724,6 +724,16 @@ findaggdecl(const struct type *ty, const char *name) {
return NULL;
}
+static bool
+typematchestarg(const struct type *targ, const struct type *ty) {
+ if (!typeof2(targ, ty))
+ return 0;
+ if (targ->t == TYptr || ty->t == TYptr)
+ if (!targ->child->konst && ty->child->konst)
+ return 0;
+ return 1;
+}
+
static struct expr
parsestructini(struct parser *P, const struct type *ty) {
struct expr ex = {Eini};
@@ -752,7 +762,7 @@ parsestructini(struct parser *P, const struct type *ty) {
if (!fld)
fatal(P, e.span,
"excess elements in struct initializer");
- if (!typeof2(e.ty, fld->ty))
+ if (!typematchestarg(fld->ty, e.ty))
fatal(P, e.span,
"incompatible element `%s` type in %s initializer (%t, expected %t)",
fld->name, kind, e.ty, fld->ty);
@@ -799,7 +809,7 @@ parsearrini(struct parser *P, const struct type *ty) {
P->targty = ty->child;
e = parseexpr(P);
- if (!typeof2(ty->child, e.ty))
+ if (!typematchestarg(ty->child, e.ty))
fatal(P, e.span,
"incompatible element type in array initializer (%t, expected %t)",
e.ty, ty->child);
@@ -879,6 +889,7 @@ pexprimary(struct parser *P) {
const struct decl *decl;
decl = finddecl(P, tok.str);
+ decl:
if (!decl)
fatal(P, tok.span, "%T is not defined", tok);
if (decl->t == Dtype) {
@@ -888,9 +899,20 @@ pexprimary(struct parser *P) {
P->targty = ty;
goto enumlit;
} else if (ty->t == TYstruct || ty->t == TYunion) {
- lexexpect(P, '{');
- P->targty = ty;
- goto aggini;
+ 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];
+ goto decl;
+ }
+ }
+ fatal(P, tok.span, "no such declaration %t:%bs", ty, nam);
+ } else {
+ lexexpects(P, '{', "`{' or `:'");
+ P->targty = ty;
+ goto aggini;
+ }
} else {
goto experr;
}
@@ -1006,17 +1028,19 @@ pexpostfix(struct parser *P) {
while (!lexmatch(P, NULL, ')')) {
int n = ty->fn.params.n;
struct expr arg;
+ const struct type **pty = &ty->fn.params.d[i];
if (i == n && ! ty->fn.variadic)
fatal(P, arg.span, "too many args for call: (expected %d)", n);
if (i < n)
P->targty = ty->fn.params.d[i];
arg = parseexpr(P);
- if (i < n && !typeof2(arg.ty, ty->fn.params.d[i++]))
+ if (i < n && !typematchestarg(*pty, arg.ty))
fatal(P, arg.span,
"call argument #%d type mismatch (%t, expected %t)",
- i, arg.ty, ty->fn.params.d[i - 1]);
+ i, arg.ty, ty->fn.params.d[i]);
+ ++i;
vec_push(&args, arg);
if (!lexmatch(P, NULL, ',')) {
lexexpect(P, ')');
@@ -1577,7 +1601,7 @@ parsevardecl(decl_yielder_t yield, void *yarg, struct parser *P, bool let, bool
// if (ini && decl.t == Dstatic && !fold(ini))
// fatal(P, ini->span, "static initializer isn't constant");
- if (ini && !typeof2(ty, ini->ty))
+ if (ini && !typematchestarg(ty, ini->ty))
fatal(P, tok.span, "incompatible initializer type (%t, expected %t)",
ini->ty, ty);
@@ -1944,7 +1968,7 @@ parsestmt(stmt_yielder_t yield, void *yarg, struct parser *P) {
P->targty = P->curfn->retty;
st.retex = exprdup(parseexpr(P));
lexexpect(P, ';');
- if (!typeof2(st.retex->ty, P->curfn->retty))
+ if (!typematchestarg(st.retex->ty, P->curfn->retty))
fatal(P, st.retex->span,
"incompatible type in return statement (%t, expected %t)",
st.retex->ty, P->curfn->retty);
diff --git a/bootstrap/test.cff b/bootstrap/test.cff
index 2a7a138..4d1393b 100644
--- a/bootstrap/test.cff
+++ b/bootstrap/test.cff
@@ -68,7 +68,7 @@ extern fn main (argc int, argv **u8) int {
let p *const Vec2f = &x;
printf("v = { %g, %g }\n", x.x, p.y);
printf("mag = %g\n", x->mag());
- x->zero();
+ Vec2f:zero(&x);
printf("mag = %g\n", (&x)->mag());
let is []int = { [4] = 1, 2, [1 - 1] = 3 };
@@ -84,6 +84,7 @@ extern fn main (argc int, argv **u8) int {
slice.#len;
let const v Vec2f = {};
+ ! v->zero();
! v.x += 1;
printf("sizeof(is) = %zu\n", sizeof(is));