view basic/Message.d @ 100:5f258eaf9517 new_gen

Loading modules in. Just need to add them to the scope of the "main" Module now.
author Anders Johnsen <skabet@gmail.com>
date Tue, 06 May 2008 22:49:43 +0200
parents 621cedba53ea
children 89db676fbacb
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;

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

    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.location = location;
        args ~= Messages[opcode].message;
        this.type = Messages[opcode].type;
        this.msg_handler = msg_handler;
    }

    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.getColumn(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 fatal(ExitLevel exitlevel = ExitLevel.Normal)
    {
        msg_handler.checkErrors(exitlevel);
        return this;
    }

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

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