aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff43
1 files changed, 36 insertions, 7 deletions
diff --git a/src/parse.cff b/src/parse.cff
index 1ea05d5..c3831ef 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -832,7 +832,7 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type {
let loc = container_of(tepl, Decl, u.Tepl).loc;
while !lexmatch(P, &tok, '>') {
let par = &tepl.params[i];
- let toks [#]Tok = (as(*Tok)P.alloc->alloc(sizeof Tok, alignof Tok))[0::1];
+ let toks [#]Tok = (as(*Tok)P.tlalloc->alloc(sizeof Tok, alignof Tok))[0::1];
switch par.u {
case Ty;
toks[0] = { :typearg, P.curloc, parsetype(P), .u: { .ident: par.name }};
@@ -893,7 +893,6 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type {
let arg = &tpargs[i];
switch cache.args[i] {
case Ty ty;
- efmt("cmp %t %t\n",ty,arg.Ty);
if ty != arg.Ty {
continue #'search;
}
@@ -922,7 +921,7 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type {
free(tpargs.#ptr);
return cache.ty;
}
- let env = mkenv(tepl.env, P.alloc);
+ let env = mkenv(tepl.env, P.tlalloc);
with_tmpchange(P.curenv, env) {
let decl *Decl #?;
let expan Expan = {
@@ -935,11 +934,10 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type {
P.peektok = :None;
envfree(env);
(as(*Type)ty).u.Agg.tpargs = tpargs;
- cache = P.alloc->alloc(sizeof(*cache), alignof(*cache));
+ cache = P.tlalloc->alloc(sizeof(*cache), alignof(*cache));
cache.next = tepl.cache;
cache.args = tpargs;
cache.ty = ty;
- efmt("new %s %p %t %p\n", tname, tepl, tpargs[0].Ty, tpargs[0].Ty);
tepl.cache = cache;
return ty;
}
@@ -1111,12 +1109,16 @@ fn parseaggini(P *Parser, loc Loc, ty *const Type) Expr {
iota = (fld - ty.u.Agg.flds.#ptr) + 1;
} else {
if iota >= ty.u.Agg.flds.#len {
- fatal(P, tok.loc, "excess elements in struct initializer");
+ fatal(P, tok.loc, "excess elements in %t struct initializer", ty);
}
fld = &ty.u.Agg.flds[iota++];
}
P.targty = fld.ty;
ex = parseexpr(P);
+ if !typematchestarg(fld.ty, ex.ty) {
+ err(P, ex.loc, "incompatible element `%s' type in %t initializer (%t, expected %t)",
+ fld.name, ty, ex.ty, fld.ty);
+ }
flds->push(fld);
exs->push(ex);
if !lexmatch(P, &tok, ',') {
@@ -1387,6 +1389,27 @@ fn pexprimary(P *Parser) Expr {
}
ex = { tok.loc, ty_usize, :IntLit { ty.align }};
+ case :kw_offsetof;
+ lexexpect(P, '(');
+ let ty = parsetype(P);
+ lexexpect(P, ',');
+ let off = 0z;
+ for ;; {
+ let name = (tok = lexexpect(P, :ident)).u.ident;
+ let fld = findaggfield(ty, name);
+ if fld == #null {
+ fatal(P, tok.loc, "%t has no such field %qT", ty, tok);
+ }
+ off += fld.off;
+ ty = fld.ty;
+ if !lexmatch(P, #null, '.') {
+ lexmatch(P, #null, ',');
+ lexexpect(P, ')');
+ break;
+ }
+ }
+ ex = { tok.loc, ty_usize, :IntLit { off }};
+
case '(';
if lexmatch(P, &tok, :kw_do) {
let st = parseblock0(P);
@@ -2467,6 +2490,7 @@ fn doimport(P *Parser, loc Loc, path *const u8) [#]Decl {
let P2 Parser #?;
parser_init(&P2, rpath);
P2.is_header = #t;
+ P2.tlalloc = P.tlalloc;
P2.alloc = P.alloc;
let decls = parse4import(&P2);
@@ -2766,6 +2790,11 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool)
let name = lexexpects(P, :ident, "macro name").u.ident;
decl = parsemacro(P, tok.loc, name);
+ case lexmatch(P, &tok, :kw_typedef);
+ let name = lexexpects(P, :ident, "typedef name").u.ident;
+ decl = putdecl(P, tok.loc, { name, tok.loc, .u: :Ty(parsetype(P)) });
+ lexexpect(P, ';');
+
case else;
if (tok = lexpeek(P)).t == :ident {
let decl = finddecl(P, tok.u.ident);
@@ -2805,7 +2834,7 @@ extern fn parse(P *Parser) [#]Decl {
let aralloc = Arena {};
let alloc = Allocator { &aralloc, &Arena:allocf, #null };
let decls Vec<Decl> = {};
- P.alloc = &alloc;
+ P.alloc = (P.tlalloc = &alloc);
P.curenv = mkenv(#null, P.alloc);
if primenv == #null {
primenv = mkenv(#null, P.alloc);