2008-03-27 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / ecore.cs
index 4d99f415c86fa30ce9ef16bb5a166016538865bb..6beb5fab57d9b4711adb2684915f30f65b17a96f 100644 (file)
@@ -165,8 +165,7 @@ namespace Mono.CSharp {
                                return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
                                        TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
 
-                       if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
-                                       TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
+                       if (TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) {
                                if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
                                        return true;
                        } else {
@@ -347,9 +346,9 @@ namespace Mono.CSharp {
 
                        if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) {
 #if GMCS_SOURCE
-                               string sig1 = Type.DeclaringMethod == null ?
-                                       TypeManager.CSharpName (Type.DeclaringType) :
-                                       TypeManager.CSharpSignature (Type.DeclaringMethod);
+                               string sig1 = type.DeclaringMethod == null ?
+                                       TypeManager.CSharpName (type.DeclaringType) :
+                                       TypeManager.CSharpSignature (type.DeclaringMethod);
                                string sig2 = target.DeclaringMethod == null ?
                                        TypeManager.CSharpName (target.DeclaringType) :
                                        TypeManager.CSharpSignature (target.DeclaringMethod);
@@ -888,6 +887,11 @@ namespace Mono.CSharp {
                        return new MethodGroupExpr (members, type, loc);
                }
 
+               protected virtual void Error_NegativeArrayIndex (Location loc)
+               {
+                       throw new NotImplementedException ();
+               }
+
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -909,12 +913,6 @@ namespace Mono.CSharp {
                static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
                        MethodGroupExpr operator_group;
-
-#if GMCS_SOURCE
-                       if (TypeManager.IsNullableType (e.Type))
-                               return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
-#endif
-
                        operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
                        if (operator_group == null)
                                return null;
@@ -922,12 +920,12 @@ namespace Mono.CSharp {
                        ArrayList arguments = new ArrayList (1);
                        arguments.Add (new Argument (e, Argument.AType.Expression));
                        operator_group = operator_group.OverloadResolve (
-                               ec, arguments, false, loc);
+                               ec, ref arguments, false, loc);
 
                        if (operator_group == null)
                                return null;
 
-                       return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc);
+                       return new UserOperatorCall (operator_group, arguments, null, loc);
                }
 
                /// <summary>
@@ -1079,7 +1077,7 @@ namespace Mono.CSharp {
                                if (t == TypeManager.enum_type)
                                        ig.Emit (OpCodes.Ldind_Ref);
                                else
-                                       LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
+                                       LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t));
                        } else if (t.IsValueType || TypeManager.IsGenericParameter (t))
                                ig.Emit (OpCodes.Ldobj, t);
                        else if (t.IsPointer)
