aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff95
1 files changed, 52 insertions, 43 deletions
diff --git a/src/parse.cff b/src/parse.cff
index 3be70cf..aad88d1 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -584,9 +584,9 @@ fn lexexpects(P *Parser, t TokT, what *const u8) Tok {
let tok = Tok {};
if !lexmatch(P, &tok, t) {
if what {
- fatal(P, tok.loc, "expected %s (near %qT)", what, tok);
+ fatal(P, tok.loc, "expected %s (near %qT)", what, &tok);
} else {
- fatal(P, tok.loc, "expected %qk (near %qT)", t, tok);
+ fatal(P, tok.loc, "expected %qk (near %qT)", t, &tok);
}
}
return tok;
@@ -626,7 +626,7 @@ fn putdecl(P *Parser, eloc Loc, decl Decl) *Decl {
let d0 *const Decl;
let d = envput(P.curenv, decl, &d0);
if d == #null {
- fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, d0.loc);
+ fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, &d0.loc);
}
return d;
}
@@ -638,7 +638,7 @@ fn putdecl_alloc(P *Parser, alloc *Allocator, eloc Loc, decl Decl) *Decl {
let d0 *const Decl;
let d = envput_alloc(P.curenv, alloc, decl, &d0);
if d == #null {
- fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, d0.loc);
+ fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, &d0.loc);
}
return d;
}
@@ -1160,7 +1160,7 @@ fn parsetype(P *Parser) *const Type {
return parsebitfield(P, #{name} #null);
case else;
- fatal(P, tok.loc, "expected type (near %qT)", tok);
+ fatal(P, tok.loc, "expected type (near %qT)", &tok);
}
}
@@ -1185,7 +1185,7 @@ fn parseaggini(P *Parser, loc Loc, ty *const Type) Expr {
fld = findaggfield(ty, (tok = lexexpects(P, :ident, "field name")).u.ident);
lexexpect(P, ':');
if fld == #null {
- fatal(P, tok.loc, "%t has no such field %qT", ty, tok);
+ fatal(P, tok.loc, "%t has no such field %qT", ty, &tok);
}
iota = (fld - ty.u.Agg.flds.#ptr) + 1;
} else {
@@ -1384,7 +1384,7 @@ fn pexprimary(P *Parser) Expr {
fn resolvedecl(P *Parser, tok Tok, decl *Decl, ex *Expr) void {
let fakedecl Decl #?;
if decl == #null {
- fatal(P, tok.loc, "%qT is not defined", tok);
+ fatal(P, tok.loc, "%qT is not defined", &tok);
}
while #t {
switch decl.u {
@@ -1409,7 +1409,7 @@ fn pexprimary(P *Parser) Expr {
let name = (tok = lexexpect(P, :ident)).u.ident;
decl = envfind_noparent(ty.u.Agg.decls, name);
if decl == #null {
- fatal(P, tok.loc, "%t has no such decl %qT", ty, tok);
+ fatal(P, tok.loc, "%t has no such decl %qT", ty, &tok);
}
continue;
} else if !ty->is(:Agg) and !ty->is(:Enum) {
@@ -1502,7 +1502,7 @@ fn pexprimary(P *Parser) Expr {
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);
+ fatal(P, tok.loc, "%t has no such field %qT", ty, &tok);
}
off += fld.off;
ty = fld.ty;
@@ -1545,27 +1545,27 @@ fn pexprimary(P *Parser) Expr {
break #'search;
}
}
- fatal(P, tok.loc, "%t has no such variant %qT", ty, tok);
+ fatal(P, tok.loc, "%t has no such variant %qT", ty, &tok);
} while #f;
ex = { tok.loc, ty, :EnumIni(i) };
} else if ty->is(:Agg) and ty.u.Agg.kind == :EUnion {
let name = (tok = lexexpects(P, :ident, "variant name")).u.ident;
let fld = findaggfield(ty, name);
if fld == #null {
- fatal(P, tok.loc, "%t has no such variant %qT", ty, tok);
+ fatal(P, tok.loc, "%t has no such variant %qT", ty, &tok);
}
let iex *Expr = #null;
if lexpeek(P).t == '(' or lexpeek(P).t == '{' {
P.targty = fld.ty;
iex = exprdup(P.alloc, parseexpr(P));
if fld.ty == #null {
- fatal(P, iex.loc, "%t variant %qT is empty", ty, tok);
+ fatal(P, iex.loc, "%t variant %qT is empty", ty, &tok);
}
if !typematchestarg(fld.ty, iex.ty) {
fatal(P, iex.loc, "bad enum union initializer (%t, expected %t)", iex.ty, fld.ty);
}
} else if fld.ty {
- fatal(P, tok.loc, "%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 {
@@ -1590,7 +1590,7 @@ fn pexprimary(P *Parser) Expr {
}
}
case else;
- fatal(P, tok.loc, "expected expression (near %qT)", tok);
+ fatal(P, tok.loc, "expected expression (near %qT)", &tok);
}
P.targty = #null;
return ex;
@@ -1614,10 +1614,13 @@ fn pexpostfix(P *Parser) Expr {
while !lexmatch(P, #null, ')') {
P.targty = args.len + 1 <= params.#len ? *param : #null;
let ex = parseexpr(P);
- args->push(ex);
if args.len > params.#len and !Fn.variadic {
fatal(P, ex.loc, "too many args (%z, expected %z)", args.len, params.#len);
}
+ if args.len >= params.#len and (ex.ty->is(:Agg) or ex.ty->is(:Slice) or ex.ty->is(:VaList)) {
+ err(P, ex.loc, "cannot pass aggregate value as variadic argument");
+ }
+ args->push(ex);
if args.len <= params.#len and !typematchestarg(*param, ex.ty) {
err(P, ex.loc, "function call argument type mismatch (%t, expected %t)",
ex.ty, *param);
@@ -1663,13 +1666,13 @@ fn pexpostfix(P *Parser) Expr {
}
case lexmatch(P, &tok, '++') or lexmatch(P, &tok, '--');
if !isnumtype(ex.ty) and !ex.ty->is(:Ptr) {
- fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty);
+ fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty);
}
if !islvalue(&ex) {
- err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", tok);
+ err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", &tok);
}
if ex.ty.konst {
- err(P, ex.loc, "left operand to prefix %qT operator is const", tok);
+ err(P, ex.loc, "left operand to prefix %qT operator is const", &tok);
}
ex = {
tok.loc, ex.ty, .u: :UnOp {
@@ -1694,8 +1697,8 @@ fn pexpostfix(P *Parser) Expr {
break;
}
}
- if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, tok); }
- if fld.ty == #null { fatal(P, tok.loc, "field %qT has no type", tok); }
+ if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); }
+ if fld.ty == #null { fatal(P, tok.loc, "field %qT has no type", &tok); }
ex = { tok.loc, konst ? constify(fld.ty) : fld.ty, :Dot { exprdup(P.alloc, ex), fld }};
case BitF *bitf;
let fld *BitFField = #null;
@@ -1705,7 +1708,7 @@ fn pexpostfix(P *Parser) Expr {
break;
}
}
- if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, tok); }
+ if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); }
ex = { tok.loc, konst ? constify(fld.ty) : fld.ty, :BitDot { exprdup(P.alloc, ex), fld }};
case else
fatal(P, tok.loc, "left-hand-side is not an aggregate (%t)", ty);
@@ -1774,7 +1777,7 @@ fn pexpostfix(P *Parser) Expr {
case Agg *agg;
let decl *Decl = agg.decls ? envfind_noparent(agg.decls, name) : #null;
if decl == #null {
- fatal(P, tok.loc, "%t has no such method %qT", ty, tok);
+ fatal(P, tok.loc, "%t has no such method %qT", ty, &tok);
}
lexexpect(P, '(');
switch decl.u {
@@ -1859,6 +1862,9 @@ fn pexpostfix(P *Parser) Expr {
let type = parsetype(P);
lexmatch(P, #null, ',');
lexexpect(P, ')');
+ if type->is(:Agg) {
+ err(P, tok.loc, "unsupported use of variadic arg of aggregate type");
+ }
ex = { tok.loc, type, :VaArg(exprdup(P.alloc, ex)) };
case streq(name, "end");
@@ -1889,10 +1895,10 @@ fn pexprefix(P *Parser) Expr {
let ex = pexprefix(P);
let ty = typeof2(ex.ty, ty_int);
if ty == #null {
- fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty);
+ fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty);
}
if !ty->is(:Int) and tok.t == '~' {
- fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty);
+ fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty);
}
return {
tok.loc, ty, .u: :UnOp {
@@ -1902,13 +1908,13 @@ fn pexprefix(P *Parser) Expr {
case lexmatch(P, &tok, '++') or lexmatch(P, &tok, '--');
let ex = pexprefix(P);
if !isnumtype(ex.ty) and !ex.ty->is(:Ptr) {
- fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty);
+ fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty);
}
if !islvalue(&ex) {
- err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", tok);
+ err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", &tok);
}
if ex.ty.konst {
- err(P, ex.loc, "left operand to prefix %qT operator is const", tok);
+ err(P, ex.loc, "left operand to prefix %qT operator is const", &tok);
}
return {
tok.loc, ex.ty, .u: :UnOp {
@@ -1918,7 +1924,7 @@ fn pexprefix(P *Parser) Expr {
case lexmatch(P, &tok, '!');
let ex = pexprefix(P);
if !ex.ty->is(:Bool) {
- err(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty);
+ err(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty);
}
return { tok.loc, ty_bool, .u: :UnOp { :not, exprdup(P.alloc, ex) }};
@@ -2043,13 +2049,13 @@ fn pexcmp(P *Parser) Expr {
P.targty = #null;
if typeof2(ex.ty, rhs.ty) == #null {
fatal(P, tok.loc, "incompatible operands %t and %t to binary operator %qT",
- ex.ty, rhs.ty, tok);
+ ex.ty, rhs.ty, &tok);
}
let ty = typeof2(ex.ty, rhs.ty);
if tok.t != '==' and tok.t != '!=' {
if !isnumtype(ty) and !ty->is(:Ptr) {
fatal(P, tok.loc, "invalid non-numeric operands %t and %t to relational operator %qT",
- ex.ty, rhs.ty, tok);
+ ex.ty, rhs.ty, &tok);
}
fn ispositiveintlit(ex Expr) bool {
return ex.u.#tag == :IntLit and ex.u.IntLit.i >- 0;
@@ -2167,14 +2173,14 @@ fn pexassign(P *Parser) Expr {
and !((ex.ty->is(:Ptr) and rhs.ty->is(:Int)
and (tok.t == '+=' or tok.t == '-=')));
err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT",
- ex.ty, rhs.ty, tok);
+ ex.ty, rhs.ty, &tok);
case okind == :IntFlo and (!isnumtype(ex.ty) or !isnumtype(rhs.ty));
err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT",
- ex.ty, rhs.ty, tok);
+ ex.ty, rhs.ty, &tok);
case okind == :Int and (!ex.ty->is(:Int) or !rhs.ty->is(:Int));
err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT",
- ex.ty, rhs.ty, tok);
+ ex.ty, rhs.ty, &tok);
case ex.ty.konst;
err(P, ex.loc, "left operand to assignment is const");
}
@@ -2380,7 +2386,7 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt {
err(P, e.loc, "bad case expression (%t, expected %t)", e.ty, ex.ty);
}
if seen->get(e.u.IntLit.i) {
- err(P, e.loc, "duplicate case expression (previously seen at %l)", *seen->get(e.u.IntLit.i));
+ err(P, e.loc, "duplicate case expression (previously seen at %l)", seen->get(e.u.IntLit.i));
}
seen->put(e.u.IntLit.i, e.loc);
es->push(e);
@@ -2421,12 +2427,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt {
let vname = (tok = lexexpect(P, :ident)).u.ident;
c.fld = findaggfield(test.ty, vname);
if c.fld == #null {
- fatal(P, tok.loc, "%t has no such variant %qT", test.ty, tok);
+ fatal(P, tok.loc, "%t has no such variant %qT", test.ty, &tok);
}
c.variant = c.fld - test.ty.u.Agg.flds.#ptr;
if seen->get(c.variant) {
- err(P, tok.loc, "duplicate case expression (previously seen at %l)", *seen->get(c.variant));
+ err(P, tok.loc, "duplicate case expression (previously seen at %l)", seen->get(c.variant));
}
seen->put(c.variant, tok.loc);
@@ -2558,7 +2564,7 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void {
if lexmatch(P, &tok2, :label) {
let decl = finddecl(P, tok2.u.ident);
if decl == #null {
- fatal(P, tok2.loc, "no such label %qT", tok2);
+ fatal(P, tok2.loc, "no such label %qT", &tok2);
}
assert(decl.u.#tag == :Label, "label?");
loop = decl.u.Label;
@@ -2700,7 +2706,7 @@ fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, yield DeclYie
}
let decll *Decl #?;
yield(decll = putdecl(P, tok.loc, decl), yarg);
- if !letp and !fwd {
+ if !letp and !fwd and !P.error {
llvm_genstatic(decl.externp, decl.name, &decl.u.Static);
}
@@ -2765,7 +2771,9 @@ fn parsefn(P *Parser, loc Loc, toplevel bool, externp bool, name *const u8) *Dec
P.curblock = block;
popenv(P);
// ir_genfn(P.irctx, Fn);
- llvm_genfn(externp, name, Fn);
+ if !P.error {
+ llvm_genfn(externp, name, Fn);
+ }
(as(*Arena)P.alloc.a)->destroy();
}
}
@@ -2994,7 +3002,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool)
if streq(a, "lax") {
attr |= ATTR_LAX;
} else {
- err(P, tok.loc, "unknown attribute %qT", tok);
+ err(P, tok.loc, "unknown attribute %qT", &tok);
}
}
}
@@ -3145,7 +3153,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool)
return parsedecls(P, tok.loc, yield, yarg, toplevel);
}
}
- fatal(P, tok.loc, "expected declaration (near %qT)", tok);
+ fatal(P, tok.loc, "expected declaration (near %qT)", &tok);
}
if yield != #null and decl != #null {
@@ -3176,7 +3184,6 @@ extern fn parse(P *Parser) [#]Decl {
let alloc = Allocator { &aralloc, &Arena:allocf, #null };
let decls Vec<Decl> = {};
P.alloc = (P.tlalloc = &alloc);
- P.irctx = mkirctx(P.alloc);
P.curenv = mkenv(#null, P.alloc);
if primenv == #null {
primenv = mkenv(#null, P.alloc);
@@ -3194,7 +3201,9 @@ extern fn parse(P *Parser) [#]Decl {
}
}
- llvm_fini();
+ if !P.error {
+ llvm_fini();
+ }
envfree(P.curenv);
aralloc->destroy();
return decls.dat[0::decls.len];