# HG changeset patch # User Anders Halager # Date 1208684854 -7200 # Node ID 41d23f2762c319da33da7fe66003d432d24f6223 # Parent 69464d4652848d7096eaacd1459f4f2f50da52ab Merge, and updated Error class Usage is something like: --- auto e = new Error("No conversion between %0 and %1); e.arg(t1).arg(t2); e.loc(exp.location); --- Multiple locations can be given, to do clang like errors in the future diff -r 69464d465284 -r 41d23f2762c3 gen/LLVMGen.d --- a/gen/LLVMGen.d Sun Apr 20 11:20:28 2008 +0200 +++ b/gen/LLVMGen.d Sun Apr 20 11:47:34 2008 +0200 @@ -10,6 +10,8 @@ ast.Stmt, ast.Exp; +import misc.Error; + import lexer.Token; import sema.SymbolTableBuilder, @@ -175,6 +177,12 @@ } } + struct PE + { + static char[] NoImplicitConversion = + "Can't find an implicit conversion between %1 and %2"; + } + void sextSmallerToLarger(ref Value left, ref Value right) { if (left.type != right.type) @@ -183,10 +191,9 @@ IntegerType l = cast(IntegerType) left.type; IntegerType r = cast(IntegerType) right.type; if (l is null || r is null) - throw new Exception( - "Can't find a valid convertion between " - "a " ~ left.type.toString ~ " and a " - ~ right.type.toString); + throw error(__LINE__, PE.NoImplicitConversion) + .arg(left.type.toString) + .arg(right.type.toString); if (l.numBits() < r.numBits()) left = b.buildSExt(left, r, ".cast"); @@ -393,8 +400,7 @@ Stdout(v.type).newline; Stdout(t.type).newline; if (v_t is null || i_t is null) - throw new Exception( - "Inappropriate assignment, types don't match"); + throw error(__LINE__, "Inappropriate assignment, types don't match"); if (v_t.numBits() < i_t.numBits()) v = b.buildSExt(v, t.type, ".cast"); @@ -404,6 +410,11 @@ return b.buildStore(v, t); } + Error error(uint line, char[] msg) + { + return new Error(msg); + } + private: // llvm stuff diff -r 69464d465284 -r 41d23f2762c3 lexer/Lexer.d --- a/lexer/Lexer.d Sun Apr 20 11:20:28 2008 +0200 +++ b/lexer/Lexer.d Sun Apr 20 11:47:34 2008 +0200 @@ -127,8 +127,7 @@ if(source.data[position-1] == '/') return this.next; } - throw new Error("Unexpected end of file. Unclosed comment block", - Location(position, source)); + throw error(__LINE__, "Unexpected end of file. Unclosed comment block"); case '+': position += 2; @@ -153,8 +152,7 @@ if(nesting == 0) return this.next; } - throw new Error("Unexpected end of file. Unclosed comment block", - Location(position, source)); + throw error(__LINE__, "Unexpected end of file. Unclosed comment block"); default: return Token(Tok.Div, Location(position - 1, this.source), 1); @@ -227,11 +225,16 @@ return CharType.Symbol; default: - throw new Error("Read invalid symbol: '" ~ current ~ "'", Location(position, source)); + throw error(__LINE__, "Read invalid symbol: '%0'").arg(current); } } + Error error(uint line, char[] msg) + { + return (new Error(msg)).loc(Location(position, source)); + } + DataSource source; int position; Error[] errors; diff -r 69464d465284 -r 41d23f2762c3 misc/Error.d --- a/misc/Error.d Sun Apr 20 11:20:28 2008 +0200 +++ b/misc/Error.d Sun Apr 20 11:47:34 2008 +0200 @@ -1,18 +1,63 @@ module misc.Error; -import misc.Location; +import tango.core.Exception, + tango.text.Util : layout; -import tango.core.Exception; +import llvm.type; + +import misc.Location, + sema.Symbol; class Error : Exception { - char[] message; - Location errorLocation; + + this(char[] message) + { + super(message); + args ~= message; + } - this(char[] message, Location errorLocation) + char[] toString() + { + char[256] tmp = void; + char[] msg = layout(tmp, args); + if (locs.length > 0) + msg = locs[0].toString ~ ": " ~ msg; + else + msg = msg.dup; + return msg; + } + + Error arg(char[] s) { - super(errorLocation.toString ~ " " ~ message); - this.message = message; - this.errorLocation = errorLocation; + if (args.length == 11) + throw new Exception("Sorry, errors only support up to 10 args"); + args ~= s; + return this; + } + + Error arg(char c) + { + return arg([c]); + } + + Error arg(DType type) + { + return arg(type.name()); } + + Error arg(Symbol sym) + { + return arg(sym.type.name ~ " " ~ sym.id.get); + } + + Error loc(Location loc) + { + locs ~= loc; + return this; + } + +private: + char[][] args; + Location[] locs; } diff -r 69464d465284 -r 41d23f2762c3 misc/Location.d --- a/misc/Location.d Sun Apr 20 11:20:28 2008 +0200 +++ b/misc/Location.d Sun Apr 20 11:47:34 2008 +0200 @@ -2,7 +2,7 @@ import misc.DataSource; -import Integer = tango.text.convert.Integer, +import tango.text.convert.Integer, tango.text.Util; struct Location @@ -12,8 +12,16 @@ char[] toString () { - int lineNumber = split(source.get(0, position), "\n").length; - return source.name ~ ":" ~ Integer.toString(lineNumber); + int lineNumber = 0; + char[] end_line; + foreach (line; lines(source.get(0, position))) + { + ++lineNumber; + end_line = line; + } + return source.name + ~ "(" ~ .toString(lineNumber) + ~ ":" ~ .toString(end_line.length) ~ ")"; } char[] get(uint length) diff -r 69464d465284 -r 41d23f2762c3 parser/Parser.d --- a/parser/Parser.d Sun Apr 20 11:20:28 2008 +0200 +++ b/parser/Parser.d Sun Apr 20 11:47:34 2008 +0200 @@ -70,12 +70,12 @@ return new VarDecl(type, identifier, exp); default: char[] c = t.getType; - error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__)); + error(__LINE__, "Unexpexted token %0").arg(c); } break; default: char[] c = t.getType; - error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__)); + error(__LINE__, "Unexpexted token %0", &iden).arg(c); } break; case Tok.Struct: @@ -87,14 +87,13 @@ Identifier identifier = new Identifier(iden); return new StructDecl (identifier, parseStruct()); default: - throw new Error("Expected struct identifier, but got "~iden.getType, - iden.location); + throw error(__LINE__, "Expected struct identifier, but got %0").arg(iden.getType); } case Tok.EOF: return null; default: char[] c = t.getType; - error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__)); + throw error(__LINE__, "Unexpexted token %0", &t).arg(c); } } @@ -292,7 +291,9 @@ return new Identifier(identifier); break; default: - throw new Error("Unexpexted token in Identifier parsing. Got "~identifier.getType, identifier.location); + throw error(__LINE__, "Unexpexted token in Identifier parsing. Got %0") + .arg(identifier.getType) + .loc(identifier.location); } } @@ -313,7 +314,7 @@ break; default: char[] c = type.getType; - error("Unexpexted token in Type parsing. Got "~c); + error(__LINE__, "Unexpexted token in Type parsing. Got %0").arg(c); } } @@ -464,13 +465,23 @@ void require(Tok t) { if (lexer.peek().type != t) - error("Unexpexted token: Got '"~lexer.peek.getType~"' Expected '"~typeToString[t]~"'"); + error(__LINE__, "Unexpexted token: Got '%0' Expected '%1'") + .arg(lexer.peek.getType) + .arg(typeToString[t]); lexer.next(); } - void error(char[] errMsg) + Error error(uint line, char[] errMsg, Token* tok = null) { - throw new Exception("Parser error: " ~errMsg); + Location loc; + if (tok is null) + loc = lexer.peek.location; + else + loc = tok.location; + return + (new Error + ("Parser.d(" ~ Integer.toString(line) ~ "): " ~errMsg)) + .loc(loc); } Lexer lexer; diff -r 69464d465284 -r 41d23f2762c3 sema/Declarations.d --- a/sema/Declarations.d Sun Apr 20 11:20:28 2008 +0200 +++ b/sema/Declarations.d Sun Apr 20 11:47:34 2008 +0200 @@ -11,19 +11,27 @@ { int[char[]] types; + private Error error(uint line, char[] msg) + { + return new Error(msg); + } + override void visitIdentifier(Identifier i) { auto symbol = i.env.find(i); if(symbol is null) - throw new Error("Undefined identifier: '"~i.get~"'",i.token.location); - + throw error(__LINE__, "Undefined identifier: '%0'") + .arg(i.get) + .loc(i.token.location); } override void visitVarDecl(VarDecl d) { if(!d.env.findType(d.type)) - throw new Error("Undefined type: '"~d.type.get~"'",d.type.token.location); + throw error(__LINE__, "Undefined type: '%0'") + .arg(d.type.get) + .loc(d.type.token.location); visitExp(d.identifier); if (d.init)