Revert until fixed
[mono.git] / mcs / mcs / constant.cs
index 3f72833379e6988688954440508d8b0174a77bdd..76c2c5667a8574a363f163ea62e0f84844823968 100644 (file)
@@ -3,6 +3,7 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Marek Safar (marek.safar@seznam.cz)
 //
 // (C) 2001 Ximian, Inc.
 //
@@ -57,17 +58,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override void Error_ValueCannotBeConverted (Location loc, Type t)
-               {
-                       // string is not real constant
-                       if (type == TypeManager.string_type)
-                               base.Error_ValueCannotBeConverted (loc, t);
-                       else
-                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
-                                       AsString (), TypeManager.CSharpName (t));
-               }
-
-
                //
                // The various ToXXXX conversion functions are used by the constant
                // folding evaluator.   A null value is returned if the conversion is
@@ -84,7 +74,7 @@ namespace Mono.CSharp {
                        DoubleConstant c = ConvertToDouble ();
 
                        if (c == null)
-                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.double_type, false);
 
                        return c;
                }
@@ -94,7 +84,7 @@ namespace Mono.CSharp {
                        FloatConstant c = ConvertToFloat ();
 
                        if (c == null)
-                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.float_type, false);
 
                        return c;
                }
@@ -104,7 +94,7 @@ namespace Mono.CSharp {
                        ULongConstant c = ConvertToULong ();
 
                        if (c == null)
-                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.uint64_type, false);
 
                        return c;
                }
@@ -114,7 +104,7 @@ namespace Mono.CSharp {
                        LongConstant c = ConvertToLong ();
 
                        if (c == null)
-                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.int64_type, false);
 
                        return c;
                }
@@ -124,7 +114,7 @@ namespace Mono.CSharp {
                        UIntConstant c = ConvertToUInt ();
 
                        if (c == null)
-                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.uint32_type, false);
 
                        return c;
                }
@@ -134,7 +124,7 @@ namespace Mono.CSharp {
                        IntConstant c = ConvertToInt ();
 
                        if (c == null)
-                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
 
                        return c;
                }
@@ -144,7 +134,7 @@ namespace Mono.CSharp {
                        DecimalConstant c = ConvertToDecimal ();
 
                        if (c == null)
-                               Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
+                               Error_ValueCannotBeConverted (loc, TypeManager.decimal_type, false);
 
                        return c;
                }
@@ -158,7 +148,7 @@ namespace Mono.CSharp {
                                return this;
 
                        if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){
-                               Error_ValueCannotBeConverted (loc, type);
+                               Error_ValueCannotBeConverted (loc, type, false);
                                return null;
                        }
 
