2008-03-27 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / ecore.cs
index b71a823849ccf220c2415c6f585bb817729e3887..6beb5fab57d9b4711adb2684915f30f65b17a96f 100644 (file)
@@ -1321,6 +1321,21 @@ namespace Mono.CSharp {
                        if (c != null)
                                return new EmptyConstantCast (c, type);
 
+                       //
+                       // No double conversion required when wrapping nullable types
+                       //
+                       if (TypeManager.IsNullableType (type)) {
+                               EmptyCast empty_cast = child as EmptyCast;
+                               if (empty_cast != null) {
+                                       if (TypeManager.IsNullableTypeOf (empty_cast.type, type))
+                                               throw new InternalErrorException ("Missing nullable underlying type conversion {0} != {1}",
+                                                       TypeManager.CSharpName (empty_cast.type), TypeManager.CSharpName (type));
+
+                                       empty_cast.type = type;
+                                       return empty_cast;
+                               }
+                       }
+                       
                        return new EmptyCast (child, type);
                }
 
@@ -1996,8 +2011,8 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       // This has no expresion tree representation
-                       return this;
+                       // A cast has no expresion tree representation
+                       return child.CreateExpressionTree (ec);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -2056,6 +2071,114 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Castclass, type);
                }
        }
+
+       //
+       // Used when resolved expression has different representations for
+       // expression trees and emit phase
+       //
+       public class ReducedExpression : Expression
+       {
+               class ReducedConstantExpression : Constant
+               {
+                       readonly Constant expr;
+                       readonly Expression orig_expr;
+
+                       public ReducedConstantExpression (Constant expr, Expression orig_expr)
+                               : base (expr.Location)
+                       {
+                               this.expr = expr;
+                               this.orig_expr = orig_expr;
+                       }
+
+                       public override string AsString ()
+                       {
+                               return expr.AsString ();
+                       }
+
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               return orig_expr.CreateExpressionTree (ec);
+                       }
+
+                       public override object GetValue ()
+                       {
+                               return expr.GetValue ();
+                       }
+
+                       public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               eclass = expr.eclass;
+                               type = expr.Type;
+                               return this;
+                       }
+
+                       public override Constant Increment ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public override bool IsDefaultValue {
+                               get {
+                                       return expr.IsDefaultValue;
+                               }
+                       }
+
+                       public override bool IsNegative {
+                               get {
+                                       return expr.IsNegative;
+                               }
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               expr.Emit (ec);
+                       }
+               }
+
+               readonly Expression expr, orig_expr;
+
+               private ReducedExpression (Expression expr, Expression orig_expr)
+               {
+                       this.expr = expr;
+                       this.orig_expr = orig_expr;
+               }
+
+               public static Expression Create (Constant expr, Expression original_expr)
+               {
+                       return new ReducedConstantExpression (expr, original_expr);
+               }
+
+               public static Expression Create (Expression expr, Expression original_expr)
+               {
+                       Constant c = expr as Constant;
+                       if (c != null)
+                               return Create (c, original_expr);
+
+                       return new ReducedExpression (expr, original_expr);
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return orig_expr.CreateExpressionTree (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = expr.eclass;
+                       type = expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       expr.Emit (ec);
+               }
+       }
        
        /// <summary>
        ///   SimpleName expressions are formed of a single word and only happen at the beginning 
@@ -4157,7 +4280,7 @@ namespace Mono.CSharp {
                        // should be better than all the others
                        //
                        MethodBase ambiguous = null;
-                       for (int ix = 0; ix < candidate_top; ix++) {
+                       for (int ix = 1; ix < candidate_top; ix++) {
                                MethodBase candidate = (MethodBase) candidates [ix];
 
                                if (candidate == best_candidate)
@@ -4335,7 +4458,7 @@ namespace Mono.CSharp {
                        //
                        // Fill not provided arguments required by params modifier
                        //
-                       if (params_initializers == null && pd.HasParams && arg_count < pd.Count) {
+                       if (params_initializers == null && pd.HasParams && arg_count < pd.Count && a_idx + 1 == pd.Count) {
                                if (arguments == null)
                                        arguments = new ArrayList (1);
 
@@ -5053,7 +5176,7 @@ namespace Mono.CSharp {
                                Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
                                return;
                        }
-
+                       
                        StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
                        sig.Append ('.');
                        ParameterData iparams = TypeManager.GetParameterData (mi);
@@ -5077,7 +5200,12 @@ namespace Mono.CSharp {
 
                bool IsSingleDimensionalArrayLength ()
                {
-                       return DeclaringType == TypeManager.array_type && getter != null && getter.Name == "Length";
+                       if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length")
+                               return false;
+
+                       string t_name = InstanceExpression.Type.Name;
+                       int t_name_len = t_name.Length;
+                       return t_name_len > 2 && t_name [t_name_len - 2] == '[' && t_name [t_name_len - 3] != ']';
                }
 
                override public Expression DoResolve (EmitContext ec)