Reverted.
authorMarek Safar <marek.safar@gmail.com>
Thu, 30 Nov 2006 22:46:13 +0000 (22:46 -0000)
committerMarek Safar <marek.safar@gmail.com>
Thu, 30 Nov 2006 22:46:13 +0000 (22:46 -0000)
svn path=/trunk/mcs/; revision=68781

mcs/mcs/ChangeLog
mcs/mcs/cfold.cs
mcs/mcs/const.cs
mcs/mcs/constant.cs
mcs/mcs/convert.cs
mcs/mcs/ecore.cs
mcs/mcs/enum.cs
mcs/mcs/expression.cs
mcs/mcs/literal.cs

index 274ef071be24fe92b56039619ce89be8a7f5f94b..b7accf51d372686eee40915294d8ac61fe26cc49 100644 (file)
@@ -1,27 +1,3 @@
-2006-11-30  Marek Safar  <marek.safar@gmail.com>
-
-       Correct unary operators implementation (part I)
-       Also fixes #80026
-
-       * cfold.cs (Error_CompileTimeOverflow): Made internal
-
-       * const.cs (IConstant): Changed to use reference to constant and
-       not constant itself.
-       Updated IConstant implementations.
-
-       * constant.cs (CreateConstant): New factory method.
-       Updated IConstant implementation.
-
-       * convert.cs (ImplicitStandardConversionExists): Uses compiler Equals.
-
-       * ecore.cs: Updated to use CreateConstantReference.
-
-       * enum.cs: Reflects IConstant changes.
-
-       * expression.cs (Unary): Reimplemented +,-,~ to conform C# standard.
-
-       * literal.cs (NullConstant): Change to be independently usable.
-
 2006-11-29  Martin Baulig  <martin@ximian.com>
 
        * class.cs (Constructor.Emit): Correctly handle anonymous methods;
index f8d1f424a9bf4ae9b95e2b4f40a8336ba7c6c171..9986c418e0fdf923609d4f6b2be772e19d96aab5 100644 (file)
@@ -162,7 +162,7 @@ namespace Mono.CSharp {
                        return;
                }
 
-               internal static void Error_CompileTimeOverflow (Location loc)
+               static void Error_CompileTimeOverflow (Location loc)
                {
                        Report.Error (220, loc, "The operation overflows at compile time in checked mode");
                }
