Mercurial > projects > ddmd
diff dmd/TypeBasic.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | fd4acc376c45 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TypeBasic.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,779 @@ +module dmd.TypeBasic; + +import dmd.Type; +import dmd.Id; +import dmd.MOD; +import dmd.TOK; +import dmd.Token; +import dmd.TFLAGS; +import dmd.TY; +import dmd.Loc; +import dmd.Scope; +import dmd.Expression; +import dmd.IntegerExp; +import dmd.Identifier; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.CppMangleState; +import dmd.MATCH; +import dmd.RealExp; +import dmd.ComplexExp; +import dmd.Util; +import dmd.Port; +import dmd.Complex; + +class TypeBasic : Type +{ + string dstring; + uint flags; + + this(TY ty) + { + super(ty); + + enum TFLAGSintegral = 1; + enum TFLAGSfloating = 2; + enum TFLAGSunsigned = 4; + enum TFLAGSreal = 8; + enum TFLAGSimaginary = 0x10; + enum TFLAGScomplex = 0x20; + + string d; + + uint flags = 0; + switch (ty) + { + case TY.Tvoid: d = Token.toChars(TOK.TOKvoid); + break; + + case TY.Tint8: d = Token.toChars(TOK.TOKint8); + flags |= TFLAGSintegral; + break; + + case TY.Tuns8: d = Token.toChars(TOK.TOKuns8); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Tint16: d = Token.toChars(TOK.TOKint16); + flags |= TFLAGSintegral; + break; + + case TY.Tuns16: d = Token.toChars(TOK.TOKuns16); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Tint32: d = Token.toChars(TOK.TOKint32); + flags |= TFLAGSintegral; + break; + + case TY.Tuns32: d = Token.toChars(TOK.TOKuns32); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Tfloat32: d = Token.toChars(TOK.TOKfloat32); + flags |= TFLAGSfloating | TFLAGSreal; + break; + + case TY.Tint64: d = Token.toChars(TOK.TOKint64); + flags |= TFLAGSintegral; + break; + + case TY.Tuns64: d = Token.toChars(TOK.TOKuns64); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Tfloat64: d = Token.toChars(TOK.TOKfloat64); + flags |= TFLAGSfloating | TFLAGSreal; + break; + + case TY.Tfloat80: d = Token.toChars(TOK.TOKfloat80); + flags |= TFLAGSfloating | TFLAGSreal; + break; + + case TY.Timaginary32: d = Token.toChars(TOK.TOKimaginary32); + flags |= TFLAGSfloating | TFLAGSimaginary; + break; + + case TY.Timaginary64: d = Token.toChars(TOK.TOKimaginary64); + flags |= TFLAGSfloating | TFLAGSimaginary; + break; + + case TY.Timaginary80: d = Token.toChars(TOK.TOKimaginary80); + flags |= TFLAGSfloating | TFLAGSimaginary; + break; + + case TY.Tcomplex32: d = Token.toChars(TOK.TOKcomplex32); + flags |= TFLAGSfloating | TFLAGScomplex; + break; + + case TY.Tcomplex64: d = Token.toChars(TOK.TOKcomplex64); + flags |= TFLAGSfloating | TFLAGScomplex; + break; + + case TY.Tcomplex80: d = Token.toChars(TOK.TOKcomplex80); + flags |= TFLAGSfloating | TFLAGScomplex; + break; + + case TY.Tbool: d = "bool"; + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Tascii: d = Token.toChars(TOK.TOKchar); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Twchar: d = Token.toChars(TOK.TOKwchar); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + + case TY.Tdchar: d = Token.toChars(TOK.TOKdchar); + flags |= TFLAGSintegral | TFLAGSunsigned; + break; + } + + this.dstring = d; + this.flags = flags; + merge(); + } + +version (DumbClone) { +} else { + Type clone() + { + assert(false); + } +} + Type syntaxCopy() + { + // No semantic analysis done on basic types, no need to copy + return this; + } + + ulong size(Loc loc) + { + uint size; + + //printf("TypeBasic.size()\n"); + switch (ty) + { + case TY.Tint8: + case TY.Tuns8: size = 1; break; + case TY.Tint16: + case TY.Tuns16: size = 2; break; + case TY.Tint32: + case TY.Tuns32: + case TY.Tfloat32: + case TY.Timaginary32: + size = 4; break; + case TY.Tint64: + case TY.Tuns64: + case TY.Tfloat64: + case TY.Timaginary64: + size = 8; break; + case TY.Tfloat80: + case TY.Timaginary80: + size = REALSIZE; break; + case TY.Tcomplex32: + size = 8; break; + case TY.Tcomplex64: + size = 16; break; + case TY.Tcomplex80: + size = REALSIZE * 2; break; + + case TY.Tvoid: + //size = Type.size(); // error message + size = 1; + break; + + case TY.Tbool: size = 1; break; + case TY.Tascii: size = 1; break; + case TY.Twchar: size = 2; break; + case TY.Tdchar: size = 4; break; + + default: + assert(0); + break; + } + + //printf("TypeBasic.size() = %d\n", size); + return size; + } + + uint alignsize() + { + uint sz; + + switch (ty) + { + case TY.Tfloat80: + case TY.Timaginary80: + case TY.Tcomplex80: + sz = REALALIGNSIZE; + break; + +version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS + case TY.Tint64: + case TY.Tuns64: + case TY.Tfloat64: + case TY.Timaginary64: + case TY.Tcomplex32: + case TY.Tcomplex64: + sz = 4; + break; +} + + default: + sz = cast(uint)size(Loc(0)); /// + break; + } + + return sz; + } + + Expression getProperty(Loc loc, Identifier ident) + { + Expression e; + long ivalue; + real fvalue; + + //printf("TypeBasic.getProperty('%s')\n", ident.toChars()); + if (ident is Id.max) + { + switch (ty) + { + case TY.Tint8: ivalue = byte.max; goto Livalue; + case TY.Tuns8: ivalue = ubyte.max; goto Livalue; + case TY.Tint16: ivalue = short.max; goto Livalue; + case TY.Tuns16: ivalue = ushort.max; goto Livalue; + case TY.Tint32: ivalue = int.max; goto Livalue; + case TY.Tuns32: ivalue = uint.max; goto Livalue; + case TY.Tint64: ivalue = long.max; goto Livalue; + case TY.Tuns64: ivalue = ulong.max; goto Livalue; + case TY.Tbool: ivalue = bool.max; goto Livalue; + case TY.Tchar: ivalue = char.max; goto Livalue; + case TY.Twchar: ivalue = wchar.max; goto Livalue; + case TY.Tdchar: ivalue = 0x10FFFF; goto Livalue; + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: fvalue = float.max; goto Lfvalue; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: fvalue = double.max;goto Lfvalue; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: fvalue = real.max; goto Lfvalue; + } + } + else if (ident is Id.min) + { + switch (ty) + { + case TY.Tint8: ivalue = byte.min; goto Livalue; + case TY.Tuns8: ivalue = ubyte.min; goto Livalue; + case TY.Tint16: ivalue = short.min; goto Livalue; + case TY.Tuns16: ivalue = ushort.min; goto Livalue; + case TY.Tint32: ivalue = int.min; goto Livalue; + case TY.Tuns32: ivalue = uint.min; goto Livalue; + case TY.Tint64: ivalue = long.min; goto Livalue; + case TY.Tuns64: ivalue = ulong.min; goto Livalue; + case TY.Tbool: ivalue = bool.min; goto Livalue; + case TY.Tchar: ivalue = char.min; goto Livalue; + case TY.Twchar: ivalue = wchar.min; goto Livalue; + case TY.Tdchar: ivalue = dchar.min; goto Livalue; + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: fvalue = float.min; goto Lfvalue; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: fvalue = double.min; goto Lfvalue; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: fvalue = real.min; goto Lfvalue; + } + } + else if (ident is Id.nan) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Tcomplex64: + case TY.Tcomplex80: + case TY.Timaginary32: + case TY.Timaginary64: + case TY.Timaginary80: + case TY.Tfloat32: + case TY.Tfloat64: + case TY.Tfloat80: + { + fvalue = real.nan; + goto Lfvalue; + } + } + } + else if (ident is Id.infinity) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Tcomplex64: + case TY.Tcomplex80: + case TY.Timaginary32: + case TY.Timaginary64: + case TY.Timaginary80: + case TY.Tfloat32: + case TY.Tfloat64: + case TY.Tfloat80: + fvalue = real.infinity; + goto Lfvalue; + } + } + else if (ident is Id.dig) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: ivalue = float.dig; goto Lint; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: ivalue = double.dig; goto Lint; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: ivalue = real.dig; goto Lint; + } + } + else if (ident is Id.epsilon) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: fvalue = float.epsilon; goto Lfvalue; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: fvalue = double.epsilon; goto Lfvalue; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: fvalue = real.epsilon; goto Lfvalue; + } + } + else if (ident is Id.mant_dig) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: ivalue = float.mant_dig; goto Lint; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: ivalue = double.mant_dig; goto Lint; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: ivalue = real.mant_dig; goto Lint; + } + } + else if (ident is Id.max_10_exp) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: ivalue = float.max_10_exp; goto Lint; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: ivalue = double.max_10_exp; goto Lint; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: ivalue = real.max_10_exp; goto Lint; + } + } + else if (ident is Id.max_exp) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: ivalue = float.max_exp; goto Lint; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: ivalue = double.max_exp; goto Lint; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: ivalue = real.max_exp; goto Lint; + } + } + else if (ident is Id.min_10_exp) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: ivalue = float.min_10_exp; goto Lint; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: ivalue = double.min_10_exp; goto Lint; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: ivalue = real.min_10_exp; goto Lint; + } + } + else if (ident is Id.min_exp) + { + switch (ty) + { + case TY.Tcomplex32: + case TY.Timaginary32: + case TY.Tfloat32: ivalue = float.min_exp; goto Lint; + case TY.Tcomplex64: + case TY.Timaginary64: + case TY.Tfloat64: ivalue = double.min_exp; goto Lint; + case TY.Tcomplex80: + case TY.Timaginary80: + case TY.Tfloat80: ivalue = real.min_exp; goto Lint; + } + } + + Ldefault: + return Type.getProperty(loc, ident); + + Livalue: + e = new IntegerExp(loc, ivalue, this); + return e; + + Lfvalue: + if (isreal() || isimaginary()) + e = new RealExp(loc, fvalue, this); + else + { + Complex!(real) cvalue; + cvalue.re = fvalue; + cvalue.im = fvalue; + + //for (int i = 0; i < 20; i++) + // printf("%02x ", ((unsigned char *)&cvalue)[i]); + //printf("\n"); + e = new ComplexExp(loc, cvalue, this); + } + return e; + + Lint: + e = new IntegerExp(loc, ivalue, Type.tint32); + return e; + } + + Expression dotExp(Scope sc, Expression e, Identifier ident) + { +version (LOGDOTEXP) { + printf("TypeBasic.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); +} + Type t; + + if (ident is Id.re) + { + switch (ty) + { + case TY.Tcomplex32: t = tfloat32; goto L1; + case TY.Tcomplex64: t = tfloat64; goto L1; + case TY.Tcomplex80: t = tfloat80; goto L1; + L1: + e = e.castTo(sc, t); + break; + + case TY.Tfloat32: + case TY.Tfloat64: + case TY.Tfloat80: + break; + + case TY.Timaginary32: t = tfloat32; goto L2; + case TY.Timaginary64: t = tfloat64; goto L2; + case TY.Timaginary80: t = tfloat80; goto L2; + L2: + e = new RealExp(Loc(0), 0.0, t); + break; + + default: + return Type.getProperty(e.loc, ident); + } + } + else if (ident is Id.im) + { + Type t2; + + switch (ty) + { + case TY.Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3; + case TY.Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3; + case TY.Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3; + L3: + e = e.castTo(sc, t); + e.type = t2; + break; + + case TY.Timaginary32: t = tfloat32; goto L4; + case TY.Timaginary64: t = tfloat64; goto L4; + case TY.Timaginary80: t = tfloat80; goto L4; + L4: + e = e.copy(); + e.type = t; + break; + + case TY.Tfloat32: + case TY.Tfloat64: + case TY.Tfloat80: + e = new RealExp(Loc(0), 0.0, this); + break; + + default: + return Type.getProperty(e.loc, ident); + } + } + else + { + return Type.dotExp(sc, e, ident); + } + return e; + } + + string toChars() + { + return Type.toChars(); + } + + void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) + { + //printf("TypeBasic.toCBuffer2(mod = %d, this.mod = %d)\n", mod, this.mod); + if (mod != this.mod) + { + toCBuffer3(buf, hgs, mod); + return; + } + buf.writestring(dstring); + } + +version (CPP_MANGLE) { + void toCppMangle(OutBuffer buf, CppMangleState* cms) + { + assert(false); + } +} + bool isintegral() + { + //printf("TypeBasic.isintegral('%s') x%x\n", toChars(), flags); + return (flags & TFLAGS.TFLAGSintegral) != 0; + } + + bool isbit() + { + assert(false); + } + + bool isfloating() + { + return (flags & TFLAGS.TFLAGSfloating) != 0; + } + + bool isreal() + { + return (flags & TFLAGS.TFLAGSreal) != 0; + } + + bool isimaginary() + { + return (flags & TFLAGS.TFLAGSimaginary) != 0; + } + + bool iscomplex() + { + return (flags & TFLAGS.TFLAGScomplex) != 0; + } + + bool isscalar() + { + return (flags & (TFLAGS.TFLAGSintegral | TFLAGS.TFLAGSfloating)) != 0; + } + + bool isunsigned() + { + return (flags & TFLAGS.TFLAGSunsigned) != 0; + } + + MATCH implicitConvTo(Type to) + { + //printf("TypeBasic.implicitConvTo(%s) from %s\n", to.toChars(), toChars()); + if (this is to) + return MATCH.MATCHexact; + +version (DMDV2) { + if (ty is to.ty) + { + return (mod == to.mod) ? MATCH.MATCHexact : MATCH.MATCHconst; + } +} + + if (ty == TY.Tvoid || to.ty == TY.Tvoid) + return MATCH.MATCHnomatch; + if (to.ty == TY.Tbool) + return MATCH.MATCHnomatch; + if (!to.isTypeBasic()) + return MATCH.MATCHnomatch; + + TypeBasic tob = cast(TypeBasic)to; + if (flags & TFLAGS.TFLAGSintegral) + { + // Disallow implicit conversion of integers to imaginary or complex + if (tob.flags & (TFLAGS.TFLAGSimaginary | TFLAGS.TFLAGScomplex)) + return MATCH.MATCHnomatch; + +version (DMDV2) { + // If converting from integral to integral + if (1 && tob.flags & TFLAGS.TFLAGSintegral) + { ulong sz = size(Loc(0)); + ulong tosz = tob.size(Loc(0)); + + /* Can't convert to smaller size + */ + if (sz > tosz) + return MATCH.MATCHnomatch; + + /* Can't change sign if same size + */ + /*if (sz == tosz && (flags ^ tob.flags) & TFLAGSunsigned) + return MATCH.MATCHnomatch;*/ + } +} + } + else if (flags & TFLAGS.TFLAGSfloating) + { + // Disallow implicit conversion of floating point to integer + if (tob.flags & TFLAGS.TFLAGSintegral) + return MATCH.MATCHnomatch; + + assert(tob.flags & TFLAGS.TFLAGSfloating); + + // Disallow implicit conversion from complex to non-complex + if (flags & TFLAGS.TFLAGScomplex && !(tob.flags & TFLAGS.TFLAGScomplex)) + return MATCH.MATCHnomatch; + + // Disallow implicit conversion of real or imaginary to complex + if (flags & (TFLAGS.TFLAGSreal | TFLAGS.TFLAGSimaginary) && + tob.flags & TFLAGS.TFLAGScomplex) + return MATCH.MATCHnomatch; + + // Disallow implicit conversion to-from real and imaginary + if ((flags & (TFLAGS.TFLAGSreal | TFLAGS.TFLAGSimaginary)) != + (tob.flags & (TFLAGS.TFLAGSreal | TFLAGS.TFLAGSimaginary))) + return MATCH.MATCHnomatch; + } + return MATCH.MATCHconvert; + } + + Expression defaultInit(Loc loc) + { + long value = 0; + +version (SNAN_DEFAULT_INIT) { + /* + * Use a payload which is different from the machine NaN, + * so that uninitialised variables can be + * detected even if exceptions are disabled. + */ + ushort[8] snan = [ 0, 0, 0, 0xA000, 0x7FFF, 0, 0, 0 ]; + /* + * Although long doubles are 10 bytes long, some + * C ABIs pad them out to 12 or even 16 bytes, so + * leave enough space in the snan array. + */ + assert(REALSIZE <= snan.sizeof); + real fvalue = *cast(real*)snan.ptr; +} + + version (LOGDEFAULTINIT) { + printf("TypeBasic.defaultInit() '%s'\n", toChars()); + } + switch (ty) + { + case TY.Tchar: + value = 0xFF; + break; + + case TY.Twchar: + case TY.Tdchar: + value = 0xFFFF; + break; + + case TY.Timaginary32: + case TY.Timaginary64: + case TY.Timaginary80: + case TY.Tfloat32: + case TY.Tfloat64: + case TY.Tfloat80: + version (SNAN_DEFAULT_INIT) { + return new RealExp(loc, fvalue, this); + } else { + return getProperty(loc, Id.nan); + } + + case TY.Tcomplex32: + case TY.Tcomplex64: + case TY.Tcomplex80: + version (SNAN_DEFAULT_INIT) { + { + // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN). + Complex!(real) cvalue; + cvalue.re = fvalue; + cvalue.im = fvalue; + + return new ComplexExp(loc, cvalue, this); + } + } else { + return getProperty(loc, Id.nan); + } + + case TY.Tvoid: + error(loc, "void does not have a default initializer"); + + default: + break; /// + } + return new IntegerExp(loc, value, this); + } + + bool isZeroInit(Loc loc) + { + switch (ty) + { + case TY.Tchar: + case TY.Twchar: + case TY.Tdchar: + case TY.Timaginary32: + case TY.Timaginary64: + case TY.Timaginary80: + case TY.Tfloat32: + case TY.Tfloat64: + case TY.Tfloat80: + case TY.Tcomplex32: + case TY.Tcomplex64: + case TY.Tcomplex80: + return false; // no + default: + break; + } + + return true; // yes + } + + bool builtinTypeInfo() + { + version (DMDV2) { + return mod ? false : true; + } else { + return true; + } + } + + // For eliminating dynamic_cast + TypeBasic isTypeBasic() + { + return this; + } +} \ No newline at end of file