aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-19 11:05:06 +0200
committerlemon <lsof@mailbox.org>2022-08-19 11:05:06 +0200
commit87ee8d01a7e8a19461d712c7acd3e2050ccf3ffc (patch)
treeb5dc6f879bcb9aeae810cae62ab13674edd7b9a5 /src
parente9543de5ab1de08a452de4b9df705c43aa9ff6ac (diff)
do not use P.tokloc directly
for it is not what is intended whilst a macro is being expanded
Diffstat (limited to 'src')
-rw-r--r--src/parse.cff119
1 files changed, 56 insertions, 63 deletions
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<Expr> = {};
@@ -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<u32> = {};
let exs Vec<Expr> = {};
@@ -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<Expr>:None;
+ let tok Tok #?;
if lexmatch(P, #null, :kw_let) {
let sts Vec<Stmt> = {};
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, &paramnames, &paramtys);
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<MacroCase> = {};
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<TeplParam> = {};
let toks Vec<Tok> = {};
@@ -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<Decl> = arg;
decls->push(*decl);
}
- parsedecls(P, &yield, &decls, #{toplevel} #t);
+ parsedecls(P, P.tokloc, &yield, &decls, #{toplevel} #t);
if lexmatch(P, #null, :eof) {
break;
}