index b947e4d68f5485ee6552e1e4abb33d32d71d8459..7422b492b3f23be40c2771edca882855dc315718 100644 (file)
@@ -20,7 +20,7 @@ namespace Mono.CSharp {
        {
                void CheckObsoleteness (Location loc);
                bool ResolveValue ();
-               Constant CreateConstantReference (Location loc);
+               Constant Value { get; }
        }
 
        public class Const : FieldMember, IConstant {
@@ -189,12 +189,10 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public Constant CreateConstantReference (Location loc)
-               {
-                       if (value == null)
-                               return null;
-
-                       return Constant.CreateConstant (value.Type, value.GetValue(), loc);
+               public Constant Value {
+                       get {
+                               return value;
+                       }
                }
 
                #endregion
@@ -203,14 +201,14 @@ namespace Mono.CSharp {
        public class ExternalConstant : IConstant
        {
                FieldInfo fi;
-               object value;
+               Constant value;
 
                public ExternalConstant (FieldInfo fi)
                {
                        this.fi = fi;
                }
 
-               private ExternalConstant (FieldInfo fi, object value):
+               private ExternalConstant (FieldInfo fi, Constant value):
                        this (fi)
                {
                        this.value = value;
@@ -231,7 +229,7 @@ namespace Mono.CSharp {
                                return null;
 
                        IConstant ic = new ExternalConstant (fi,
-                               ((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
+                               new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value, Location.Null));
 
                        return ic;
                }
@@ -253,13 +251,20 @@ namespace Mono.CSharp {
                        if (value != null)
                                return true;
 
-                       value = fi.GetValue (fi);
+                       if (fi.DeclaringType.IsEnum) {
+                               value = Expression.Constantify (fi.GetValue (fi), TypeManager.EnumToUnderlying (fi.FieldType));
+                               value = new EnumConstant (value, fi.DeclaringType);
+                               return true;
+                       }
+
+                       value = Expression.Constantify (fi.GetValue (fi), fi.FieldType);
                        return true;
                }
 
-               public Constant CreateConstantReference (Location loc)
-               {
-                       return Constant.CreateConstant (fi.FieldType, value, loc);
+               public Constant Value {
+                       get {
+                               return value;
+                       }
                }
 
                #endregion
index e88ffadd4e3088e5b633306cd7755c4dfe781964..69a91c2f232f2e9d9e681f8781fd8bab998e1892 100644 (file)
@@ -188,52 +188,39 @@ namespace Mono.CSharp {
                                        String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
                        }
 
-                       return CreateConstant (type, constant_value, loc);
-               }
-
-               ///  Returns a constant instance based on Type
-               ///  The returned value is already resolved.
-               public static Constant CreateConstant (Type t, object v, Location loc)
-               {
-                       if (t == TypeManager.int32_type)
-                               return new IntConstant ((int) v, loc);
-                       if (t == TypeManager.string_type)
-                               return new StringConstant ((string) v, loc);
-                       if (t == TypeManager.uint32_type)
-                               return new UIntConstant ((uint) v, loc);
-                       if (t == TypeManager.int64_type)
-                               return new LongConstant ((long) v, loc);
-                       if (t == TypeManager.uint64_type)
-                               return new ULongConstant ((ulong) v, loc);
-                       if (t == TypeManager.float_type)
-                               return new FloatConstant ((float) v, loc);
-                       if (t == TypeManager.double_type)
-                               return new DoubleConstant ((double) v, loc);
-                       if (t == TypeManager.short_type)
-                               return new ShortConstant ((short)v, loc);
-                       if (t == TypeManager.ushort_type)
-                               return new UShortConstant ((ushort)v, loc);
-                       if (t == TypeManager.sbyte_type)
-                               return new SByteConstant ((sbyte)v, loc);
-                       if (t == TypeManager.byte_type)
-                               return new ByteConstant ((byte)v, loc);
-                       if (t == TypeManager.char_type)
-                               return new CharConstant ((char)v, loc);
-                       if (t == TypeManager.bool_type)
-                               return new BoolConstant ((bool) v, loc);
-                       if (t == TypeManager.decimal_type)
-                               return new DecimalConstant ((decimal) v, loc);
-                       if (TypeManager.IsEnumType (t)) {
-                               Type real_type = TypeManager.TypeToCoreType (v.GetType ());
-                               if (real_type == t)
-                                       real_type = System.Enum.GetUnderlyingType (real_type);
-                               return new EnumConstant (CreateConstant (real_type, v, loc), t);
-                       } 
-                       if (v == null && !TypeManager.IsValueType (t))
-                               return new EmptyConstantCast (new NullConstant (loc), t);
-
-                       throw new Exception ("Unknown type for constant (" + t +
-                                       "), details: " + v);
+                       Constant retval;
+                       if (type == TypeManager.int32_type)
+                               retval = new IntConstant ((int) constant_value, loc);
+                       else if (type == TypeManager.uint32_type)
+                               retval = new UIntConstant ((uint) constant_value, loc);
+                       else if (type == TypeManager.int64_type)
+                               retval = new LongConstant ((long) constant_value, loc);
+                       else if (type == TypeManager.uint64_type)
+                               retval = new ULongConstant ((ulong) constant_value, loc);
+                       else if (type == TypeManager.float_type)
+                               retval = new FloatConstant ((float) constant_value, loc);
+                       else if (type == TypeManager.double_type)
+                               retval = new DoubleConstant ((double) constant_value, loc);
+                       else if (type == TypeManager.string_type)
+                               retval = new StringConstant ((string) constant_value, loc);
+                       else if (type == TypeManager.short_type)
+                               retval = new ShortConstant ((short) constant_value, loc);
+                       else if (type == TypeManager.ushort_type)
+                               retval = new UShortConstant ((ushort) constant_value, loc);
+                       else if (type == TypeManager.sbyte_type)
+                               retval = new SByteConstant ((sbyte) constant_value, loc);
+                       else if (type == TypeManager.byte_type)
+                               retval = new ByteConstant ((byte) constant_value, loc);
+                       else if (type == TypeManager.char_type)
+                               retval = new CharConstant ((char) constant_value, loc);
+                       else if (type == TypeManager.bool_type)
+                               retval = new BoolConstant ((bool) constant_value, loc);
+                       else if (type == TypeManager.decimal_type)
+                               retval = new DecimalConstant ((decimal) constant_value, loc);
+                       else
+                               throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
+                       
+                       return retval;
                }
 
                protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
@@ -391,12 +378,16 @@ namespace Mono.CSharp {
                public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
                {
                        try {
+                               Console.WriteLine (GetValue ());
+                               Console.WriteLine (GetType ());
                                Reduce (true, target);
                                base.Error_ValueCannotBeConverted (loc, target, expl);
                        }
-                       catch 
+                       catch (Exception e) 
                        {
-                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
+                               
+Console.WriteLine(e.ToString());
+                               Report.Error (9931, loc, "Constant value `{0}' cannot be converted to a `{1}'",
                                        GetValue ().ToString (), TypeManager.CSharpName (target));
                        }
                }
@@ -1625,7 +1616,7 @@ namespace Mono.CSharp {
        }
 
        public class FloatConstant : Constant {
-               public float Value;
+               public readonly float Value;
 
                public FloatConstant (float v, Location loc):
                        base (loc)
@@ -1741,7 +1732,7 @@ namespace Mono.CSharp {
        }
 
        public class DoubleConstant : Constant {
-               public double Value;
+               public readonly double Value;
 
                public DoubleConstant (double v, Location loc):
                        base (loc)
index 16e16ac006de1d6b920d34e7d55a428f8721d7fa..a35cc845bf27230694ce6f9c77874c6050ea1bf6 100644 (file)
@@ -666,7 +666,7 @@ namespace Mono.CSharp {
 
                        //Console.WriteLine ("Expr is {0}", expr);
                        //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
-                       if (TypeManager.IsEqual (expr_type, target_type))
+                       if (expr_type.Equals (target_type))
                                return true;
 
 
index 8f5398ecae40462e50a8ee6fdc5687452b9491c3..3ae282ba6f5018ebd8a61228a5359490f0ef74c4 100644 (file)
@@ -330,6 +330,7 @@ namespace Mono.CSharp {
                        }
                        
                        Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
+                       Console.WriteLine ("Converting {0} -> {1}", Type.ToString (), target.ToString());
                        bool b = Convert.ExplicitNumericConversion (e, target) != null;
 
                        if (b || Convert.ExplicitReferenceConversionExists (Type, target) ||
@@ -538,6 +539,64 @@ namespace Mono.CSharp {
                        type = null;
                }
 
+               /// <summary>
+               ///   Returns a literalized version of a literal FieldInfo
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The possible return values are:
+               ///      IntConstant, UIntConstant
+               ///      LongLiteral, ULongConstant
+               ///      FloatConstant, DoubleConstant
+               ///      StringConstant
+               ///
+               ///   The value returned is already resolved.
+               /// </remarks>
+               public static Constant Constantify (object v, Type t)
+               {
+                       if (t == TypeManager.int32_type)
+                               return new IntConstant ((int) v, Location.Null);
+                       else if (t == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) v, Location.Null);
+                       else if (t == TypeManager.int64_type)
+                               return new LongConstant ((long) v, Location.Null);
+                       else if (t == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) v, Location.Null);
+                       else if (t == TypeManager.float_type)
+                               return new FloatConstant ((float) v, Location.Null);
+                       else if (t == TypeManager.double_type)
+                               return new DoubleConstant ((double) v, Location.Null);
+                       else if (t == TypeManager.string_type)
+                               return new StringConstant ((string) v, Location.Null);
+                       else if (t == TypeManager.short_type)
+                               return new ShortConstant ((short)v, Location.Null);
+                       else if (t == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort)v, Location.Null);
+                       else if (t == TypeManager.sbyte_type)
+                               return new SByteConstant ((sbyte)v, Location.Null);
+                       else if (t == TypeManager.byte_type)
+                               return new ByteConstant ((byte)v, Location.Null);
+                       else if (t == TypeManager.char_type)
+                               return new CharConstant ((char)v, Location.Null);
+                       else if (t == TypeManager.bool_type)
+                               return new BoolConstant ((bool) v, Location.Null);
+                       else if (t == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal) v, Location.Null);
+                       else if (TypeManager.IsEnumType (t)){
+                               Type real_type = TypeManager.TypeToCoreType (v.GetType ());
+                               if (real_type == t)
+                                       real_type = System.Enum.GetUnderlyingType (real_type);
+
+                               Constant e = Constantify (v, real_type);
+
+                               return new EnumConstant (e, t);
+                       } else if (v == null && !TypeManager.IsValueType (t))
+                               return new NullLiteral (Location.Null);
+                       else
+                               throw new Exception ("Unknown type for constant (" + t +
+                                                    "), details: " + v);
+               }
+
                /// <summary>
                ///   Returns a fully formed expression after a MemberLookup
                /// </summary>
@@ -3137,7 +3196,7 @@ namespace Mono.CSharp {
                                                ic.CheckObsoleteness (loc);
                                }
 
-                               return ic.CreateConstantReference (loc);
+                               return ic.Value;
                        }
                        
                        if (t.IsPointer && !ec.InUnsafe) {
index 75a9dbd7d5e404500be0829063d4d56711ad8a6b..6067a8acfa3fa093b1eac3f098efb091b2359ed8 100644 (file)
@@ -28,7 +28,7 @@ namespace Mono.CSharp {
                readonly Expression ValueExpr;
                readonly EnumMember prev_member;
 
-               EnumConstant value;
+               Constant value;
                bool in_transit;
 
                // TODO: remove or simplify
@@ -149,7 +149,7 @@ namespace Mono.CSharp {
                        in_transit = true;
 
                        try {
-                               value = (EnumConstant)prev_member.value.Increment ();
+                               value = prev_member.value.Increment ();
                        }
                        catch (OverflowException) {
                                Report.Error (543, Location, "The enumerator value `{0}' is too large to fit in its type `{1}'",
@@ -193,13 +193,10 @@ namespace Mono.CSharp {
 
                #region IConstant Members
 
-               public Constant CreateConstantReference (Location loc)
-               {
-                       if (value == null)
-                               return null;
-
-                       return new EnumConstant (Constant.CreateConstant (value.Child.Type, value.Child.GetValue(), loc),
-                               value.Type);
+               public Constant Value {
+                       get {
+                               return value;
+                       }
                }
 
                #endregion
index e4b6384a907b45745f807397b61dbc78d9475276..c975d3ea7fd362fd7ea23a82c69a99a1ab391cac 100644 (file)
@@ -194,161 +194,154 @@ namespace Mono.CSharp {
                        Error_OperatorCannotBeApplied (loc, OperName (Oper), t);
                }
 
+               /// <remarks>
+               ///   The result has been already resolved:
+               ///
+               ///   FIXME: a minus constant -128 sbyte cant be turned into a
+               ///   constant byte.
+               /// </remarks>
+               static Expression TryReduceNegative (Constant expr)
+               {
+                       Expression e = null;
+
+                       if (expr is IntConstant)
+                               e = new IntConstant (-((IntConstant) expr).Value, expr.Location);
+                       else if (expr is UIntConstant){
+                               uint value = ((UIntConstant) expr).Value;
+
+                               if (value < 2147483649)
+                                       return new IntConstant (-(int)value, expr.Location);
+                               else
+                                       e = new LongConstant (-value, expr.Location);
+                       }
+                       else if (expr is LongConstant)
+                               e = new LongConstant (-((LongConstant) expr).Value, expr.Location);
+                       else if (expr is ULongConstant){
+                               ulong value = ((ULongConstant) expr).Value;
+
+                               if (value < 9223372036854775809)
+                                       return new LongConstant(-(long)value, expr.Location);
+                       }
+                       else if (expr is FloatConstant)
+                               e = new FloatConstant (-((FloatConstant) expr).Value, expr.Location);
+                       else if (expr is DoubleConstant)
+                               e = new DoubleConstant (-((DoubleConstant) expr).Value, expr.Location);
+                       else if (expr is DecimalConstant)
+                               e = new DecimalConstant (-((DecimalConstant) expr).Value, expr.Location);
+                       else if (expr is ShortConstant)
+                               e = new IntConstant (-((ShortConstant) expr).Value, expr.Location);
+                       else if (expr is UShortConstant)
+                               e = new IntConstant (-((UShortConstant) expr).Value, expr.Location);
+                       else if (expr is SByteConstant)
+                               e = new IntConstant (-((SByteConstant) expr).Value, expr.Location);
+                       else if (expr is ByteConstant)
+                               e = new IntConstant (-((ByteConstant) expr).Value, expr.Location);
+                       return e;
+               }
+
                // <summary>
                //   This routine will attempt to simplify the unary expression when the
-               //   argument is a constant.
+               //   argument is a constant.  The result is returned in `result' and the
+               //   function returns true or false depending on whether a reduction
+               //   was performed or not
                // </summary>
-               Constant TryReduceConstant (EmitContext ec, Constant e)
+               bool Reduce (EmitContext ec, Constant e, out Expression result)
                {
                        Type expr_type = e.Type;
                        
                        switch (Oper){
-                               case Operator.UnaryPlus:
-                                       // Unary numeric promotions
-                                       if (expr_type == TypeManager.byte_type)
-                                               return new IntConstant (((ByteConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.sbyte_type)
-                                               return new IntConstant (((SByteConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.short_type)
-                                               return new IntConstant (((ShortConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.ushort_type)
-                                               return new IntConstant (((UShortConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.char_type)
-                                               return new IntConstant (((CharConstant)e).Value, e.Location);
-
-                                       // Predefined operators
-                                       if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
-                                               expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
-                                               expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
-                                               expr_type == TypeManager.decimal_type)
-                                       {
-                                               return e;
-                                       }
-
-                                       return null;
+                       case Operator.UnaryPlus:
+                               if (expr_type == TypeManager.bool_type){
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
                                
-                               case Operator.UnaryNegation:
-                                       // Unary numeric promotions
-                                       if (expr_type == TypeManager.byte_type)
-                                               return new IntConstant (-((ByteConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.sbyte_type)
-                                               return new IntConstant (-((SByteConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.short_type)
-                                               return new IntConstant (-((ShortConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.ushort_type)
-                                               return new IntConstant (-((UShortConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.char_type)
-                                               return new IntConstant (-((CharConstant)e).Value, e.Location);
-
-                                       // Predefined operators
-                                       if (expr_type == TypeManager.int32_type) {
-                                               int value = ((IntConstant)e).Value;
-                                               if (value == int.MinValue) {
-                                                       if (ec.ConstantCheckState) {
-                                                               ConstantFold.Error_CompileTimeOverflow (loc);
-                                                               return null;
-                                                       }
-                                                       return e;
-                                               }
-                                               return new IntConstant (-value, e.Location);
-                                       }
-                                       if (expr_type == TypeManager.int64_type) {
-                                               long value = ((LongConstant)e).Value;
-                                               if (value == long.MinValue) {
-                                                       if (ec.ConstantCheckState) {
-                                                               ConstantFold.Error_CompileTimeOverflow (loc);
-                                                               return null;
-                                                       }
-                                                       return e;
-                                               }
-                                               return new LongConstant (-value, e.Location);
-                                       }
-
-                                       if (expr_type == TypeManager.uint32_type) {
-                                               UIntLiteral uil = e as UIntLiteral;
-                                               if (uil != null) {
-                                                       if (uil.Value == 2147483648)
-                                                               return new IntLiteral (int.MinValue, e.Location);
-                                                       return new LongLiteral (-uil.Value, e.Location);
-                                               }
-                                               return new LongConstant (-((UIntConstant)e).Value, e.Location);
-                                       }
-
-                                       if (expr_type == TypeManager.uint64_type) {
-                                               ULongLiteral ull = e as ULongLiteral;
-                                               if (ull != null && ull.Value == 9223372036854775808)
-                                                       return new LongLiteral (long.MinValue, e.Location);
-                                               return null;
+                               result = e;
+                               return true;
+                               
+                       case Operator.UnaryNegation:
+                               result = TryReduceNegative (e);
+                               return result != null;
+                               
+                       case Operator.LogicalNot:
+                               if (expr_type != TypeManager.bool_type) {
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
+                               
+                               BoolConstant b = (BoolConstant) e;
+                               result = new BoolConstant (!(b.Value), b.Location);
+                               return true;
+                               
+                       case Operator.OnesComplement:
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+
+                                       result = null;
+                                       if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
+                                               result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
+                                               result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
+                                               result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
+                                               result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
+                                               result = result.Resolve (ec);
                                        }
 
-                                       if (expr_type == TypeManager.float_type) {
-                                               FloatLiteral fl = e as FloatLiteral;
-                                               // For better error reporting
-                                               if (fl != null) {
-                                                       fl.Value = -fl.Value;
-                                                       return fl;
-                                               }
-                                               return new FloatConstant (-((FloatConstant)e).Value, e.Location);
+                                       if (result == null || !(result is Constant)){
+                                               result = null;
+                                               Error23 (expr_type);
+                                               return false;
                                        }
-                                       if (expr_type == TypeManager.double_type) {
-                                               DoubleLiteral dl = e as DoubleLiteral;
-                                               // For better error reporting
-                                               if (dl != null) {
-                                                       dl.Value = -dl.Value;
-                                                       return dl;
-                                               }
 
-                                               return new DoubleConstant (-((DoubleConstant)e).Value, e.Location);
-                                       }
-                                       if (expr_type == TypeManager.decimal_type)
-                                               return new DecimalConstant (-((DecimalConstant)e).Value, e.Location);
+                                       expr_type = result.Type;
+                                       e = (Constant) result;
+                               }
 
-                                       return null;
-                               
-                               case Operator.LogicalNot:
-                                       if (expr_type != TypeManager.bool_type)
-                                               return null;
+                               if (e is EnumConstant){
+                                       EnumConstant enum_constant = (EnumConstant) e;
+                                       Expression reduced;
                                        
-                                       BoolConstant b = (BoolConstant) e;
-                                       return new BoolConstant (!(b.Value), b.Location);
-                               
-                               case Operator.OnesComplement:
-                                       // Unary numeric promotions
-                                       if (expr_type == TypeManager.byte_type)
-                                               return new IntConstant (~((ByteConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.sbyte_type)
-                                               return new IntConstant (~((SByteConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.short_type)
-                                               return new IntConstant (~((ShortConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.ushort_type)
-                                               return new IntConstant (~((UShortConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.char_type)
-                                               return new IntConstant (~((CharConstant)e).Value, e.Location);
-
-                                       // Predefined operators
-                                       if (expr_type == TypeManager.int32_type)
-                                               return new IntConstant (~((IntConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.uint32_type)
-                                               return new UIntConstant (~((UIntConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.int64_type)
-                                               return new LongConstant (~((LongConstant)e).Value, e.Location);
-                                       if (expr_type == TypeManager.uint64_type)
-                                               return new ULongConstant (~((UIntConstant)e).Value, e.Location);
-                                       if (e is EnumConstant) {
-                                               e = TryReduceConstant (ec, ((EnumConstant)e).Child);
-                                               if (e != null)
-                                                       e = new EnumConstant (e, expr_type);
-                                               return e;
+                                       if (Reduce (ec, enum_constant.Child, out reduced)){
+                                               result = new EnumConstant ((Constant) reduced, enum_constant.Type);
+                                               return true;
+                                       } else {
+                                               result = null;
+                                               return false;
                                        }
-                                       return null;
+                               }
 
-                               case Operator.AddressOf:
-                                       return e;
-                                       //return false;
+                               if (expr_type == TypeManager.int32_type){
+                                       result = new IntConstant (~ ((IntConstant) e).Value, e.Location);
+                               } else if (expr_type == TypeManager.uint32_type){
+                                       result = new UIntConstant (~ ((UIntConstant) e).Value, e.Location);
+                               } else if (expr_type == TypeManager.int64_type){
+                                       result = new LongConstant (~ ((LongConstant) e).Value, e.Location);
+                               } else if (expr_type == TypeManager.uint64_type){
+                                       result = new ULongConstant (~ ((ULongConstant) e).Value, e.Location);
+                               } else {
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
+                               return true;
 
-                               case Operator.Indirection:
-                                       return e;
-                                       //return false;
+                       case Operator.AddressOf:
+                               result = this;
+                               return false;
+
+                       case Operator.Indirection:
+                               result = this;
+                               return false;
                        }
                        throw new Exception ("Can not constant fold: " + Oper.ToString());
                }
@@ -360,21 +353,24 @@ namespace Mono.CSharp {
                        //
 
                        // Attempt to use a constant folding operation.
-                       Constant cexpr = Expr as Constant;
-                       if (cexpr != null) {
-                               cexpr = TryReduceConstant (ec, cexpr);
-                               if (cexpr != null) {
-                                       return cexpr;
-                               }
+                       if (Expr is Constant){
+                               Expression result;
+                               
+                               if (Reduce (ec, (Constant) Expr, out result))
+                                       return result;
                        }
 
                        //
                        // Step 2: Perform Operator Overload location
                        //
                        Type expr_type = Expr.Type;
-                       string op_name = oper_names [(int) Oper];
+                       Expression mg;
+                       string op_name;
+                       
+                       op_name = oper_names [(int) Oper];
 
-                       Expression mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+                       mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+                       
                        if (mg != null) {
                                Expression e = StaticCallExpr.MakeSimpleCall (
                                        ec, (MethodGroupExpr) mg, Expr, loc);
@@ -387,6 +383,12 @@ namespace Mono.CSharp {
                                return e;
                        }
 
+                       // Only perform numeric promotions on:
+                       // +, - 
+
+                       if (expr_type == null)
+                               return null;
+                       
                        switch (Oper){
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
@@ -401,31 +403,34 @@ namespace Mono.CSharp {
                                return this;
 
                        case Operator.OnesComplement:
-                               // Unary numeric promotions
-                               if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.char_type) 
-                               {
-                                       type = TypeManager.int32_type;
-                                       return new EmptyCast (this, type);
-                               }
-
-                               // Predefined operators
-                               if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
-                                       TypeManager.IsEnumType (expr_type))
-                               {
-                                       type = expr_type;
-                                       return this;
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+                                       Expression e;
+
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
+                                       if (e != null)
+                                               goto ok;
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint32_type, loc);
+                                       if (e != null)
+                                               goto ok;
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
+                                       if (e != null)
+                                               goto ok;
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint64_type, loc);
+                                       if (e != null)
+                                               goto ok;
+                                       Error23 (expr_type);
+                                       return null;
+                               ok:
+                                       Expr = e;
+                                       expr_type = e.Type;
                                }
 
-                               type = TypeManager.int32_type;
-                               Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
-                               if (Expr != null)
-                                       return this;
-
-                               Error23 (expr_type);
-                               return null;
+                               type = expr_type;
+                               return this;
 
                        case Operator.AddressOf:
                                if (!ec.InUnsafe) {
@@ -494,65 +499,91 @@ namespace Mono.CSharp {
                                return new Indirection (Expr, loc);
                        
                        case Operator.UnaryPlus:
-                               // Unary numeric promotions
-                               if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.char_type) 
-                               {
-                                       return new EmptyCast (Expr, TypeManager.int32_type);
-                               }
+                               //
+                               // A plus in front of something is just a no-op, so return the child.
+                               //
+                               return Expr;
 
-                               // Predefined operators
-                               if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
-                                       expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
-                                       expr_type == TypeManager.decimal_type)
-                               {
-                                       return Expr;
-                               }
+                       case Operator.UnaryNegation:
+                               //
+                               // Deals with -literals
+                               // int     operator- (int x)
+                               // long    operator- (long x)
+                               // float   operator- (float f)
+                               // double  operator- (double d)
+                               // decimal operator- (decimal d)
+                               //
+                               Expression expr = null;
 
-                               Expr = Convert.ImplicitUserConversion(ec, Expr, TypeManager.int32_type, loc);
-                               if (Expr != null) {
-                                        // Becausew we can completely ignore unary +
-                                       return Expr;
+                               //
+                               // transform - - expr into expr
+                               //
+                               if (Expr is Unary){
+                                       Unary unary = (Unary) Expr;
+                                       
+                                       if (unary.Oper == Operator.UnaryNegation)
+                                               return unary.Expr;
                                }
 
-                               Error23 (expr_type);
-                               return null;
-
-                       case Operator.UnaryNegation:
                                //
-                               // transform - - expr into expr
+                               // perform numeric promotions to int,
+                               // long, double.
+                               //
                                //
-                               Unary u = Expr as Unary;
-                               if (u != null && u.Oper == Operator.UnaryNegation) {
-                                       return u.Expr;
-                               }
-
-                               // Unary numeric promotions
-                               if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.char_type) 
-                               {
-                                       type = TypeManager.int32_type;
-                                       return new EmptyCast (this, type);
-                               }
-
-                               // Predefined operators
-                               if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.int64_type ||
-                                       expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
-                                       expr_type == TypeManager.decimal_type)
-                               {
+                               // The following is inneficient, because we call
+                               // ImplicitConversion too many times.
+                               //
+                               // It is also not clear if we should convert to Float
+                               // or Double initially.
+                               //
+                               if (expr_type == TypeManager.uint32_type){
+                                       //
+                                       // FIXME: handle exception to this rule that
+                                       // permits the int value -2147483648 (-2^31) to
+                                       // bt wrote as a decimal interger literal
+                                       //
+                                       type = TypeManager.int64_type;
+                                       Expr = Convert.ImplicitConversion (ec, Expr, type, loc);
+                                       return this;
+                               }
+
+                               if (expr_type == TypeManager.uint64_type){
+                                       //
+                                       // FIXME: Handle exception of `long value'
+                                       // -92233720368547758087 (-2^63) to be wrote as
+                                       // decimal integer literal.
+                                       //
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+
+                               if (expr_type == TypeManager.float_type){
                                        type = expr_type;
+                                       Expr = Convert.ImplicitConversion (ec, Expr, type, loc);
                                        return this;
                                }
+                               
+                               expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               } 
 
-                               type = TypeManager.int32_type;
-                               Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
-                               if (Expr != null)
+                               expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
                                        return this;
+                               }
 
+                               expr = Convert.ImplicitConversion (ec, Expr, TypeManager.double_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               }
+                               
                                Error23 (expr_type);
                                return null;
                        }
index eb06c1fffa353f7cb86e1f748d210ddb5cbaf807..8f4cb6e60d3ba67375602ff23ca5dc1265d3f5bf 100644 (file)
@@ -45,13 +45,12 @@ namespace Mono.CSharp {
        }
 
 
-       public class NullConstant : Constant
+       public abstract class NullConstant : Constant
        {
                public NullConstant (Location loc):
                        base (loc)
                {
                        eclass = ExprClass.Value;
-                       type = TypeManager.null_type;
                }
                
                override public string AsString ()
@@ -146,7 +145,7 @@ namespace Mono.CSharp {
                {
                        if (TypeManager.IsGenericParameter (t)) {
                                Report.Error(403, loc,
-                                       "Cannot convert null to the type parameter `{0}' because it could be a value " +
+                                       "Cannot convert null to the type parameter `{0}' becaues it could be a value " +
                                        "type. Consider using `default ({0})' instead", t.Name);
                        } else {
                                Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type",