view basic/Message.d @ 89:a49bb982a7b0 new_gen

Using the new SourceLocation system to handle errors. Also, this is the first push for making the errors don't throw, but continue to check the source.
author Anders Johnsen <skabet@gmail.com>
date Sun, 04 May 2008 20:27:01 +0200
parents misc/Error.d@eb5b2c719a39
children 771ac63898e2
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,
       sema.DType,
       sema.Symbol;

import basic.SourceLocation,
       basic.SourceManager;

public import basic.Messages;

class MessageHandler
{
public:

    this(SourceManager src_mgr)
    {
        this.src_mgr = src_mgr;
    }

    Message report(uint opcode, SLoc location, bool fatal = false)
    {
        Message m = new Message(opcode, location, src_mgr);
        messages ~= m;
        if(fatal)
            checkErrors();
        return m;
    }

    void checkErrors()
    {
        if(messages.length == 0)
            return;

        foreach(m ; messages)
            if(m.type == MessageType.Error)
            {
                Stdout(m).newline;
            }

        exit(1);
    }

    void checkWarnings()
    {
    }

    void showWarnings(bool value)
    {
        warnings = value;
    }

private:
    Message[] messages;
    SourceManager src_mgr;
    bool warnings;
}

class Message
{

    this(int opcode, SLoc location, SourceManager src_mgr)
    {
        this.src_mgr = src_mgr;
        this.location = location;
        args ~= Messages[opcode].message;
        this.type = Messages[opcode].type;
    }

    char[] toString()
    {
        char[256] tmp = void;
        char[] msg = layout(tmp, args);

        Lexer l = new Lexer(location, src_mgr, new MessageHandler(src_mgr));

        Token t = l.next;
        
        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[] = ' ';
        size_t p = src_mgr.getOffsetToLine(location);
        marks[p .. p + t.length] = '^';

        msg ~= "\n    ";
        msg ~= line;
        msg ~= "\n    ";
        msg ~= marks;

        return msg;
    }

    Message arg(char[] s)
    {
        if (args.length == 11)
            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 arg(DType[] types)
    {
        char[][] res;
        foreach (type; types)
            res ~= type.name();
        return arg(res);
    }

    Message arg(Symbol sym)
    {
        return arg(sym.type.name ~ " " ~ sym.id.get);
    }

    /*
    Message loc(SLoc loc)
    {
        location = loc;
        return this;
    }
    */

    MessageType type;
private:
    char[][] args;
    SLoc location;
    SourceManager src_mgr;
}