diff options
Diffstat (limited to 'src/parse.cff')
| -rw-r--r-- | src/parse.cff | 43 |
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); |