Ooops. No wonder people complained I never fixed this, I never flushed
[mono.git] / mcs / mcs / constant.cs
index 6fa4c625233b07cde9734a7b8a25a7fd6fd55e31..2bfdfc031f5a8f6eb889daeffcb7a677dbca3ffa 100755 (executable)
@@ -17,12 +17,6 @@ namespace Mono.CSharp {
        ///   Base class for constants and literals.
        /// </summary>
        public abstract class Constant : Expression {
-
-               protected Constant ()
-               {
-                       eclass = ExprClass.Value;
-               }
-
                /// <remarks>
                ///   This is different from ToString in that ToString
                ///   is supposed to be there for debugging purposes,
@@ -35,7 +29,7 @@ namespace Mono.CSharp {
 
                override public string ToString ()
                {
-                       return AsString ();
+                       return this.GetType ().Name + " (" + AsString () + ")";
                }
 
                /// <summary>
@@ -51,14 +45,116 @@ namespace Mono.CSharp {
                {
                        return this;
                }
-       }
 
+               //
+               // The various ToXXXX conversion functions are used by the constant
+               // folding evaluator.   A null value is returned if the conversion is
+               // not possible.   
+               //
+               // Note: not all the patterns for catching `implicit_conv' are the same.
+               // some implicit conversions can never be performed between two types
+               // even if the conversion would be lossless (for example short to uint),
+               // but some conversions are explicitly permitted by the standard provided
+               // that there will be no loss of information (for example, int to uint).
+               //
+               public DoubleConstant ToDouble (Location loc)
+               {
+                       DoubleConstant c = ConvertToDouble ();
+
+                       if (c == null)
+                               Error_CannotConvertImplicit (loc, Type, TypeManager.double_type);
+
+                       return c;
+               }
+
+               public FloatConstant ToFloat (Location loc)
+               {
+                       FloatConstant c = ConvertToFloat ();
+
+                       if (c == null)
+                               Error_CannotConvertImplicit (loc, Type, TypeManager.float_type);
+
+                       return c;
+               }
+
+               public ULongConstant ToULong (Location loc)
+               {
+                       ULongConstant c = ConvertToULong ();
+
+                       if (c == null)
+                               Error_CannotConvertImplicit (loc, Type, TypeManager.uint64_type);
+
+                       return c;
+               }
+
+               public LongConstant ToLong (Location loc)
+               {
+                       LongConstant c = ConvertToLong ();
+
+                       if (c == null)
+                               Error_CannotConvertImplicit (loc, Type, TypeManager.int64_type);
+
+                       return c;
+               }
+               
+               public UIntConstant ToUInt (Location loc)
+               {
+                       UIntConstant c = ConvertToUInt ();
+
+                       if (c == null)
+                               Error_CannotConvertImplicit (loc, Type, TypeManager.uint32_type);
+
+                       return c;
+               }
+
+               public IntConstant ToInt (Location loc)
+               {
+                       IntConstant c = ConvertToInt ();
+
+                       if (c == null)
+                               Error_CannotConvertImplicit (loc, Type, TypeManager.int32_type);
+
+                       return c;
+               }
+               
+               public virtual DoubleConstant ConvertToDouble ()
+               {
+                       return null;
+               }
+
+               public virtual FloatConstant ConvertToFloat ()
+               {
+                       return null;
+               }
+
+               public virtual ULongConstant ConvertToULong ()
+               {
+                       return null;
+               }
+
+               public virtual LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public virtual UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public virtual IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+       
        public class BoolConstant : Constant {
                public readonly bool Value;
                
                public BoolConstant (bool val)
                {
                        type = TypeManager.bool_type;
+                       eclass = ExprClass.Value;
 
                        Value = val;
                }
@@ -89,6 +185,7 @@ namespace Mono.CSharp {
                public ByteConstant (byte v)
                {
                        type = TypeManager.byte_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -106,6 +203,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return new UIntConstant (Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
        }
 
        public class CharConstant : Constant {
@@ -114,6 +241,7 @@ namespace Mono.CSharp {
                public CharConstant (char v)
                {
                        type = TypeManager.char_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -160,6 +288,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return new UIntConstant (Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
        }
 
        public class SByteConstant : Constant {
@@ -168,6 +326,7 @@ namespace Mono.CSharp {
                public SByteConstant (sbyte v)
                {
                        type = TypeManager.sbyte_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -185,6 +344,39 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       if (Value >= 0)
+                               return new ULongConstant ((ulong) Value);
+                       
+                       return null;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
        }
 
        public class ShortConstant : Constant {
@@ -193,6 +385,7 @@ namespace Mono.CSharp {
                public ShortConstant (short v)
                {
                        type = TypeManager.short_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -210,6 +403,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return null;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
        }
 
        public class UShortConstant : Constant {
@@ -218,6 +441,7 @@ namespace Mono.CSharp {
                public UShortConstant (ushort v)
                {
                        type = TypeManager.ushort_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -235,6 +459,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return new UIntConstant (Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
        }
 
        public class IntConstant : Constant {
@@ -243,6 +497,7 @@ namespace Mono.CSharp {
                public IntConstant (int v)
                {
                        type = TypeManager.int32_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -312,6 +567,42 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       if (Value < 0)
+                               return null;
+
+                       return new ULongConstant ((ulong) Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       if (Value < 0)
+                               return null;
+
+                       return new UIntConstant ((uint) Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return this;
+               }
        }
 
        public class UIntConstant : Constant {
@@ -320,6 +611,7 @@ namespace Mono.CSharp {
                public UIntConstant (uint v)
                {
                        type = TypeManager.uint32_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -337,6 +629,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return this;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
        }
 
        public class LongConstant : Constant {
@@ -345,6 +667,7 @@ namespace Mono.CSharp {
                public LongConstant (long v)
                {
                        type = TypeManager.int64_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -369,6 +692,39 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       if (Value < 0)
+                               return null;
+                       
+                       return new ULongConstant ((ulong) Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return this;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
        }
 
        public class ULongConstant : Constant {
@@ -377,6 +733,7 @@ namespace Mono.CSharp {
                public ULongConstant (ulong v)
                {
                        type = TypeManager.uint64_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -396,6 +753,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return this;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
        }
 
        public class FloatConstant : Constant {
@@ -404,6 +791,7 @@ namespace Mono.CSharp {
                public FloatConstant (float v)
                {
                        type = TypeManager.float_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -421,6 +809,31 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return this;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
        }
 
        public class DoubleConstant : Constant {
@@ -429,6 +842,7 @@ namespace Mono.CSharp {
                public DoubleConstant (double v)
                {
                        type = TypeManager.double_type;
+                       eclass = ExprClass.Value;
                        Value = v;
                }
 
@@ -446,6 +860,36 @@ namespace Mono.CSharp {
                {
                        return Value;
                }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return this;
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return null;
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return null;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
        }
 
        public class DecimalConstant : Constant {
@@ -454,6 +898,7 @@ namespace Mono.CSharp {
                public DecimalConstant (decimal d)
                {
                        type = TypeManager.decimal_type;
+                       eclass = ExprClass.Value;
                        Value = d;
                }
 
@@ -469,7 +914,26 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Implement me");
+                       int [] words = Decimal.GetBits (Value);
+                       
+                       //
+                       // FIXME: we could optimize this, and call a better 
+                       // constructor
+                       //
+
+                       ILGenerator ig = ec.ig;
+                       
+                       IntConstant.EmitInt (ig, words [0]);
+                       IntConstant.EmitInt (ig, words [1]);
+                       IntConstant.EmitInt (ig, words [2]);
+
+                       // sign
+                       IntConstant.EmitInt (ig, words [3] >> 31);
+
+                       // power
+                       IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
+
+                       ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
                }
        }
 
@@ -479,6 +943,7 @@ namespace Mono.CSharp {
                public StringConstant (string s)
                {
                        type = TypeManager.string_type;
+                       eclass = ExprClass.Value;
                        Value = s;
                }