@@ -1094,7 +1092,7 @@ namespace Mono.CSharp {
                public static void StoreFromPtr (ILGenerator ig, Type type)
                {
                        if (TypeManager.IsEnumType (type))
-                               type = TypeManager.EnumToUnderlying (type);
+                               type = TypeManager.GetEnumUnderlyingType (type);
                        if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
                                ig.Emit (OpCodes.Stind_I4);
                        else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
@@ -1145,11 +1143,6 @@ namespace Mono.CSharp {
                                return 0;
                }
 
-               public static void Error_NegativeArrayIndex (Location loc)
-               {
-                       Report.Error (248, loc, "Cannot create an array with a negative size");
-               }
-
                protected void Error_CannotCallAbstractBase (string name)
                {
                        Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
@@ -1170,21 +1163,21 @@ namespace Mono.CSharp {
                //
                // Converts `source' to an int, uint, long or ulong.
                //
-               public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
+               public Expression ConvertExpressionToArrayIndex (EmitContext ec, Expression source)
                {
-                       Expression target;
+                       Expression converted;
                        
                        using (ec.With (EmitContext.Flags.CheckState, true)) {
-                               target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
-                               if (target == null)
-                                       target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
-                               if (target == null)
-                                       target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
-                               if (target == null)
-                                       target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
-
-                               if (target == null) {
-                                       source.Error_ValueCannotBeConverted (ec, loc, TypeManager.int32_type, false);
+                               converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc);
+                               if (converted == null)
+                                       converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc);
+                               if (converted == null)
+                                       converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc);
+                               if (converted == null)
+                                       converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc);
+
+                               if (converted == null) {
+                                       source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false);
                                        return null;
                                }
                        }
@@ -1192,24 +1185,15 @@ namespace Mono.CSharp {
                        //
                        // Only positive constants are allowed at compile time
                        //
-                       if (target is Constant){
-                               if (target is IntConstant){
-                                       if (((IntConstant) target).Value < 0){
-                                               Error_NegativeArrayIndex (loc);
-                                               return null;
-                                       }
-                               }
-
-                               if (target is LongConstant){
-                                       if (((LongConstant) target).Value < 0){
-                                               Error_NegativeArrayIndex (loc);
-                                               return null;
-                                       }
+                       Constant c = converted as Constant;
+                       if (c != null) {
+                               if (c.IsNegative) {
+                                       Error_NegativeArrayIndex (source.loc);
                                }
-                               
+                               return c;
                        }
 
-                       return target;
+                       return new ArrayIndexCast (converted).Resolve (ec);
                }
 
                //
@@ -1244,6 +1228,36 @@ namespace Mono.CSharp {
 
                        return cloned;
                }
+
+               public virtual Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotImplementedException (
+                               "Expression tree conversion not implemented for " + GetType ());
+               }
+
+               protected Expression CreateExpressionFactoryCall (string name, ArrayList args)
+               {
+                       return CreateExpressionFactoryCall (name, null, args, loc);
+               }
+
+               protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args)
+               {
+                       return CreateExpressionFactoryCall (name, typeArguments, args, loc);
+               }
+
+               public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args, Location loc)
+               {
+                       TypeExpr texpr = TypeManager.expression_type_expr;
+                       if (texpr == null) {
+                               Type t = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression", Kind.Class, true);
+                               if (t == null)
+                                       return null;
+
+                               TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null);
+                       }
+
+                       return new Invocation (new MemberAccess (texpr, name, typeArguments, loc), args);
+               }
        }
 
        /// <summary>
@@ -1307,8 +1321,31 @@ 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);
-               }               
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (child.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args);
+               }
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -1370,7 +1407,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo oper in mi) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
-                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                               if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
                                        return oper;
                        }
 
@@ -1425,7 +1462,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo oper in mi) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
-                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                               if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
                                        return oper;
                        }
 
@@ -1468,7 +1505,7 @@ namespace Mono.CSharp {
                                foreach (MethodInfo oper in all_oper) {
                                        ParameterData pd = TypeManager.GetParameterData (oper);
                                        if (pd.ParameterType (0) == TypeManager.decimal_type)
-                                               operators.Add (oper.ReturnType, oper);
+                                               operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper);
                                }
                        }
 
@@ -1972,6 +2009,12 @@ namespace Mono.CSharp {
                        second_valid = true;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       // A cast has no expresion tree representation
+                       return child.CreateExpressionTree (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        // This should never be invoked, we are born in fully
@@ -1987,7 +2030,11 @@ namespace Mono.CSharp {
 
                        if (second_valid)
                                ec.ig.Emit (op2);
-               }                       
+               }
+
+               public Type UnderlyingType {
+                       get { return child.Type; }
+               }
        }
 
        /// <summary>
