Mercurial > projects > dang
view src/basic/Message.d @ 209:42e663451371
Renamed some of the actions. Declarations now have it's own action.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Tue, 12 Aug 2008 19:05:17 +0200 |
parents | e0551773a005 |
children | 9e9f3e7e342b |
line wrap: on
line source
module basic.Message; import tango.core.Exception, Array = tango.core.Array, tango.io.Stdout, tango.text.Util; import tango.stdc.stdlib; import llvm.type; import lexer.Token, lexer.Lexer; import basic.SourceLocation, basic.SourceManager; public import basic.Messages; enum ExitLevel { Normal = 1, Lexer = 2, Parser = 3, Semantic = 3, } class MessageHandler { public: this(SourceManager src_mgr) { this.src_mgr = src_mgr; } Message report(uint opcode, SLoc location) { Message m = new Message(opcode, location, src_mgr, this); messages ~= m; return m; } Message report(uint opcode, SourceRange[] ranges, SourceLocation[] locs) { Message m = new Message(opcode, ranges, locs, src_mgr, this); messages ~= m; return m; } Message report(uint opcode, SLoc location1, SLoc location2, SLoc location3 = SLoc.Invalid) { Message m = new Message(opcode, [SourceRange(location1, location2)][], [location3][], src_mgr, this); messages ~= m; return m; } void checkErrors(ExitLevel exitlevel = ExitLevel.Normal) { if(messages.length == 0) return; if(warnings) checkWarnings; foreach(m ; messages) if(m.type == MessageType.Error) { Stdout(m).newline; } exit(exitlevel); } void checkWarnings() { foreach(m ; messages) if(m.type == MessageType.Warning) { Stdout(m).newline; } } void showWarnings(bool value) { warnings = value; } private: Message[] messages; SourceManager src_mgr; bool warnings; } class Message { this(int opcode, SLoc location, SourceManager src_mgr, MessageHandler msg_handler) { this.src_mgr = src_mgr; this.interests ~= location; args ~= Messages[opcode].message; this.type = Messages[opcode].type; this.msg_handler = msg_handler; } this(int opcode, SourceRange[] locs, SLoc[] interests, SourceManager src_mgr, MessageHandler msg_handler) in { assert(locs.length + interests.length, "Atleast one location is requiret for a mark"); } body { this.src_mgr = src_mgr; this.locs = locs; this.interests = interests; args ~= Messages[opcode].message; this.type = Messages[opcode].type; this.msg_handler = msg_handler; haveEnd = true; } char[] toString() { char[256] tmp = void; char[] msg = layout(tmp, args); SLoc location; if (interests.length) location = interests[0]; else location = locs[0].begin; int len = 0; if(!haveEnd) { Lexer l = new Lexer(interests[0], src_mgr, new MessageHandler(src_mgr)); Token t = l.next; len = t.length; } // else // len = end - location; if (src_mgr.getRawData(location).length > 0) msg = src_mgr.getLocationAsString(location) ~ ": " ~ msg; else msg = msg.dup; char[] line = src_mgr.getLine(location); char[] marks = line.dup; marks[] = ' '; foreach (s ; locs) { size_t p = src_mgr.getColumn(s.begin); marks[p .. p + (s.end-s.begin)] = interests.length ? '~' : '^'; } foreach (interest ; interests) { size_t i = src_mgr.getColumn(interest); marks[i] = '^'; } msg ~= "\n "; msg ~= line; msg ~= "\n "; msg ~= marks; return msg; } Message arg(char[] s) { if (args.length > 10) throw new Exception("Sorry, errors only support up to 10 args"); args ~= s; return this; } Message arg(char[][] s) { char[] res = s[0 .. $ - 1].join(", "); if (s.length > 1) res ~= " and "; res ~= s[$ - 1]; return arg(res); } Message arg(char c) { return arg([c]); } Message fatal(ExitLevel exitlevel = ExitLevel.Normal) { msg_handler.checkErrors(exitlevel); return this; } /* Message loc(SLoc loc) { location = loc; return this; } */ MessageType type; private: char[][] args; SourceRange[] locs; SLoc[] interests; bool haveEnd; SourceManager src_mgr; MessageHandler msg_handler; Token t; }