view sema/DType.d @ 88:eb5b2c719a39 new_gen

Major change to locations, tokens and expressions. A location (now SourceLocation or SLoc) is only 32 bit in size - disadvantage is that it can't find its own text. You have to go through the new SourceManager to do that. This has caused changes to a lot of stuff and removal of DataSource and the old Location Additionally Exp has gotten some location stuff, so we can give proper error messages. Not in Decl and Stmt yet, but thats coming too.
author Anders Halager <halager@gmail.com>
date Sun, 04 May 2008 18:13:46 +0200
parents 9e90694f5da0
children 438e6ed4cda1
line wrap: on
line source

module sema.DType;

import lexer.Token,
       ast.Exp;

import tango.io.Stdout;

class DType
{
    private char[] id;
    private SourceLocation loc;
    public DType actual;

    this(Identifier id, DType actual = null)
    {
        this.id = id.name;
        this.loc = id.startLoc();
        this.actual = actual is null? this : actual;
    }

    this(char[] id, DType actual = null)
    {
        this.id = id;
        this.actual = actual is null? this : actual;
    }

    /// Is this type a DStruct
    bool isStruct() { return false; }
    /// Return a DStruct if this is one, otherwise return null
    DStruct asStruct() { return null; }

    /// Is this type a DArray
    bool isArray() { return false; }
    /// Return a DArray if this is one, otherwise return null
    DArray asArray() { return null; }

    /// Is this type a DPointer
    bool isPointer() { return false; }
    /// Return a DPointer if this is one, otherwise return null
    DPointer asPointer() { return null; }

    /// Is this type a DFunction
    bool isFunction() { return false; }
    /// Return a DFunction if this is one, otherwise return null
    DFunction asFunction() { return null; }

    /// Is this type a DInteger
    bool isInteger() { return false; }
    /// Return a DInteger if this is one, otherwise return null
    DInteger asInteger() { return null; }

    int opEquals(Object o)
    {
        if (auto t = cast(DType)o)
            return this.actual is t.actual;
        return 0;
    }

    int opCmp(Object o)
    {
        if (auto t = cast(DType)o)
            return cast(void*)this.actual - cast(void*)t.actual;
        return 0;
    }

    /**
      Hashing is done by casting the reference to a void* and taking that
      value, but this gives a bad distribution of hash-values.

      Multiple DType's allocated close to each other will only have a
      difference in the lower bits of their hashes.
     */
    hash_t toHash()
    {
        return cast(hash_t)(cast(void*)this);
    }

    char[] name() { return id; }
    SourceLocation getLoc() { return loc; }
    int byteSize() { return 0; }

    /**
      Can this type legally be converted to that type with no casts?
      True for short -> int etc.
     */
    bool hasImplicitConversionTo(DType that) { return false; }

    /**
      Get a type representing a pointer to this type (from int to int*)
     */
    DPointer getPointerTo()
    {
        if(myPointer !is null)
            return myPointer;
        myPointer = new DPointer(this);
        return myPointer;
    }
    private DPointer myPointer;

    /**
      Get a type representing a static array of this type with length 'size'
     */
    DArray getAsArray(int size)
    {
        if(size in myArray)
            return myArray[size];
        myArray[size] = new DArray(this, size);
        return myArray[size];
    }
    private DArray[int] myArray;

    static DInteger
        Bool,
        Byte, UByte, Short, UShort,
        Int, UInt, Long, ULong;

    static DType Void;

    static this()
    {
        Void   = new DType("void");

        Bool   = new DInteger("bool",    1, false);
        Byte   = new DInteger("byte",    8, false);
        UByte  = new DInteger("ubyte",   8, true);
        Short  = new DInteger("short",  16, false);
        UShort = new DInteger("ushort", 16, true);
        Int    = new DInteger("int",    32, false);
        UInt   = new DInteger("uint",   32, true);
        Long   = new DInteger("long",   64, false);
        ULong  = new DInteger("ulong",  64, true);
    }
}

/**
  Class to represent the built-in integer types, from byte to long.
 */
class DInteger : DType
{
    this(char[] name, int bits, bool unsigned)
    {
        super(name, null);
        this.bits = bits;
        this.unsigned = unsigned;
    }

    override int byteSize() { return bits / 8; }

    override bool hasImplicitConversionTo(DType that)
    {
        if (auto o = cast(DInteger)that)
            return true;
//            return this.bits >= o.bits;
        return false;
    }

    override bool isInteger() { return true; }
    override DInteger asInteger() { return this; }

    int bits;
    bool unsigned;
}

class DStruct : DType
{
    this(Identifier id, DType actual = null)
    {
        super(id, actual);
    }

    int byteSize() { return bytes_total; }

    override bool isStruct() { return true; }
    override DStruct asStruct() { return this; }

    void addMember(DType type, char[] name)
    {
        auto s = DStructMember(type, members.length);
        members[name] = s;

        bytes_total += type.byteSize();
    }

    int indexOf(char[] name)
    {
        if(name in members)
            return members[name].index;

        return -1;
    }

    DType typeOf(char[] name)
    {
        if (auto res = name in members)
            return res.type;
        return null;
    }

    DStructMember[char[]] members;
    private int bytes_total;

    struct DStructMember
    {
        DType type;
        int index;
    }
}

class DArray : DType
{
    this(DType arrayOf, int size, DType actual = null)
    {
        super(id, actual);
        this.arrayOf = arrayOf;
        this.size = size;
    }

    override bool isArray() { return true; }
    override DArray asArray() { return this; }

    int byteSize() { return arrayOf.byteSize * size; }

    DType arrayOf;
    const int size;
}

class DPointer : DType
{
    this(DType pointerOf, DType actual = null)
    {
        super(id, actual);
        this.pointerOf = pointerOf;
    }

    override bool isPointer() { return true; }
    override DPointer asPointer() { return this; }

    int byteSize() { return DType.Int.byteSize; }

    DType pointerOf;
}

class DFunction : DType
{
    this(Identifier id, DType actual = null)
    {
        super(id, actual);
    }

    override bool isFunction() { return true; }
    override DFunction asFunction() { return this; }

    DType[] params;
    DType returnType;
    bool firstParamIsReturnValue = false;
}