@@ -171,7 +161,7 @@ namespace Mono.CSharp {
                        bool fail;                      
                        object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
                        if (fail){
-                               Convert.Error_CannotImplicitConversion (loc, Type, type);
+                               Error_ValueCannotBeConverted (loc, type, false);
                                
                                //
                                // We should always catch the error before this is ever
@@ -216,6 +206,69 @@ namespace Mono.CSharp {
                        return retval;
                }
 
+               protected void CheckRange (EmitContext ec, ulong value, Type type, ulong max)
+               {
+                       if (!ec.ConstantCheckState)
+                               return;
+
+                       if (value > max)
+                               throw new OverflowException ();
+               }
+
+               protected void CheckRange (EmitContext ec, double value, Type type, long min, long max)
+               {
+                       if (!ec.ConstantCheckState)
+                               return;
+
+                       if (((value < min) || (value > max)))
+                               throw new OverflowException ();
+               }
+
+               protected void CheckUnsigned (EmitContext ec, long value, Type type)
+               {
+                       if (!ec.ConstantCheckState)
+                               return;
+
+                       if (value < 0)
+                               throw new OverflowException ();
+               }
+
+               public abstract Constant Reduce (EmitContext ec, Type target_type);
+
+               /// <summary>
+               ///   Attempts to do a compile-time folding of a constant cast.
+               /// </summary>
+               public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
+               {
+                       try {
+                               return  TryReduce (ec, target_type);
+                       }
+                       catch (OverflowException) {
+                               if (ec.ConstantCheckState) {
+                                       Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
+                                               GetValue ().ToString (), TypeManager.CSharpName (target_type));
+                               }
+                               return null;
+                       }
+               }
+
+               Constant TryReduce (EmitContext ec, Type target_type)
+               {
+                       if (Type == target_type)
+                               return this;
+
+                       if (TypeManager.IsEnumType (target_type)) {
+                               Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
+                               if (c == null)
+                                       return null;
+
+                               return new EnumConstant (c, target_type);
+                       }
+
+                       return Reduce (ec, target_type);
+               }
+
+
                public virtual DecimalConstant ConvertToDecimal ()
                {
                        return null;
@@ -321,6 +374,12 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == false; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       return null;
+               }
+
        }
 
        public class ByteConstant : Constant {
@@ -399,6 +458,37 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type)
+                               return new ShortConstant ((short) Value, Location);
+                       if (target_type == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort) Value, Location);
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) Value, Location);
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) Value, Location);
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type)
+                               return new CharConstant ((char) Value, Location);
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class CharConstant : Constant {
@@ -506,6 +596,39 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == '\0'; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MinValue, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type) {
+                               CheckRange (ec, Value, target_type, Int16.MinValue, Int16.MaxValue);
+                               return new ShortConstant ((short) Value, Location);
+                       }
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) Value, Location);
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) Value, Location);
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class SByteConstant : Constant {
@@ -587,6 +710,43 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type)
+                               return new ShortConstant ((short) Value, Location);
+                       if (target_type == TypeManager.ushort_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new UShortConstant ((ushort) Value, Location);
+                       } if (target_type == TypeManager.int32_type)
+                                 return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new UIntConstant ((uint) Value, Location);
+                       } if (target_type == TypeManager.int64_type)
+                                 return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new ULongConstant ((ulong) Value, Location);
+                       }
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class ShortConstant : Constant {
@@ -665,6 +825,47 @@ namespace Mono.CSharp {
                                return Value < 0;
                        }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MinValue, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.ushort_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new UShortConstant ((ushort) Value, Location);
+                       }
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new UIntConstant ((uint) Value, Location);
+                       }
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new ULongConstant ((ulong) Value, Location);
+                       }
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, Char.MinValue, Char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class UShortConstant : Constant {
@@ -743,6 +944,42 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MinValue, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type) {
+                               CheckRange (ec, Value, target_type, Int16.MinValue, Int16.MaxValue);
+                               return new ShortConstant ((short) Value, Location);
+                       }
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) Value, Location);
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) Value, Location);
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, Char.MinValue, Char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
        }
 
        public class IntConstant : Constant {
@@ -884,6 +1121,48 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MinValue, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type) {
+                               CheckRange (ec, Value, target_type, Int16.MinValue, Int16.MaxValue);
+                               return new ShortConstant ((short) Value, Location);
+                       }
+                       if (target_type == TypeManager.ushort_type) {
+                               CheckRange (ec, Value, target_type, UInt16.MinValue, UInt16.MaxValue);
+                               return new UShortConstant ((ushort) Value, Location);
+                       }
+                       if (target_type == TypeManager.uint32_type) {
+                               CheckRange (ec, Value, target_type, Int32.MinValue, Int32.MaxValue);
+                               return new UIntConstant ((uint) Value, Location);
+                       }
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new ULongConstant ((ulong) Value, Location);
+                       }
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, Char.MinValue, Char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
        }
 
        public class UIntConstant : Constant {
@@ -962,6 +1241,47 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Char.MinValue, Char.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type) {
+                               CheckRange (ec, Value, target_type, Int16.MinValue, Int16.MaxValue);
+                               return new ShortConstant ((short) Value, Location);
+                       }
+                       if (target_type == TypeManager.ushort_type) {
+                               CheckRange (ec, Value, target_type, UInt16.MinValue, UInt16.MaxValue);
+                               return new UShortConstant ((ushort) Value, Location);
+                       }
+                       if (target_type == TypeManager.int32_type) {
+                               CheckRange (ec, Value, target_type, Int32.MinValue, Int32.MaxValue);
+                               return new IntConstant ((int) Value, Location);
+                       }
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) Value, Location);
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, Char.MinValue, Char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class LongConstant : Constant {
@@ -1055,6 +1375,51 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MinValue, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type) {
+                               CheckRange (ec, Value, target_type, Int16.MinValue, Int16.MaxValue);
+                               return new ShortConstant ((short) Value, Location);
+                       }
+                       if (target_type == TypeManager.ushort_type) {
+                               CheckRange (ec, Value, target_type, UInt16.MinValue, UInt16.MaxValue);
+                               return new UShortConstant ((ushort) Value, Location);
+                       }
+                       if (target_type == TypeManager.int32_type) {
+                               CheckRange (ec, Value, target_type, Int32.MinValue, Int32.MaxValue);
+                               return new IntConstant ((int) Value, Location);
+                       }
+                       if (target_type == TypeManager.uint32_type) {
+                               CheckRange (ec, Value, target_type, UInt32.MinValue, UInt32.MaxValue);
+                               return new UIntConstant ((uint) Value, Location);
+                       }
+                       if (target_type == TypeManager.uint64_type) {
+                               CheckUnsigned (ec, Value, target_type);
+                               return new ULongConstant ((ulong) Value, Location);
+                       }
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, Char.MinValue, Char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class ULongConstant : Constant {
@@ -1135,6 +1500,51 @@ namespace Mono.CSharp {
                public override bool IsZeroInteger {
                        get { return Value == 0; }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, (ulong) SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type) {
+                               CheckRange (ec, Value, target_type, (ulong) Int16.MaxValue);
+                               return new ShortConstant ((short) Value, Location);
+                       }
+                       if (target_type == TypeManager.ushort_type) {
+                               CheckRange (ec, Value, target_type, UInt16.MaxValue);
+                               return new UShortConstant ((ushort) Value, Location);
+                       }
+                       if (target_type == TypeManager.int32_type) {
+                               CheckRange (ec, Value, target_type, Int32.MaxValue);
+                               return new IntConstant ((int) Value, Location);
+                       }
+                       if (target_type == TypeManager.uint32_type) {
+                               CheckRange (ec, Value, target_type, UInt32.MaxValue);
+                               return new UIntConstant ((uint) Value, Location);
+                       }
+                       if (target_type == TypeManager.int64_type) {
+                               CheckRange (ec, Value, target_type, (ulong) Int64.MaxValue);
+                               return new LongConstant ((long) Value, Location);
+                       }
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, Char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class FloatConstant : Constant {
@@ -1204,6 +1614,35 @@ namespace Mono.CSharp {
                                return Value < 0;
                        }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type)
+                               return new ByteConstant ((byte) Value, Location);
+                       if (target_type == TypeManager.sbyte_type)
+                               return new SByteConstant ((sbyte) Value, Location);
+                       if (target_type == TypeManager.short_type)
+                               return new ShortConstant ((short) Value, Location);
+                       if (target_type == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort) Value, Location);
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) Value, Location);
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) Value, Location);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) Value, Location);
+                       if (target_type == TypeManager.char_type)
+                               return new CharConstant ((char) Value, Location);
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class DoubleConstant : Constant {
@@ -1278,6 +1717,41 @@ namespace Mono.CSharp {
                                return Value < 0;
                        }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.byte_type) {
+                               CheckRange (ec, Value, target_type, Byte.MinValue, Byte.MaxValue);
+                               return new ByteConstant ((byte) Value, Location);
+                       }
+                       if (target_type == TypeManager.sbyte_type) {
+                               CheckRange (ec, Value, target_type, SByte.MinValue, SByte.MaxValue);
+                               return new SByteConstant ((sbyte) Value, Location);
+                       }
+                       if (target_type == TypeManager.short_type)
+                               return new ShortConstant ((short) Value, Location);
+                       if (target_type == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort) Value, Location);
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int) Value, Location);
+                       if (target_type == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) Value, Location);
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long) Value, Location);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) Value, Location);
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) Value, Location);
+                       if (target_type == TypeManager.char_type) {
+                               CheckRange (ec, Value, target_type, char.MinValue, char.MaxValue);
+                               return new CharConstant ((char) Value, Location);
+                       }
+                       if (target_type == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) Value, Location);
+
+                       return null;
+               }
+
        }
 
        public class DecimalConstant : Constant {
@@ -1350,6 +1824,35 @@ namespace Mono.CSharp {
                                return Value < 0;
                        }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       if (target_type == TypeManager.sbyte_type)
+                               return new SByteConstant ((sbyte)Value, loc);
+                       if (target_type == TypeManager.byte_type)
+                               return new ByteConstant ((byte)Value, loc);
+                       if (target_type == TypeManager.short_type)
+                               return new ShortConstant ((short)Value, loc);
+                       if (target_type == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort)Value, loc);
+                       if (target_type == TypeManager.int32_type)
+                               return new IntConstant ((int)Value, loc);
+                       if (target_type == TypeManager.uint32_type)
+                               return new UIntConstant ((uint)Value, loc);
+                       if (target_type == TypeManager.int64_type)
+                               return new LongConstant ((long)Value, loc);
+                       if (target_type == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong)Value, loc);
+                       if (target_type == TypeManager.char_type)
+                               return new CharConstant ((char)Value, loc);
+                       if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float)Value, loc);
+                       if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double)Value, loc);
+
+                       return null;
+               }
+
        }
 
        public class StringConstant : Constant {
@@ -1398,6 +1901,11 @@ namespace Mono.CSharp {
                                return false;
                        }
                }
+
+               public override Constant Reduce (EmitContext ec, Type target_type)
+               {
+                       return null;
+               }
        }
 
 }