Mercurial > projects > dang
view sema/DType.d @ 179:2a1a635bd531
Changes the way messages can be displayed. Also added a toString to DType's for type printing.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Fri, 25 Jul 2008 01:21:07 +0200 |
parents | dc9bf56b7ace |
children | 59cd211a1bd3 |
line wrap: on
line source
module sema.DType; import lexer.Token, ast.Exp; public import sema.Operation; /// 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 DClass bool isClass() { return false; } /// Return a DClass if this is one, otherwise return null DClass asClass() { return null; } /// Is this type a DInterface bool isInterface() { return false; } /// Return a DInterface if this is one, otherwise return null DInterface asInterface() { return null; } /// Is this type a DStaticArray bool isStaticArray() { return false; } /// Return a DStaticArray if this is one, otherwise return null DStaticArray asStaticArray() { 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; } /// Returns true for integers, reals and complex numbers bool isArithmetic() { return false; } /// Is this type a DInteger bool isInteger() { return false; } /// Return a DInteger if this is one, otherwise return null DInteger asInteger() { return null; } /// Is this type a DReal bool isReal() { return false; } /// Return a DReal if this is one, otherwise return null DReal asReal() { 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[] toString() { return id; } 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 an Operation describing how to use the supplied operator on the two types given. */ Operation getOperationWith(Operator op, DType other) { Operation res; return res; } /** 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; /** Mangle the DType following the specs at http://digitalmars.com/d/1.0/abi.html **/ char[] mangle() { /// expects to be void return "v"; } /** Get a type representing a static array of this type with length 'size' */ DStaticArray getAsStaticArray(int size) { if(size in myStaticArray) return myStaticArray[size]; myStaticArray[size] = new DStaticArray(this, size); return myStaticArray[size]; } private DStaticArray[int] myStaticArray; DArray getAsArray() { if(myArray !is null) return myArray; myArray = new DArray(this); return myArray; } private DArray myArray; bool isSame(DType d) { return d is this; } static DInteger Bool, Byte, UByte, Short, UShort, Int, UInt, Long, ULong, Char, WChar, DChar; static DReal Float, Double, Real; // Ignore - we dont support complex numbers yet static DReal CFloat, CDouble, CReal; static DType Void; static this() { Void = new DType("void"); Bool = new DInteger("bool", 1, true); 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); Float = new DReal("float", 32); Double = new DReal("double", 64); Real = new DReal("real", 80); Char = new DInteger("char", 8, true); WChar = new DInteger("wchar", 16, true); DChar = new DInteger("dchar", 32, true); } } /** Class to represent the built-in numerical types, from byte to long, reals and complex numbers. Should not actually use this, but DInteger, DReal or DComplex. */ class DArithmetic : DType { private static char[][DArithmetic] mangle_types; static this() { mangle_types = [ cast(DArithmetic) Bool : "b", Byte : "g", UByte : "h", Short : "s", UShort : "t", Int : "i", UInt : "k", Long : "l", ULong : "m", Float : "f", Double : "d", Real : "e", /* CFloat : "q", CDouble : "r", CReal : "c", */ Char : "a", WChar : "u", DChar : "w" ]; } this(char[] name, int bits, bool unsigned) { super(name, null); this.bits = bits; this.unsigned = unsigned; } override int byteSize() { return bits / 8; } bool isArithmetic() { return true; } override Operation getOperationWith(Operator op, DType that) { Operation operation; if (this is that) operation = Operation.builtin(op, unsigned, isReal()); return operation; } override char[] mangle() { return mangle_types[this]; } int bits; bool unsigned; } class DInteger : DArithmetic { this(char[] name, int bits, bool unsigned) { super(name, bits, unsigned); } override bool hasImplicitConversionTo(DType that) { if (that.isInteger() || that.isReal()) return true; return false; } override bool isInteger() { return true; } override DInteger asInteger() { return this; } } class DReal : DArithmetic { this(char[] name, int bits) { super(name, bits, false); } override bool hasImplicitConversionTo(DType that) { if (that.isInteger() || that.isReal()) return true; return false; } override bool isReal() { return true; } override DReal asReal() { return this; } } 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; override char[] mangle() { return "S"~Integer.toString(name.length)~name; } override bool isSame(DType d) { if (d is this) return true; if (!d.isStruct) return false; auto s = d.asStruct; return id == s.id; } struct DStructMember { DType type; int index; char[] toString() { return type.toString(); } } } class DClass : DType { this(Identifier id, DType actual = null) { super(id, actual); } int byteSize() { return bytes_total; } override bool isClass() { return true; } override DClass asClass() { return this; } void addMember(DType type, char[] name) { auto s = DClassMember(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; } DClassMember[char[]] members; private int bytes_total; override char[] mangle() { return "S"~Integer.toString(name.length)~name; } override bool isSame(DType d) { if (d is this) return true; if (!d.isClass) return false; auto c = d.asClass; return id == c.id; } struct DClassMember { DType type; int index; char[] toString() { return type.toString(); } } } class DInterface : DType { this(Identifier id, DType actual = null) { super(id, actual); } int byteSize() { return bytes_total; } override bool isInterface() { return true; } override DInterface asInterface() { return this; } void addMember(DType type, char[] name) { auto s = DInterfaceMember(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; } override bool isSame(DType d) { if (d is this) return true; if (!d.isInterface) return false; auto i = d.asInterface; return id == i.id; } DInterfaceMember[char[]] members; private int bytes_total; override char[] mangle() { return "S"~Integer.toString(name.length)~name; } struct DInterfaceMember { DType type; int index; char[] toString() { return type.toString(); } } } class DStaticArray : DType { this(DType arrayOf, int size, DType actual = null) { super(arrayOf.id ~ "[" ~ Integer.toString(size) ~ "]", actual); this.arrayOf = arrayOf; this.size = size; } override bool isStaticArray() { return true; } override DStaticArray asStaticArray() { return this; } int byteSize() { return arrayOf.byteSize * size; } override bool isSame(DType d) { if (d is this) return true; if (!d.isArray) return false; auto a = d.asStaticArray; if (size != a.size) return false; return arrayOf.isSame(a.arrayOf); } char[] toString() { return arrayOf.toString~"["~Integer.toString(size)~"]"; } override char[] mangle() { return "G"~Integer.toString(size)~arrayOf.mangle; } DType arrayOf; const int size; } class DArray : DType { this(DType arrayOf, DType actual = null) { super(id, actual); this.arrayOf = arrayOf; } override bool isArray() { return true; } override DArray asArray() { return this; } int byteSize() { return 8; } // FIXME: Size is a pointer + on size. (platform depend) override bool isSame(DType d) { if (d is this) return true; if (!d.isArray) return false; auto a = d.asArray; return arrayOf.isSame(a.arrayOf); } override char[] mangle() { return "G"~arrayOf.mangle; // FIXME: Need correct mangling } DType arrayOf; } 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; } override bool isSame(DType d) { if (d is this) return true; if (!d.isPointer) return false; auto p = d.asPointer; return pointerOf.isSame(p.pointerOf); } char[] toString() { if (!pointerOf.isFunction) return pointerOf.toString~"*"; auto f = pointerOf.asFunction; char[] res = f.returnType.toString~" function("; foreach (i, p ; f.params) res ~= i ? ", "~p.toString : p.toString; return res ~ ")"; } override char[] mangle() { return "P"~pointerOf.mangle; } DType pointerOf; } class DFunction : DType { this(Identifier id, DType actual = null) { super(id, actual); } override bool isFunction() { return true; } override DFunction asFunction() { return this; } override bool hasImplicitConversionTo(DType that) { return returnType.hasImplicitConversionTo(that); } override char[] mangle() { char[] res; res ~= "F"; foreach(param ; params) res ~= param.mangle; res ~= "Z"; res ~= returnType.mangle; return res; } char[] toString() { char[] res = returnType.toString~" ("; foreach (i, p ; params) res ~= i ? ", "~p.toString : p.toString; return res ~ ")"; } override bool isSame(DType f) { if (f is this) return true; if (!f.isFunction) return false; auto func = f.asFunction; if (returnType != func.returnType) return false; if (params.length != func.params.length) return false; foreach (i, p ; params) if (!p.isSame(func.params[0])) return false; return true; } DType[] params; DType returnType; bool firstParamIsReturnValue = false; }