@@ -2024,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 
@@ -2433,7 +2588,7 @@ namespace Mono.CSharp {
                                                if (!me.IsStatic &&
                                                    (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
                                                        Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
-                                                       return EmptyExpression.Null;
+                                                       return null;
                                                }
 
                                                //
@@ -2544,9 +2699,9 @@ namespace Mono.CSharp {
                        return ds.CheckAccessLevel (Type);
                }
 
-               public virtual bool AsAccessible (DeclSpace ds, int flags)
+               public virtual bool AsAccessible (DeclSpace ds)
                {
-                       return ds.AsAccessible (Type, flags);
+                       return ds.IsAccessibleAs (Type);
                }
 
                public virtual bool IsClass {
@@ -2890,9 +3045,9 @@ namespace Mono.CSharp {
                        return texpr.CheckAccessLevel (ds);
                }
 
-               public override bool AsAccessible (DeclSpace ds, int flags)
+               public override bool AsAccessible (DeclSpace ds)
                {
-                       return texpr.AsAccessible (ds, flags);
+                       return texpr.AsAccessible (ds);
                }
 
                public override bool IsClass {
@@ -3081,11 +3236,8 @@ namespace Mono.CSharp {
                        base.EmitCall (ec, arguments);
                }
 
-               public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc)
+               public override MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList arguments, bool may_fail, Location loc)
                {
-                       if ((ExtensionExpression.eclass & (ExprClass.Value | ExprClass.Variable)) == 0)
-                               return base.OverloadResolve (ec, arguments, may_fail, loc);
-
                        if (arguments == null)
                                arguments = new ArrayList (1);
 
@@ -3103,7 +3255,7 @@ namespace Mono.CSharp {
                MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
                {
                        // Use normal resolve rules
-                       MethodGroupExpr mg = base.OverloadResolve (ec, arguments, ns != null, loc);
+                       MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
                        if (mg != null)
                                return mg;
 
@@ -3113,7 +3265,7 @@ namespace Mono.CSharp {
                        // Search continues
                        ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name);
                        if (e == null)
-                               return base.OverloadResolve (ec, arguments, false, loc);
+                               return base.OverloadResolve (ec, ref arguments, false, loc);
 
                        e.ExtensionExpression = ExtensionExpression;
                        return e.ResolveOverloadExtensions (ec, arguments, e.namespace_entry, loc);
@@ -3247,57 +3399,77 @@ namespace Mono.CSharp {
                        return (MethodInfo)mg.best_candidate;
                }
 
-               /// <summary>
-               ///   Determines "better conversion" as specified in 14.4.2.3
-               ///
-               ///    Returns : p    if a->p is better,
-               ///              q    if a->q is better,
-               ///              null if neither is better
-               /// </summary>
-               static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q)
+               //
+               //  7.4.3.3  Better conversion from expression
+               //  Returns :   1    if a->p is better,
+               //              2    if a->q is better,
+               //              0 if neither is better
+               //
+               static int BetterExpressionConversion (EmitContext ec, Argument a, Type p, Type q)
                {
                        Type argument_type = TypeManager.TypeToCoreType (a.Type);
-                       Expression argument_expr = a.Expr;
+                       if (argument_type == TypeManager.anonymous_method_type && RootContext.Version > LanguageVersion.ISO_2) {
+                               //
+                               // Uwrap delegate from Expression<T>
+                               //
+                               if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) {
+                                       p = TypeManager.GetTypeArguments (p) [0];
+                                       q = TypeManager.GetTypeArguments (q) [0];
+                               }
+                               p = Delegate.GetInvokeMethod (null, p).ReturnType;
+                               q = Delegate.GetInvokeMethod (null, q).ReturnType;
+                       } else {
+                               if (argument_type == p)
+                                       return 1;
 
-                       if (argument_type == null)
-                               throw new Exception ("Expression of type " + a.Expr +
-                                       " does not resolve its type");
+                               if (argument_type == q)
+                                       return 2;
+                       }
 
-                       if (p == null || q == null)
-                               throw new InternalErrorException ("BetterConversion Got a null conversion");
+                       return BetterTypeConversion (ec, p, q);
+               }
 
-                       if (p == q)
-                               return null;
+               //
+               // 7.4.3.4  Better conversion from type
+               //
+               public static int BetterTypeConversion (EmitContext ec, Type p, Type q)
+               {
+                       if (p == null || q == null)
+                               throw new InternalErrorException ("BetterTypeConversion got a null conversion");
 
-                       if (argument_expr is NullLiteral) 
-                       {
-                               //
-                               // If the argument is null and one of the types to compare is 'object' and
-                               // the other is a reference type, we prefer the other.
-                               //
-                               // This follows from the usual rules:
-                               //   * There is an implicit conversion from 'null' to type 'object'
-                               //   * There is an implicit conversion from 'null' to any reference type
-                               //   * There is an implicit conversion from any reference type to type 'object'
-                               //   * There is no implicit conversion from type 'object' to other reference types
-                               //  => Conversion of 'null' to a reference type is better than conversion to 'object'
-                               //
-                               //  FIXME: This probably isn't necessary, since the type of a NullLiteral is the 
-                               //         null type. I think it used to be 'object' and thus needed a special 
-                               //         case to avoid the immediately following two checks.
-                               //
-                               if (!p.IsValueType && q == TypeManager.object_type)
-                                       return p;
-                               if (!q.IsValueType && p == TypeManager.object_type)
-                                       return q;
+                       if (p == TypeManager.int32_type) {
+                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.int64_type) {
+                               if (q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.sbyte_type) {
+                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
+                                       q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.short_type) {
+                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
+                                       q == TypeManager.uint64_type)
+                                       return 1;
                        }
-                                
-                       if (argument_type == p)
-                               return p;
 
-                       if (argument_type == q)
-                               return q;
+                       if (q == TypeManager.int32_type) {
+                               if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return 2;
+                       } if (q == TypeManager.int64_type) {
+                               if (p == TypeManager.uint64_type)
+                                       return 2;
+                       } else if (q == TypeManager.sbyte_type) {
+                               if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+                                       p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return 2;
+                       } if (q == TypeManager.short_type) {
+                               if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
+                                       p == TypeManager.uint64_type)
+                                       return 2;
+                       }
 
+                       // TODO: this is expensive
                        Expression p_tmp = new EmptyExpression (p);
                        Expression q_tmp = new EmptyExpression (q);
 
@@ -3305,44 +3477,12 @@ namespace Mono.CSharp {
                        bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
 
                        if (p_to_q && !q_to_p)
-                               return p;
+                               return 1;
 
                        if (q_to_p && !p_to_q)
-                               return q;
-
-                       if (p == TypeManager.sbyte_type)
-                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
-                                       q == TypeManager.uint32_type || q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.sbyte_type)
-                               if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
-                                       p == TypeManager.uint32_type || p == TypeManager.uint64_type)
-                                       return q;
-
-                       if (p == TypeManager.short_type)
-                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
-                                       q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.short_type)
-                               if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
-                                       p == TypeManager.uint64_type)
-                                       return q;
-
-                       if (p == TypeManager.int32_type)
-                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.int32_type)
-                               if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
-                                       return q;
-
-                       if (p == TypeManager.int64_type)
-                               if (q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.int64_type)
-                               if (p == TypeManager.uint64_type)
-                                       return q;
+                               return 2;
 
