diff options
| author | 2022-08-07 07:19:07 +0200 | |
|---|---|---|
| committer | 2022-08-07 07:19:07 +0200 | |
| commit | 59988a43079d0097151f57f941ea8f01a0b714d7 (patch) | |
| tree | 20932bdc821a013efaa06966ec88500ff33e6fc7 | |
| parent | e26df7d77f923108ac121f1d6c9c3160a6855109 (diff) | |
Type:decl syntax and fix some diagnostics
| -rw-r--r-- | bootstrap/cgen.c | 2 | ||||
| -rw-r--r-- | bootstrap/parse.c | 42 | ||||
| -rw-r--r-- | bootstrap/test.cff | 3 |
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)); |