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;
}