-                       return null;
+                       return 0;
                }
 
                /// <summary>
@@ -3386,16 +3526,16 @@ namespace Mono.CSharp {
                                        continue;
 
                                same = false;
-                               Type better = BetterConversion (ec, a, ct, bt);
+                               int result = BetterExpressionConversion (ec, a, ct, bt);
 
                                // for each argument, the conversion to 'ct' should be no worse than 
                                // the conversion to 'bt'.
-                               if (better == bt)
+                               if (result == 2)
                                        return false;
 
                                // for at least one argument, the conversion to 'ct' should be better than 
                                // the conversion to 'bt'.
-                               if (better == ct)
+                               if (result != 0)
                                        better_at_least_one = true;
                        }
 
@@ -3498,6 +3638,12 @@ namespace Mono.CSharp {
 
                        return base.ResolveMemberAccess (ec, left, loc, original);
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return new Cast (new TypeExpression (typeof (MethodInfo), loc),
+                               new TypeOfMethod ((MethodInfo)best_candidate, loc));
+               }
                
                override public Expression DoResolve (EmitContext ec)
                {
@@ -3523,7 +3669,7 @@ namespace Mono.CSharp {
                
                public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
                {
-                       Invocation.EmitArguments (ec, best_candidate, arguments, false, null);  
+                       Invocation.EmitArguments (ec, arguments, false, null);  
                }
                
                public virtual void EmitCall (EmitContext ec, ArrayList arguments)
@@ -3554,16 +3700,16 @@ namespace Mono.CSharp {
                        Parameter.Modifier mod = expected_par.ParameterModifier (idx);
 
                        string index = (idx + 1).ToString ();
-                       if ((mod & Parameter.Modifier.ISBYREF) != (a.Modifier & Parameter.Modifier.ISBYREF) ||
-                               (mod & Parameter.Modifier.ISBYREF) != 0) {
-                               if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0)
+                       if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
+                               (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
+                               if ((mod & Parameter.Modifier.ISBYREF) == 0)
                                        Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword",
                                                index, Parameter.GetModifierSignature (a.Modifier));
                                else
                                        Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
                                                index, Parameter.GetModifierSignature (mod));
                        } else {
-                               string p1 = Argument.FullDesc (a);
+                               string p1 = a.GetSignatureForError ();
                                string p2 = TypeManager.CSharpName (paramType);
 
                                if (p1 == p2) {
@@ -3628,7 +3774,8 @@ namespace Mono.CSharp {
                                                return score - 20000;
 
                                        if (TypeManager.IsGenericMethodDefinition (candidate))
-                                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
+                                               throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution",
+                                                       TypeManager.CSharpSignature (candidate));
 
                                        pd = TypeManager.GetParameterData (candidate);
                                }
@@ -3641,6 +3788,7 @@ namespace Mono.CSharp {
                        //
                        // 2. Each argument has to be implicitly convertible to method parameter
                        //
+                       method = candidate;
                        Parameter.Modifier p_mod = 0;
                        Type pt = null;
                        for (int i = 0; i < arg_count; i++) {
@@ -3674,14 +3822,16 @@ namespace Mono.CSharp {
                                                params_expanded_form = true;
                                }
 
-                               if (score != 0)
+                               if (score != 0) {
+                                       if (params_expanded_form)
+                                               ++score;
                                        return (arg_count - i) * 2 + score;
+                               }
                        }
                        
                        if (arg_count != param_count)
                                params_expanded_form = true;                    
                        
-                       method = candidate;                     
                        return 0;
                }
 
@@ -3852,7 +4002,7 @@ namespace Mono.CSharp {
                ///            that is the best match of me on Arguments.
                ///
                /// </summary>
-               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments,
+               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList Arguments,
                        bool may_fail, Location loc)
                {
                        bool method_params = false;
@@ -3980,7 +4130,7 @@ namespace Mono.CSharp {
                                        if (ex_method_lookup != null) {
                                                ex_method_lookup.ExtensionExpression = InstanceExpression;
                                                ex_method_lookup.SetTypeArguments (type_arguments);
-                                               return ex_method_lookup.OverloadResolve (ec, Arguments, may_fail, loc);
+                                               return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
                                        }
                                }
                                
@@ -4000,7 +4150,7 @@ namespace Mono.CSharp {
                                        ParameterData pd = TypeManager.GetParameterData (best_candidate);
                                        bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
                                        if (arg_count == pd.Count || pd.HasParams) {
-                                               if (TypeManager.IsGenericMethod (best_candidate)) {
+                                               if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
                                                        if (type_arguments == null) {
                                                                Report.Error (411, loc,
                                                                        "The type arguments for method `{0}' cannot be inferred from " +
@@ -4018,15 +4168,14 @@ namespace Mono.CSharp {
                                                                return null;
                                                        }
                                                } else {
-                                                       if (type_arguments != null) {
+                                                       if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
                                                                Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
                                                                return null;
                                                        }
                                                }
                                                
-                                               if (VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
-                                                       throw new InternalErrorException ("Overload verification expected failure");
-                                               return null;
+                                               if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
+                                                       return null;
                                        }
                                }
 
@@ -4108,7 +4257,9 @@ namespace Mono.CSharp {
                        //
 
                        best_candidate = (MethodBase) candidates [0];
-                       method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+                       if (delegate_type == null)
+                               method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+
                        for (int ix = 1; ix < candidate_top; ix++) {
                                MethodBase candidate = (MethodBase) candidates [ix];
 
@@ -4129,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)
@@ -4199,7 +4350,7 @@ namespace Mono.CSharp {
                        // necessary etc. and return if everything is
                        // all right
                        //
-                       if (!VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate,
+                       if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate,
                                method_params, may_fail, loc))
                                return null;
 
@@ -4225,7 +4376,7 @@ namespace Mono.CSharp {
                        type_arguments = ta;
                }
 
-               public bool VerifyArgumentsCompat (EmitContext ec, ArrayList arguments,
+               public bool VerifyArgumentsCompat (EmitContext ec, ref ArrayList arguments,
                                                          int arg_count, MethodBase method,
                                                          bool chose_params_expanded,
                                                          bool may_fail, Location loc)
@@ -4235,9 +4386,11 @@ namespace Mono.CSharp {
                        int errors = Report.Errors;
                        Parameter.Modifier p_mod = 0;
                        Type pt = null;
-                       int a_idx = 0;
+                       int a_idx = 0, a_pos = 0;
                        Argument a = null;
-                       for (; a_idx < arg_count; a_idx++) {
+                       ArrayList params_initializers = null;
+
+                       for (; a_idx < arg_count; a_idx++, ++a_pos) {
                                a = (Argument) arguments [a_idx];
                                if (p_mod != Parameter.Modifier.PARAMS) {
                                        p_mod = pd.ParameterModifier (a_idx);
@@ -4257,8 +4410,10 @@ namespace Mono.CSharp {
                                        }
 
                                        if (p_mod == Parameter.Modifier.PARAMS) {
-                                               if (chose_params_expanded)
+                                               if (chose_params_expanded) {
+                                                       params_initializers = new ArrayList (arg_count - a_idx);
                                                        pt = TypeManager.GetElementType (pt);
+                                               }
                                        } else if (p_mod != 0) {
                                                pt = TypeManager.GetElementType (pt);
                                        }
@@ -4277,25 +4432,59 @@ namespace Mono.CSharp {
                                        continue;
                                }
                
-                               if (TypeManager.IsEqual (a.Type, pt))
+                               Expression conv;
+                               if (TypeManager.IsEqual (a.Type, pt)) {
+                                       conv = a.Expr;
+                               } else {
+                                       conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
+                                       if (conv == null)
+                                               break;
+                               }
+
+                               //
+                               // Convert params arguments to an array initializer
+                               //
+                               if (params_initializers != null) {
+                                       params_initializers.Add (conv);
+                                       arguments.RemoveAt (a_idx--);
+                                       --arg_count;
                                        continue;
+                               }
                                
-                               Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
-                               if (conv == null)
-                                       break;
-
-                               if (!chose_params_expanded && (p_mod & Parameter.Modifier.PARAMS) != 0 && a.Type == TypeManager.null_type)
-                                       conv.Type = pd.ParameterType (a_idx);
-
                                // Update the argument with the implicit conversion
                                a.Expr = conv;
                        }
 
-                       if (a_idx == arg_count)
+                       //
+                       // Fill not provided arguments required by params modifier
+                       //
+                       if (params_initializers == null && pd.HasParams && arg_count < pd.Count && a_idx + 1 == pd.Count) {
+                               if (arguments == null)
+                                       arguments = new ArrayList (1);
+
+                               pt = pd.Types [GetApplicableParametersCount (method, pd) - 1];
+                               pt = TypeManager.GetElementType (pt);
+                               params_initializers = new ArrayList (0);
+                       }
+
+                       if (a_idx == arg_count) {
+                               //
+                               // Append an array argument with all params arguments
+                               //
+                               if (params_initializers != null) {
+                                       arguments.Add (new Argument (
+                                               new ArrayCreation (new TypeExpression (pt, loc), "[]",
+                                               params_initializers, loc).Resolve (ec)));
+                               }
                                return true;
+                       }
 
-                       if (!may_fail && Report.Errors == errors)
-                               Error_InvalidArguments (ec, loc, a_idx, method, a, pd, pt);
+                       if (!may_fail && Report.Errors == errors) {
+                               if (CustomErrorHandler != null)
+                                       CustomErrorHandler.NoExactMatch (ec, best_candidate);
+                               else
+                                       Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
+                       }
                        return false;
                }
        }
@@ -4614,7 +4803,7 @@ namespace Mono.CSharp {
                        }
 
                        if (right_side == EmptyExpression.OutAccess &&
-                           !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                           !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
                                Report.SymbolRelatedToPreviousError (DeclaringType);
                                Report.Warning (197, 1, loc,
                                                "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
@@ -4626,7 +4815,7 @@ namespace Mono.CSharp {
 
                public override void CheckMarshalByRefAccess (EmitContext ec)
                {
-                       if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                       if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
                                Report.SymbolRelatedToPreviousError (DeclaringType);
                                Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
                                                GetSignatureForError ());
@@ -4857,7 +5046,23 @@ namespace Mono.CSharp {
                                return is_static;
                        }
                }
-               
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       if (IsSingleDimensionalArrayLength ()) {
+                               ArrayList args = new ArrayList (1);
+                               args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+                               return CreateExpressionFactoryCall ("ArrayLength", args);
+                       }
+
+                       // TODO: it's waiting for PropertyExpr refactoring
+                       //ArrayList args = new ArrayList (2);
+                       //args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+                       //args.Add (getter expression);
+                       //return CreateExpressionFactoryCall ("Property", args);
+                       return base.CreateExpressionTree (ec);
+               }
+
                public override Type DeclaringType {
                        get {
                                return PropertyInfo.DeclaringType;
@@ -4971,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);
@@ -4993,6 +5198,16 @@ namespace Mono.CSharp {
                        return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy);
                }
 
+               bool IsSingleDimensionalArrayLength ()
+               {
+                       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)
                {
                        if (resolved)
@@ -5134,21 +5349,12 @@ namespace Mono.CSharp {
                        //
                        // Special case: length of single dimension array property is turned into ldlen
                        //
-                       if ((getter == TypeManager.system_int_array_get_length) ||
-                           (getter == TypeManager.int_array_get_length)){
-                               Type iet = InstanceExpression.Type;
-
-                               //
-                               // System.Array.Length can be called, but the Type does not
-                               // support invoking GetArrayRank, so test for that case first
-                               //
-                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
-                                       if (!prepared)
-                                               EmitInstance (ec, false);
-                                       ec.ig.Emit (OpCodes.Ldlen);
-                                       ec.ig.Emit (OpCodes.Conv_I4);
-                                       return;
-                               }
+                       if (IsSingleDimensionalArrayLength ()) {
+                               if (!prepared)
+                                       EmitInstance (ec, false);
+                               ec.ig.Emit (OpCodes.Ldlen);
+                               ec.ig.Emit (OpCodes.Conv_I4);
+                               return;
                        }
 
                        Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
@@ -5322,7 +5528,7 @@ namespace Mono.CSharp {
                        //
                        if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
                            InstanceExpression.Type != ec.ContainerType &&
-                           ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
+                           TypeManager.IsSubclassOf (ec.ContainerType, InstanceExpression.Type)) {
                                Report.SymbolRelatedToPreviousError (EventInfo);
                                ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
                                return false;