X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconstant.cs;h=d37e0f01bf37b55a738b4cc3c8b06dcb89bfc67d;hb=bff1c7a08cc189211e458561de52e76b403912f5;hp=ddc8b3b24387c75d222dbbf77771ec5dad775137;hpb=5705602f1b01fa05366c9c0328a9b5e3e4eecd89;p=mono.git diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index ddc8b3b2438..d37e0f01bf3 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -70,7 +70,7 @@ namespace Mono.CSharp { } } - public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) + public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type) { Constant c = ConvertImplicitly (type); if (c == null) @@ -89,7 +89,7 @@ namespace Mono.CSharp { if (this.type == type) return this; - if (!Convert.ImplicitNumericConversionExists (this.type, type)) + if (!Convert.ImplicitNumericConversionExists (this.type, type)) return null; bool fail; @@ -162,6 +162,88 @@ namespace Mono.CSharp { #endif } + // + // Returns a constant instance based on value and type. This is probing version of + // CreateConstantFromValue + // + public static Constant ExtractConstantFromValue (TypeSpec t, object v, Location loc) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + if (v is int) + return new IntConstant (t, (int) v, loc); + break; + case BuiltinTypeSpec.Type.String: + if (v is string) + return new StringConstant (t, (string) v, loc); + break; + case BuiltinTypeSpec.Type.UInt: + if (v is uint) + return new UIntConstant (t, (uint) v, loc); + break; + case BuiltinTypeSpec.Type.Long: + if (v is long) + return new LongConstant (t, (long) v, loc); + break; + case BuiltinTypeSpec.Type.ULong: + if (v is ulong) + return new ULongConstant (t, (ulong) v, loc); + break; + case BuiltinTypeSpec.Type.Float: + if (v is float) + return new FloatConstant (t, (float) v, loc); + break; + case BuiltinTypeSpec.Type.Double: + if (v is double) + return new DoubleConstant (t, (double) v, loc); + break; + case BuiltinTypeSpec.Type.Short: + if (v is short) + return new ShortConstant (t, (short) v, loc); + break; + case BuiltinTypeSpec.Type.UShort: + if (v is ushort) + return new UShortConstant (t, (ushort) v, loc); + break; + case BuiltinTypeSpec.Type.SByte: + if (v is sbyte) + return new SByteConstant (t, (sbyte) v, loc); + break; + case BuiltinTypeSpec.Type.Byte: + if (v is byte) + return new ByteConstant (t, (byte) v, loc); + break; + case BuiltinTypeSpec.Type.Char: + if (v is char) + return new CharConstant (t, (char) v, loc); + break; + case BuiltinTypeSpec.Type.Bool: + if (v is bool) + return new BoolConstant (t, (bool) v, loc); + break; + case BuiltinTypeSpec.Type.Decimal: + if (v is decimal) + return new DecimalConstant (t, (decimal) v, loc); + break; + } + + if (t.IsEnum) { + var real_type = EnumSpec.GetUnderlyingType (t); + return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t); + } + + if (v == null) { + if (t.IsNullableType) + return Nullable.LiftedNull.Create (t, loc); + + if (TypeSpec.IsReferenceType (t)) + return new NullConstant (t, loc); + } + + return null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -376,11 +458,6 @@ namespace Mono.CSharp { // It exists only as hint not to call Resolve on constants return true; } - - public override Constant ResolveAsPlayScriptConstant (ResolveContext rc) - { - return this; - } } public abstract class IntegralConstant : Constant @@ -1569,20 +1646,32 @@ namespace Mono.CSharp { } public class FloatConstant : Constant { - public readonly float Value; + // + // Store constant value as double because float constant operations + // need to work on double value to match JIT + // + public readonly double DoubleValue; - public FloatConstant (BuiltinTypes types, float v, Location loc) + public FloatConstant (BuiltinTypes types, double v, Location loc) : this (types.Float, v, loc) { } - public FloatConstant (TypeSpec type, float v, Location loc) + public FloatConstant (TypeSpec type, double v, Location loc) : base (loc) { this.type = type; eclass = ExprClass.Value; - Value = v; + DoubleValue = v; + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (type.BuiltinType == BuiltinTypeSpec.Type.Double) + return new DoubleConstant (type, DoubleValue, loc); + + return base.ConvertImplicitly (type); } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -1595,6 +1684,12 @@ namespace Mono.CSharp { ec.Emit (OpCodes.Ldc_R4, Value); } + public float Value { + get { + return (float) DoubleValue; + } + } + public override object GetValue () { return Value; @@ -1630,59 +1725,59 @@ namespace Mono.CSharp { if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ByteConstant (target_type, (byte) Value, Location); + return new ByteConstant (target_type, (byte) DoubleValue, Location); case BuiltinTypeSpec.Type.SByte: if (in_checked_context) { if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new SByteConstant (target_type, (sbyte) Value, Location); + return new SByteConstant (target_type, (sbyte) DoubleValue, Location); case BuiltinTypeSpec.Type.Short: if (in_checked_context) { if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ShortConstant (target_type, (short) Value, Location); + return new ShortConstant (target_type, (short) DoubleValue, Location); case BuiltinTypeSpec.Type.UShort: if (in_checked_context) { if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new UShortConstant (target_type, (ushort) Value, Location); + return new UShortConstant (target_type, (ushort) DoubleValue, Location); case BuiltinTypeSpec.Type.Int: if (in_checked_context) { if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new IntConstant (target_type, (int) Value, Location); + return new IntConstant (target_type, (int) DoubleValue, Location); case BuiltinTypeSpec.Type.UInt: if (in_checked_context) { if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new UIntConstant (target_type, (uint) Value, Location); + return new UIntConstant (target_type, (uint) DoubleValue, Location); case BuiltinTypeSpec.Type.Long: if (in_checked_context) { if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new LongConstant (target_type, (long) Value, Location); + return new LongConstant (target_type, (long) DoubleValue, Location); case BuiltinTypeSpec.Type.ULong: if (in_checked_context) { if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ULongConstant (target_type, (ulong) Value, Location); + return new ULongConstant (target_type, (ulong) DoubleValue, Location); case BuiltinTypeSpec.Type.Double: - return new DoubleConstant (target_type, (double) Value, Location); + return new DoubleConstant (target_type, DoubleValue, Location); case BuiltinTypeSpec.Type.Char: if (in_checked_context) { if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new CharConstant (target_type, (char) Value, Location); + return new CharConstant (target_type, (char) DoubleValue, Location); case BuiltinTypeSpec.Type.Decimal: - return new DecimalConstant (target_type, (decimal) Value, Location); + return new DecimalConstant (target_type, (decimal) DoubleValue, Location); } return null; @@ -2024,6 +2119,14 @@ namespace Mono.CSharp { { return null; } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (IsDefaultValue && type.BuiltinType == BuiltinTypeSpec.Type.Object) + return new NullConstant (type, loc); + + return base.ConvertImplicitly (type); + } } // @@ -2099,7 +2202,7 @@ namespace Mono.CSharp { } // Exlude internal compiler types - if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic && targetType.BuiltinType != BuiltinTypeSpec.Type.Object) + if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic) return null; if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))