From 87ee8d01a7e8a19461d712c7acd3e2050ccf3ffc Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 19 Aug 2022 11:05:06 +0200 Subject: do not use P.tokloc directly for it is not what is intended whilst a macro is being expanded --- src/parse.cff | 119 +++++++++++++++++++++++++++------------------------------- 1 file changed, 56 insertions(+), 63 deletions(-) (limited to 'src/parse.cff') diff --git a/src/parse.cff b/src/parse.cff index 96106c7..1125f37 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -625,7 +625,7 @@ fn parseexpr(P *Parser) Expr; fn pexbitarith(P *Parser) Expr; fn parsetype(P *Parser) *const Type; typedef DeclYielder *fn(*Decl, *void) void; -fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void; +fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) void; fn parseenum(P *Parser, name *const u8, lax bool) *const Type { lexexpect(P, '{'); @@ -667,8 +667,7 @@ fn isdecltokt(t TokT) bool { return #f; } -fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type { - let loc = P.tokloc; +fn parseagg(P *Parser, loc Loc, kind AggKind, name *const u8, retdecl **Decl) *const Type { let tok Tok #?; static id int = 0; let decl *Decl = name ? finddecl_noparent(P, name) : #null; @@ -768,7 +767,7 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type agg.decls = mkenv(P.curenv, P.alloc); pushenv(P, agg.decls); while !lexmatch(P, #null, '}') { - parsedecls(P, #null, #null, #{toplevel} #f); + parsedecls(P, tok.loc, #null, #null, #{toplevel} #f); } popenv(P); } @@ -869,7 +868,6 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type { #'search for cache = tepl.cache; cache; cache = cache.next { for let i = 0; i < nparam; ++i { - // XXX memcmp reliable? let arg = &tpargs[i]; switch cache.args[i] { case Ty ty; @@ -906,7 +904,7 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type { let expan Expan = { P.curexpan, args[0::nparam], tepl.toks, tname, tok.loc, #{tepl?} #t }; ++P.expanno; P.curexpan = memcpy(xmalloc(sizeof Expan), &expan, sizeof Expan); - ty = parseagg(P, tepl.kind, tname, &decl); + ty = parseagg(P, loc, tepl.kind, tname, &decl); } envfree(env); @@ -1049,8 +1047,8 @@ fn islvalue(ex Expr) bool { return #f; } -fn parseaggini(P *Parser, ty *const Type) Expr { - let loc = P.tokloc; +fn parseaggini(P *Parser, loc Loc, ty *const Type) Expr { + let loc = loc; let tok Tok #?; let flds Vec<*const AggField> = {}; let exs Vec = {}; @@ -1067,7 +1065,7 @@ fn parseaggini(P *Parser, ty *const Type) Expr { iota = (fld - ty.u.Agg.flds.#ptr) + 1; } else { if iota >= ty.u.Agg.flds.#len { - fatal(P, P.tokloc, "excess elements in struct initializer"); + fatal(P, tok.loc, "excess elements in struct initializer"); } fld = &ty.u.Agg.flds[iota++]; } @@ -1083,8 +1081,7 @@ fn parseaggini(P *Parser, ty *const Type) Expr { return { loc, ty, :AggIni { flds->move(P.alloc), exs->move(P.alloc) }}; } -fn parsearrini(P *Parser, ty *const Type) Expr { - let loc = P.tokloc; +fn parsearrini(P *Parser, loc Loc, ty *const Type) Expr { let tok Tok #?; let idxs Vec = {}; let exs Vec = {}; @@ -1142,12 +1139,11 @@ fn mergetoktrees(alloc *Allocator, src *[#]Tok, n int) [#]Tok { return d[0::len]; } -fn parseexpandmacro(P *Parser, mac *Macro) void { +fn parseexpandmacro(P *Parser, loc Loc, mac *Macro) void { let tok Tok #?; let expan Expan = {}; let args Vec<[#]Tok> = {}; let c MacroCase #?; - let loc = P.tokloc; let mname = container_of(mac, Decl, u.Macro).name; lexexpect(P, '('); @@ -1289,7 +1285,7 @@ fn pexprimary(P *Parser) Expr { dex.loc = tok.loc; ex = dex; case Macro *mac; - parseexpandmacro(P, mac); + parseexpandmacro(P, tok.loc, mac); ex = parseexpr(P); case Ty ty; if (tok = lexpeek(P)).t != ':' and tok.t != '{' { @@ -1387,7 +1383,7 @@ fn pexprimary(P *Parser) Expr { fatal(P, iex.loc, "%t variant %qT is empty", ty, tok); } } else if fld.ty { - fatal(P, P.tokloc, "%t variant %qT must be initialized", ty, tok); + fatal(P, tok.loc, "%t variant %qT must be initialized", ty, tok); } ex = { tok.loc, ty, :EUnionIni { fld, iex }}; } else { @@ -1404,9 +1400,9 @@ fn pexprimary(P *Parser) Expr { ex = { tok.loc, ty, .u: :ZeroIni }; } else { if ty->is(:Agg) { - ex = parseaggini(P, ty); + ex = parseaggini(P, tok.loc, ty); } else if ty->is(:Arr) { - ex = parsearrini(P, ty); + ex = parsearrini(P, tok.loc, ty); } else { fatal(P, tok.loc, "excess elements in initializer"); } @@ -1897,17 +1893,17 @@ fn pstlet(P *Parser, yield StmtYielder, yarg *void) void { parsevardecl(P, #{toplevel?} #f, #{extern?} #f, #{let?} #t, &varyield, &Arg { P, yield, yarg }); } -fn pstif(P *Parser) Stmt { - let loc = P.tokloc; +fn pstif(P *Parser, loc Loc) Stmt { let test = parseexpr(P); if !test.ty->is(:Bool) and !test.ty->is(:Ptr) { err(P, test.loc, "if condition must be bool or pointer (%t)", test.ty); } lexexpect(P, '{'); let t = parseblock(P); - if lexmatch(P, #null, :kw_else) { - if lexmatch(P, #null, :kw_if) { - let f = stmtdup(P.alloc, pstif(P)); + let tok Tok #?; + if lexmatch(P, &tok, :kw_else) { + if lexmatch(P, &tok, :kw_if) { + let f = stmtdup(P.alloc, pstif(P, tok.loc)); return { loc, :If { test, t, f[0::1] }}; } else { lexexpect(P, '{'); @@ -1918,8 +1914,7 @@ fn pstif(P *Parser) Stmt { return { loc, :If { test, t }}; } -fn pstreturn(P *Parser) Stmt { - let loc = P.tokloc; +fn pstreturn(P *Parser, loc Loc) Stmt { if P.curfn == #null { fatal(P, loc, "return outside function"); } @@ -1940,8 +1935,7 @@ fn pstreturn(P *Parser) Stmt { } } -fn pstwhile(P *Parser) Stmt { - let loc = P.tokloc; +fn pstwhile(P *Parser, loc Loc) Stmt { let test = parseexpr(P); if !test.ty->is(:Bool) and !test.ty->is(:Ptr) { err(P, test.loc, "while condition must be bool or pointer (%t)", test.ty); @@ -1954,11 +1948,11 @@ fn pstwhile(P *Parser) Stmt { return { loc, :While { test, t, P.loopid }}; } -fn pstfor(P *Parser) Stmt { - let loc = P.tokloc; +fn pstfor(P *Parser, loc Loc) Stmt { let ini [#]Stmt = {}; let test Expr #?; let next = Option:None; + let tok Tok #?; if lexmatch(P, #null, :kw_let) { let sts Vec = {}; fn yieldlet(st Stmt, arg *void) void { @@ -1974,9 +1968,9 @@ fn pstfor(P *Parser) Stmt { ini = stmtdup(P.alloc, { ex.loc, :Expr(ex) })[0::1]; } - if lexmatch(P, #null, ';') { + if lexmatch(P, &tok, ';') { // for (...; ; ...;) -> for (...; #t; ...;) - test = { P.tokloc, ty_bool, :BoolLit(#t) }; + test = { tok.loc, ty_bool, :BoolLit(#t) }; } else { test = parseexpr(P); lexexpect(P, ';'); @@ -2036,8 +2030,7 @@ fn psteuswitch(P *Parser, loc Loc, ex Expr) Stmt { let ty = ex.ty; } -fn pstswitch(P *Parser) Stmt { - let loc = P.tokloc; +fn pstswitch(P *Parser, loc Loc) Stmt { let tok Tok #?; if lexmatch(P, &tok, '{') { } else { @@ -2065,16 +2058,16 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { return pstlet(P, yield, yarg); case lexmatch(P, &tok, :kw_if); - return yield(pstif(P), yarg); + return yield(pstif(P, tok.loc), yarg); case lexmatch(P, &tok, :kw_return); - return yield(pstreturn(P), yarg); + return yield(pstreturn(P, tok.loc), yarg); case lexmatch(P, &tok, :kw_while); - return yield(pstwhile(P), yarg); + return yield(pstwhile(P, tok.loc), yarg); case lexmatch(P, &tok, :kw_for); - return yield(pstfor(P), yarg); + return yield(pstfor(P, tok.loc), yarg); case lexmatch(P, &tok, :kw_break); if P.curloop == 0 { @@ -2091,7 +2084,7 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { return yield({ tok.loc, :Continue(P.curloop) }, yarg); case lexmatch(P, &tok, :kw_switch); - return yield(pstswitch(P), yarg); + return yield(pstswitch(P, tok.loc), yarg); case isdecltokt(tok.t); struct Arg { @@ -2103,14 +2096,14 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { let a *Arg = arg; a.yield({ decl.loc, :Decl(decl) }, a.yarg); } - parsedecls(P, &declyield, &Arg { P, yield, yarg }, #{toplevel?} #f); + parsedecls(P, tok.loc, &declyield, &Arg { P, yield, yarg }, #{toplevel?} #f); case else; if (tok = lexpeek(P)).t == :ident { let decl = finddecl(P, tok.u.ident); if decl != #null and decl.u.#tag == :Macro { lex(P); - parseexpandmacro(P, &decl.u.Macro); + parseexpandmacro(P, tok.loc, &decl.u.Macro); return parsestmts(P, yield, yarg); } } @@ -2207,10 +2200,10 @@ fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, yield DeclYie } while !lexmatch(P, &tok, ';'); } -fn parsefn(P *Parser, externp bool, name *const u8) *Decl { +fn parsefn(P *Parser, loc Loc, externp bool, name *const u8) *Decl { let decl Decl = { name, - P.tokloc, + loc, externp, .u: :Fn {} }; @@ -2219,7 +2212,6 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { paramnames Vec<*const u8> = {}, paramtys Vec<*const Type> = {}; - let loc = P.tokloc; parsefnparams(P, &Fn.variadic, ¶mnames, ¶mtys); Fn.paramnames = paramnames->move(P.alloc); let retty = parsetype(P); @@ -2255,7 +2247,7 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { return decl; } -fn doimport(P *Parser, path *const u8) [#]Decl { +fn doimport(P *Parser, loc Loc, path *const u8) [#]Decl { struct Entry { decls [#]Decl, wip bool, @@ -2283,7 +2275,7 @@ fn doimport(P *Parser, path *const u8) [#]Decl { snprintf(path2, sizeof(path2) - 1, "%s/%s", basedir, path); let rpath *const u8 = realpath(path2, _rpath); if rpath == #null { - fatal(P, P.tokloc, "import %qs: %s", path, strerror(errno)); + fatal(P, loc, "import %qs: %s", path, strerror(errno)); } let d0 = seen->get(rpath); if d0 != #null { @@ -2300,7 +2292,7 @@ fn doimport(P *Parser, path *const u8) [#]Decl { return decls; } -fn parsemacro(P *Parser, name *const u8) *Decl { +fn parsemacro(P *Parser, loc Loc, name *const u8) *Decl { fn parsemacrocase(P *Parser) MacroCase { let tok Tok #?; let c MacroCase = {}; @@ -2390,7 +2382,6 @@ fn parsemacro(P *Parser, name *const u8) *Decl { return c; } - let loc = P.tokloc; let tok Tok #?; let cs Vec = {}; if lexpeek(P).t == '(' { @@ -2409,9 +2400,9 @@ fn parsemacro(P *Parser, name *const u8) *Decl { return putdecl(P, loc, { name, loc, .u: :Macro { cs->move(P.alloc) }}); } -fn parsetepl(P *Parser, kind AggKind, name *const u8) Tepl { +fn parsetepl(P *Parser, loc Loc, kind AggKind, name *const u8) Tepl { if envparent(P.curenv) { - fatal(P, P.tokloc, "templates can only defined be at top-level"); + fatal(P, loc, "templates can only defined be at top-level"); } let params Vec = {}; let toks Vec = {}; @@ -2456,8 +2447,8 @@ fn parsetepl(P *Parser, kind AggKind, name *const u8) Tepl { return { kind, P.curenv, params->move(P.alloc), toks->move(P.alloc), #null }; } -fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { - let tok = Tok { .loc: P.tokloc }, +fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) void { + let tok = Tok { .loc: loc }, decl *Decl = {}, externp = #f, name *const u8 = #null; @@ -2472,11 +2463,11 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { switch { case lexmatch(P, &tok, :kw_fn); let name = lexmatch(P, &tok, :ident) ? tok.u.ident : #null; - decl = parsefn(P, externp, name); + decl = parsefn(P, tok.loc, externp, name); case lexmatch(P, &tok, :kw_import); let path = (tok = lexexpects(P, :str, "import path")).u.str.#ptr; - let decls = doimport(P, path); + let decls = doimport(P, tok.loc, path); foreach(decl, _, decls) { let decl = putdecl(P, tok.loc, decl); if yield { @@ -2490,13 +2481,13 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { if lexmatch(P, &tok, :kw_union) { let name = lexexpect(P, :ident).u.ident; if !lexmatch(P, #null, '<') { - parseagg(P, :EUnion, name, &decl); + parseagg(P, tok.loc, :EUnion, name, &decl); } else { - decl = putdecl(P, tok.loc, { name, tok.loc, .u: :Tepl(parsetepl(P, :EUnion, name)) }); + decl = putdecl(P, tok.loc, + { name, tok.loc, .u: :Tepl(parsetepl(P, tok.loc, :EUnion, name)) }); } } else { let name = lexexpect(P, :ident).u.ident; - let loc = P.tokloc; let ty = parseenum(P, name, #{lax} #f); decl = putdecl(P, loc, { name, loc, .u: :Ty(ty) }); } @@ -2504,17 +2495,19 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { case lexmatch(P, &tok, :kw_struct); let name = lexexpect(P, :ident).u.ident; if !lexmatch(P, #null, '<') { - parseagg(P, :Struct, name, &decl); + parseagg(P, tok.loc, :Struct, name, &decl); } else { - decl = putdecl(P, tok.loc, { name, tok.loc, .u: :Tepl(parsetepl(P, :Struct, name)) }); + decl = putdecl(P, tok.loc, + { name, tok.loc, .u: :Tepl(parsetepl(P, tok.loc, :Struct, name)) }); } case lexmatch(P, &tok, :kw_union); let name = lexexpect(P, :ident).u.ident; if !lexmatch(P, #null, '<') { - parseagg(P, :Union, name, &decl); + parseagg(P, tok.loc, :Union, name, &decl); } else { - decl = putdecl(P, tok.loc, { name, tok.loc, .u: :Tepl(parsetepl(P, :Union, name)) }); + decl = putdecl(P, tok.loc, + { name, tok.loc, .u: :Tepl(parsetepl(P, tok.loc, :Union, name)) }); } case lexmatch(P, &tok, :kw_static); @@ -2575,15 +2568,15 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { case lexmatch(P, &tok, :kw_defmacro); let name = lexexpects(P, :ident, "macro name").u.ident; - decl = parsemacro(P, name); + decl = parsemacro(P, tok.loc, name); case else; if (tok = lexpeek(P)).t == :ident { let decl = finddecl(P, tok.u.ident); if decl != #null and decl.u.#tag == :Macro { lex(P); - parseexpandmacro(P, &decl.u.Macro); - return parsedecls(P, yield, yarg, toplevel); + parseexpandmacro(P, tok.loc, &decl.u.Macro); + return parsedecls(P, tok.loc, yield, yarg, toplevel); } } fatal(P, tok.loc, "expected declaration (near %qT)", tok); @@ -2610,7 +2603,7 @@ extern fn parse(P *Parser) [#]Decl { let decls *Vec = arg; decls->push(*decl); } - parsedecls(P, &yield, &decls, #{toplevel} #t); + parsedecls(P, P.tokloc, &yield, &decls, #{toplevel} #t); if lexmatch(P, #null, :eof) { break; } -- cgit v1.2.3