2010-06-18 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / expression.cs
index 25a1c5a32fdd1758843358c324cec8355ce5a6bd..c537b1421892eb9be2d178fe5aa698dde7d8391b 100644 (file)
 
 namespace Mono.CSharp {
        using System;
-       using System.Collections;
        using System.Collections.Generic;
        using System.Reflection;
        using System.Reflection.Emit;
        using System.Text;
-
-#if NET_4_0
        using System.Linq;
        using SLE = System.Linq.Expressions;
-#endif
 
        //
        // This is an user operator expression, automatically created during
@@ -40,7 +36,7 @@ namespace Mono.CSharp {
                        this.arguments = args;
                        this.expr_tree = expr_tree;
 
-                       type = TypeManager.TypeToCoreType (((MethodInfo) mg).ReturnType);
+                       type = mg.BestCandidate.ReturnType;
                        eclass = ExprClass.Value;
                        this.loc = loc;
                }
@@ -62,7 +58,7 @@ namespace Mono.CSharp {
                        // Nothing to clone
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        //
                        // We are born fully resolved
@@ -75,22 +71,15 @@ namespace Mono.CSharp {
                        mg.EmitCall (ec, arguments);
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       return SLE.Expression.Call ((MethodInfo) mg, Arguments.MakeExpression (arguments, ctx));
+                       var method = mg.BestCandidate.GetMetaInfo () as MethodInfo;
+                       return SLE.Expression.Call (method, Arguments.MakeExpression (arguments, ctx));
                }
-#endif
 
                public MethodGroupExpr Method {
                        get { return mg; }
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       arguments.MutateHoistedGenericType (storey);
-                       mg.MutateHoistedGenericType (storey);
-               }
        }
 
        public class ParenthesizedExpression : ShimExpression
@@ -101,7 +90,7 @@ namespace Mono.CSharp {
                        loc = expr.Location;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        return expr.Resolve (ec);
                }
@@ -122,17 +111,17 @@ namespace Mono.CSharp {
                        AddressOf,  TOP
                }
 
-               static Type [] [] predefined_operators;
+               static TypeSpec[][] predefined_operators;
 
                public readonly Operator Oper;
                public Expression Expr;
                Expression enum_conversion;
 
-               public Unary (Operator op, Expression expr)
+               public Unary (Operator op, Expression expr, Location loc)
                {
                        Oper = op;
                        Expr = expr;
-                       loc = expr.Location;
+                       this.loc = loc;
                }
 
                // <summary>
@@ -149,7 +138,7 @@ namespace Mono.CSharp {
                                return r == null ? null : new SideEffectConstant (r, e, r.Location);
                        }
 
-                       Type expr_type = e.Type;
+                       TypeSpec expr_type = e.Type;
                        
                        switch (Oper){
                        case Operator.UnaryPlus:
@@ -215,7 +204,7 @@ namespace Mono.CSharp {
                                if (expr_type == TypeManager.uint32_type) {
                                        UIntLiteral uil = e as UIntLiteral;
                                        if (uil != null) {
-                                               if (uil.Value == 2147483648)
+                                               if (uil.Value == int.MaxValue + (uint) 1)
                                                        return new IntLiteral (int.MinValue, e.Location);
                                                return new LongLiteral (-uil.Value, e.Location);
                                        }
@@ -298,7 +287,7 @@ namespace Mono.CSharp {
                        if (predefined_operators == null)
                                CreatePredefinedOperatorsTable ();
 
-                       Type expr_type = expr.Type;
+                       TypeSpec expr_type = expr.Type;
                        Expression best_expr;
 
                        //
@@ -325,7 +314,7 @@ namespace Mono.CSharp {
 
                protected virtual Expression ResolveEnumOperator (ResolveContext ec, Expression expr)
                {
-                       Type underlying_type = TypeManager.GetEnumUnderlyingType (expr.Type);
+                       TypeSpec underlying_type = EnumSpec.GetUnderlyingType (expr.Type);
                        Expression best_expr = ResolvePrimitivePredefinedType (EmptyCast.Create (expr, underlying_type));
                        if (best_expr == null)
                                return null;
@@ -374,12 +363,12 @@ namespace Mono.CSharp {
 
                static void CreatePredefinedOperatorsTable ()
                {
-                       predefined_operators = new Type [(int) Operator.TOP] [];
+                       predefined_operators = new TypeSpec [(int) Operator.TOP] [];
 
                        //
                        // 7.6.1 Unary plus operator
                        //
-                       predefined_operators [(int) Operator.UnaryPlus] = new Type [] {
+                       predefined_operators [(int) Operator.UnaryPlus] = new TypeSpec [] {
                                TypeManager.int32_type, TypeManager.uint32_type,
                                TypeManager.int64_type, TypeManager.uint64_type,
                                TypeManager.float_type, TypeManager.double_type,
@@ -389,7 +378,7 @@ namespace Mono.CSharp {
                        //
                        // 7.6.2 Unary minus operator
                        //
-                       predefined_operators [(int) Operator.UnaryNegation] = new Type [] {
+                       predefined_operators [(int) Operator.UnaryNegation] = new TypeSpec [] {
                                TypeManager.int32_type, 
                                TypeManager.int64_type,
                                TypeManager.float_type, TypeManager.double_type,
@@ -399,14 +388,14 @@ namespace Mono.CSharp {
                        //
                        // 7.6.3 Logical negation operator
                        //
-                       predefined_operators [(int) Operator.LogicalNot] = new Type [] {
+                       predefined_operators [(int) Operator.LogicalNot] = new TypeSpec [] {
                                TypeManager.bool_type
                        };
 
                        //
                        // 7.6.4 Bitwise complement operator
                        //
-                       predefined_operators [(int) Operator.OnesComplement] = new Type [] {
+                       predefined_operators [(int) Operator.OnesComplement] = new TypeSpec [] {
                                TypeManager.int32_type, TypeManager.uint32_type,
                                TypeManager.int64_type, TypeManager.uint64_type
                        };
@@ -417,7 +406,7 @@ namespace Mono.CSharp {
                //
                static Expression DoNumericPromotion (Operator op, Expression expr)
                {
-                       Type expr_type = expr.Type;
+                       TypeSpec expr_type = expr.Type;
                        if ((op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) &&
                                expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
                                expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
@@ -430,7 +419,7 @@ namespace Mono.CSharp {
                        return expr;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (Oper == Operator.AddressOf) {
                                return ResolveAddressOf (ec);
@@ -440,14 +429,14 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
-                       if (TypeManager.IsDynamicType (Expr.Type)) {
+                       if (Expr.Type == InternalType.Dynamic) {
                                Arguments args = new Arguments (1);
                                args.Add (new Argument (Expr));
                                return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).Resolve (ec);
                        }
 
                        if (TypeManager.IsNullableType (Expr.Type))
-                               return new Nullable.LiftedUnaryOperator (Oper, Expr).Resolve (ec);
+                               return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
 
                        //
                        // Attempt to use a constant folding operation.
@@ -456,7 +445,7 @@ namespace Mono.CSharp {
                        if (cexpr != null) {
                                cexpr = TryReduceConstant (ec, cexpr);
                                if (cexpr != null)
-                                       return cexpr;
+                                       return cexpr.Resolve (ec);
                        }
 
                        Expression expr = ResolveOperator (ec, Expr);
@@ -482,10 +471,8 @@ namespace Mono.CSharp {
                        EmitOperator (ec, type);
                }
 
-               protected void EmitOperator (EmitContext ec, Type type)
+               protected void EmitOperator (EmitContext ec, TypeSpec type)
                {
-                       ILGenerator ig = ec.ig;
-
                        switch (Oper) {
                        case Operator.UnaryPlus:
                                Expr.Emit (ec);
@@ -493,27 +480,27 @@ namespace Mono.CSharp {
                                
                        case Operator.UnaryNegation:
                                if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) {
-                                       ig.Emit (OpCodes.Ldc_I4_0);
+                                       ec.Emit (OpCodes.Ldc_I4_0);
                                        if (type == TypeManager.int64_type)
-                                               ig.Emit (OpCodes.Conv_U8);
+                                               ec.Emit (OpCodes.Conv_U8);
                                        Expr.Emit (ec);
-                                       ig.Emit (OpCodes.Sub_Ovf);
+                                       ec.Emit (OpCodes.Sub_Ovf);
                                } else {
                                        Expr.Emit (ec);
-                                       ig.Emit (OpCodes.Neg);
+                                       ec.Emit (OpCodes.Neg);
                                }
                                
                                break;
                                
                        case Operator.LogicalNot:
                                Expr.Emit (ec);
-                               ig.Emit (OpCodes.Ldc_I4_0);
-                               ig.Emit (OpCodes.Ceq);
+                               ec.Emit (OpCodes.Ldc_I4_0);
+                               ec.Emit (OpCodes.Ceq);
                                break;
                                
                        case Operator.OnesComplement:
                                Expr.Emit (ec);
-                               ig.Emit (OpCodes.Not);
+                               ec.Emit (OpCodes.Not);
                                break;
                                
                        case Operator.AddressOf:
@@ -545,7 +532,7 @@ namespace Mono.CSharp {
                        Expr.EmitSideEffect (ec);
                }
 
-               public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, Type t)
+               public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, TypeSpec t)
                {
                        ec.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
                                oper, TypeManager.CSharpName (t));
@@ -570,7 +557,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               static bool IsFloat (Type t)
+               static bool IsFloat (TypeSpec t)
                {
                        return t == TypeManager.float_type || t == TypeManager.double_type;
                }
@@ -596,7 +583,6 @@ namespace Mono.CSharp {
                        throw new NotImplementedException (oper.ToString ());
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        var expr = Expr.MakeExpression (ctx);
@@ -607,18 +593,18 @@ namespace Mono.CSharp {
                                return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr);
                        case Operator.LogicalNot:
                                return SLE.Expression.Not (expr);
+#if NET_4_0
                        case Operator.OnesComplement:
                                return SLE.Expression.OnesComplement (expr);
+#endif
                        default:
                                throw new NotImplementedException (Oper.ToString ());
                        }
                }
-#endif
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               public static void Reset ()
                {
-                       type = storey.MutateType (type);
-                       Expr.MutateHoistedGenericType (storey);
+                       predefined_operators = null;
                }
 
                Expression ResolveAddressOf (ResolveContext ec)
@@ -632,7 +618,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (!TypeManager.VerifyUnManaged (Expr.Type, loc)) {
+                       if (!TypeManager.VerifyUnmanaged (ec.Compiler, Expr.Type, loc)) {
                                return null;
                        }
 
@@ -665,7 +651,7 @@ namespace Mono.CSharp {
                                ec.Report.Error (212, loc, "You can only take the address of unfixed expression inside of a fixed statement initializer");
                        }
 
-                       type = TypeManager.GetPointerType (Expr.Type);
+                       type = PointerContainer.MakeType (Expr.Type);
                        eclass = ExprClass.Value;
                        return this;
                }
@@ -673,9 +659,9 @@ namespace Mono.CSharp {
                Expression ResolvePrimitivePredefinedType (Expression expr)
                {
                        expr = DoNumericPromotion (Oper, expr);
-                       Type expr_type = expr.Type;
-                       Type[] predefined = predefined_operators [(int) Oper];
-                       foreach (Type t in predefined) {
+                       TypeSpec expr_type = expr.Type;
+                       TypeSpec[] predefined = predefined_operators [(int) Oper];
+                       foreach (TypeSpec t in predefined) {
                                if (t == expr_type)
                                        return expr;
                        }
@@ -702,7 +688,7 @@ namespace Mono.CSharp {
                        }
 
                        string op_name = CSharp.Operator.GetMetadataName (op_type);
-                       MethodGroupExpr user_op = MemberLookup (ec.Compiler, ec.CurrentType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr;
+                       MethodGroupExpr user_op = MethodLookup (ec.Compiler, ec.CurrentType, expr.Type, MemberKind.Operator, op_name, 0, expr.Location);
                        if (user_op == null)
                                return null;
 
@@ -726,9 +712,9 @@ namespace Mono.CSharp {
                        if (best_expr != null)
                                return best_expr;
 
-                       Type[] predefined = predefined_operators [(int) Oper];
-                       foreach (Type t in predefined) {
-                               Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false, false);
+                       TypeSpec[] predefined = predefined_operators [(int) Oper];
+                       foreach (TypeSpec t in predefined) {
+                               Expression oper_expr = Convert.ImplicitUserConversion (ec, expr, t, expr.Location);
                                if (oper_expr == null)
                                        continue;
 
@@ -814,14 +800,14 @@ namespace Mono.CSharp {
                        if (!prepared)
                                expr.Emit (ec);
                        
-                       LoadFromPtr (ec.ig, Type);
+                       ec.EmitLoadFromPtr (Type);
                }
 
                public void Emit (EmitContext ec, bool leave_copy)
                {
                        Emit (ec);
                        if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                                temporary = new LocalTemporary (expr.Type);
                                temporary.Store (ec);
                        }
@@ -834,16 +820,16 @@ namespace Mono.CSharp {
                        expr.Emit (ec);
 
                        if (prepare_for_load)
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                        
                        source.Emit (ec);
                        if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                                temporary = new LocalTemporary (expr.Type);
                                temporary.Store (ec);
                        }
                        
-                       StoreFromPtr (ec.ig, type);
+                       ec.EmitStoreFromPtr (type);
                        
                        if (temporary != null) {
                                temporary.Emit (ec);
@@ -861,7 +847,7 @@ namespace Mono.CSharp {
                        return DoResolve (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
@@ -928,7 +914,7 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ("ET");
                        }
 
-                       public override Expression DoResolve (ResolveContext rc)
+                       protected override Expression DoResolve (ResolveContext rc)
                        {
                                eclass = expr.eclass;
                                return this;
@@ -993,10 +979,10 @@ namespace Mono.CSharp {
                // Holds the real operation
                Expression operation;
 
-               public UnaryMutator (Mode m, Expression e)
+               public UnaryMutator (Mode m, Expression e, Location loc)
                {
                        mode = m;
-                       loc = e.Location;
+                       this.loc = loc;
                        expr = e;
                }
 
@@ -1005,14 +991,14 @@ namespace Mono.CSharp {
                        return new SimpleAssign (this, this).CreateExpressionTree (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
                        
                        if (expr == null)
                                return null;
 
-                       if (TypeManager.IsDynamicType (expr.Type)) {
+                       if (expr.Type == InternalType.Dynamic) {
                                //
                                // Handle postfix unary operators using local
                                // temporary variable
@@ -1082,7 +1068,7 @@ namespace Mono.CSharp {
                //   use pre-post incr-decr operations on it, but it is not a
                //   System.Decimal, which we require operator overloading to catch)
                //
-               static bool IsPredefinedOperator (Type t)
+               static bool IsPredefinedOperator (TypeSpec t)
                {
                        return (TypeManager.IsPrimitiveType (t) && t != TypeManager.bool_type) ||
                                TypeManager.IsEnumType (t) ||
@@ -1135,9 +1121,9 @@ namespace Mono.CSharp {
                                // TODO: Cache this based on type when using EmptyExpression in
                                // context cache
                                Binary.Operator op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition;
-                               operation = new Binary (op, operation, one);
+                               operation = new Binary (op, operation, one, loc);
                                operation = operation.Resolve (ec);
-                               if (operation.Type != type)
+                               if (operation != null && operation.Type != type)
                                        operation = Convert.ExplicitNumericConversion (operation, type);
 
                                return this;
@@ -1146,7 +1132,6 @@ namespace Mono.CSharp {
                        //
                        // Step 2: Perform Operator Overload location
                        //
-                       MethodGroupExpr mg;
                        string op_name;
 
                        if (IsDecrement)
@@ -1154,7 +1139,7 @@ namespace Mono.CSharp {
                        else
                                op_name = Operator.GetMetadataName (Operator.OpType.Increment);
 
-                       mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+                       var mg = MethodLookup (ec.Compiler, ec.CurrentType, type, MemberKind.Operator, op_name, 0, loc);
 
                        if (mg != null) {
                                Arguments args = new Arguments (1);
@@ -1204,7 +1189,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        probe_type_expr = ProbeType.ResolveAsTypeTerminal (ec, false);
                        if (probe_type_expr == null)
@@ -1214,7 +1199,7 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       if ((probe_type_expr.Type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                       if (probe_type_expr.Type.IsStatic) {
                                ec.Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type",
                                        OperatorName);
                        }
@@ -1234,12 +1219,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-                       probe_type_expr.MutateHoistedGenericType (storey);
-               }
-
                protected abstract string OperatorName { get; }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -1274,28 +1253,26 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
                        if (expr_unwrap != null) {
                                expr_unwrap.EmitCheck (ec);
                                return;
                        }
 
                        expr.Emit (ec);
-                       ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
-                       ig.Emit (OpCodes.Ldnull);
-                       ig.Emit (OpCodes.Cgt_Un);
+                       ec.Emit (OpCodes.Isinst, probe_type_expr.Type);
+                       ec.Emit (OpCodes.Ldnull);
+                       ec.Emit (OpCodes.Cgt_Un);
                }
 
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
-                       ILGenerator ig = ec.ig;
                        if (expr_unwrap != null) {
                                expr_unwrap.EmitCheck (ec);
                        } else {
                                expr.Emit (ec);
-                               ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+                               ec.Emit (OpCodes.Isinst, probe_type_expr.Type);
                        }                       
-                       ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                       ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
                }
                
                Expression CreateConstantResult (ResolveContext ec, bool result)
@@ -1307,15 +1284,15 @@ namespace Mono.CSharp {
                                ec.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
                                        TypeManager.CSharpName (probe_type_expr.Type));
 
-                       return ReducedExpression.Create (new BoolConstant (result, loc), this);
+                       return ReducedExpression.Create (new BoolConstant (result, loc).Resolve (ec), this);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (base.DoResolve (ec) == null)
                                return null;
 
-                       Type d = expr.Type;
+                       TypeSpec d = expr.Type;
                        bool d_is_nullable = false;
 
                        //
@@ -1325,18 +1302,24 @@ namespace Mono.CSharp {
                        if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
                                return CreateConstantResult (ec, false);
 
-                       if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
-                               d = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (d) [0]);
-                               d_is_nullable = true;
+                       if (TypeManager.IsNullableType (d)) {
+                               var ut = Nullable.NullableInfo.GetUnderlyingType (d);
+                               if (!ut.IsGenericParameter) {
+                                       d = ut;
+                                       d_is_nullable = true;
+                               }
                        }
 
                        type = TypeManager.bool_type;
                        eclass = ExprClass.Value;
-                       Type t = probe_type_expr.Type;
+                       TypeSpec t = probe_type_expr.Type;
                        bool t_is_nullable = false;
-                       if (TypeManager.IsNullableType (t) && !TypeManager.ContainsGenericParameters (t)) {
-                               t = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (t) [0]);
-                               t_is_nullable = true;
+                       if (TypeManager.IsNullableType (t)) {
+                               var ut = Nullable.NullableInfo.GetUnderlyingType (t);
+                               if (!ut.IsGenericParameter) {
+                                       t = ut;
+                                       t_is_nullable = true;
+                               }
                        }
 
                        if (TypeManager.IsStruct (t)) {
@@ -1355,8 +1338,9 @@ namespace Mono.CSharp {
                                        return CreateConstantResult (ec, true);
                                }
 
-                               if (TypeManager.IsGenericParameter (d))
-                                       return ResolveGenericParameter (ec, t, d);
+                               var tp = d as TypeParameterSpec;
+                               if (tp != null)
+                                       return ResolveGenericParameter (ec, t, tp);
 
                                //
                                // An unboxing conversion exists
@@ -1365,15 +1349,14 @@ namespace Mono.CSharp {
                                        return this;
                        } else {
                                if (TypeManager.IsGenericParameter (t))
-                                       return ResolveGenericParameter (ec, d, t);
+                                       return ResolveGenericParameter (ec, d, (TypeParameterSpec) t);
 
                                if (TypeManager.IsStruct (d)) {
-                                       bool temp;
-                                       if (Convert.ImplicitBoxingConversionExists (expr, t, out temp))
+                                       if (Convert.ImplicitBoxingConversion (null, d, t) != null)
                                                return CreateConstantResult (ec, true);
                                } else {
                                        if (TypeManager.IsGenericParameter (d))
-                                               return ResolveGenericParameter (ec, t, d);
+                                               return ResolveGenericParameter (ec, t, (TypeParameterSpec) d);
 
                                        if (TypeManager.ContainsGenericParameters (d))
                                                return this;
@@ -1388,16 +1371,15 @@ namespace Mono.CSharp {
                        return CreateConstantResult (ec, false);
                }
 
-               Expression ResolveGenericParameter (ResolveContext ec, Type d, Type t)
+               Expression ResolveGenericParameter (ResolveContext ec, TypeSpec d, TypeParameterSpec t)
                {
-                       GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
-                       if (constraints != null) {
-                               if (constraints.IsReferenceType && TypeManager.IsStruct (d))
+                       if (t.IsReferenceType) {
+                               if (TypeManager.IsStruct (d))
                                        return CreateConstantResult (ec, false);
                        }
 
                        if (TypeManager.IsGenericParameter (expr.Type)) {
-                               if (constraints != null && constraints.IsValueType && expr.Type == t)
+                               if (t.IsValueType && expr.Type == t)
                                        return CreateConstantResult (ec, true);
 
                                expr = new BoxedCast (expr, d);
@@ -1434,23 +1416,17 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        expr.Emit (ec);
 
                        if (do_isinst)
-                               ig.Emit (OpCodes.Isinst, type);
+                               ec.Emit (OpCodes.Isinst, type);
 
                        if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type))
-                               ig.Emit (OpCodes.Unbox_Any, type);
+                               ec.Emit (OpCodes.Unbox_Any, type);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       // Because expr is modified
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-
                        if (resolved_type == null) {
                                resolved_type = base.DoResolve (ec);
 
@@ -1460,7 +1436,7 @@ namespace Mono.CSharp {
 
                        type = probe_type_expr.Type;
                        eclass = ExprClass.Value;
-                       Type etype = expr.Type;
+                       TypeSpec etype = expr.Type;
 
                        if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) {
                                if (TypeManager.IsGenericParameter (type)) {
@@ -1510,32 +1486,13 @@ namespace Mono.CSharp {
                protected override string OperatorName {
                        get { return "as"; }
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       type = storey.MutateType (type);
-                       base.MutateHoistedGenericType (storey);
-               }
-       
-               public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
-               {
-                       return expr.GetAttributableValue (ec, value_type, out value);
-               }
        }
        
-       /// <summary>
-       ///   This represents a typecast in the source language.
-       ///
-       ///   FIXME: Cast expressions have an unusual set of parsing
-       ///   rules, we need to figure those out.
-       /// </summary>
+       //
+       // This represents a typecast in the source language.
+       //
        public class Cast : ShimExpression {
                Expression target_type;
-                       
-               public Cast (Expression cast_type, Expression expr)
-                       : this (cast_type, expr, cast_type.Location)
-               {
-               }
 
                public Cast (Expression cast_type, Expression expr, Location loc)
                        : base (expr)
@@ -1548,7 +1505,7 @@ namespace Mono.CSharp {
                        get { return target_type; }
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
@@ -1560,7 +1517,7 @@ namespace Mono.CSharp {
 
                        type = target.Type;
 
-                       if (type.IsAbstract && type.IsSealed) {
+                       if (type.IsStatic) {
                                ec.Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type));
                                return null;
                        }
@@ -1576,14 +1533,17 @@ namespace Mono.CSharp {
 
                        if (type.IsPointer && !ec.IsUnsafe) {
                                UnsafeError (ec, loc);
-                       } else if (TypeManager.IsDynamicType (expr.Type)) {
+                       } else if (expr.Type == InternalType.Dynamic) {
                                Arguments arg = new Arguments (1);
                                arg.Add (new Argument (expr));
                                return new DynamicConversion (type, CSharpBinderFlags.ConvertExplicit, arg, loc).Resolve (ec);
                        }
 
-                       expr = Convert.ExplicitConversion (ec, expr, type, loc);
-                       return expr;
+                       var res = Convert.ExplicitConversion (ec, expr, type, loc);
+                       if (res == expr)
+                               return EmptyCast.Create (res, type);
+
+                       return res;
                }
                
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -1599,7 +1559,7 @@ namespace Mono.CSharp {
        {
                bool arrayAccess;
 
-               public ImplicitCast (Expression expr, Type target, bool arrayAccess)
+               public ImplicitCast (Expression expr, TypeSpec target, bool arrayAccess)
                        : base (expr)
                {
                        this.loc = expr.Location;
@@ -1607,7 +1567,7 @@ namespace Mono.CSharp {
                        this.arrayAccess = arrayAccess;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
@@ -1643,7 +1603,7 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Constant", args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        TypeExpr texpr = expr.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
@@ -1651,19 +1611,19 @@ namespace Mono.CSharp {
 
                        type = texpr.Type;
 
-                       if ((type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                       if (type.IsStatic) {
                                ec.Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type");
                        }
 
                        if (type.IsPointer)
-                               return new NullLiteral (Location).ConvertImplicitly (type);
+                               return new NullLiteral (Location).ConvertImplicitly (ec, type);
 
                        if (TypeManager.IsReferenceType (type))
                                return new NullConstant (type, loc);
 
                        Constant c = New.Constantify (type);
                        if (c != null)
-                               return c;
+                               return c.Resolve (ec);
 
                        eclass = ExprClass.Variable;
                        return this;
@@ -1674,15 +1634,10 @@ namespace Mono.CSharp {
                        LocalTemporary temp_storage = new LocalTemporary(type);
 
                        temp_storage.AddressOf(ec, AddressOp.LoadStore);
-                       ec.ig.Emit(OpCodes.Initobj, type);
+                       ec.Emit(OpCodes.Initobj, type);
                        temp_storage.Emit(ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       type = storey.MutateType (type);
-               }
-               
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        DefaultValueExpression target = (DefaultValueExpression) t;
@@ -1696,29 +1651,28 @@ namespace Mono.CSharp {
        /// </summary>
        public class Binary : Expression, IDynamicBinder
        {
-
                protected class PredefinedOperator {
-                       protected readonly Type left;
-                       protected readonly Type right;
+                       protected readonly TypeSpec left;
+                       protected readonly TypeSpec right;
                        public readonly Operator OperatorsMask;
-                       public Type ReturnType;
+                       public TypeSpec ReturnType;
 
-                       public PredefinedOperator (Type ltype, Type rtype, Operator op_mask)
+                       public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
                                : this (ltype, rtype, op_mask, ltype)
                        {
                        }
 
-                       public PredefinedOperator (Type type, Operator op_mask, Type return_type)
+                       public PredefinedOperator (TypeSpec type, Operator op_mask, TypeSpec return_type)
                                : this (type, type, op_mask, return_type)
                        {
                        }
 
-                       public PredefinedOperator (Type type, Operator op_mask)
+                       public PredefinedOperator (TypeSpec type, Operator op_mask)
                                : this (type, type, op_mask, type)
                        {
                        }
 
-                       public PredefinedOperator (Type ltype, Type rtype, Operator op_mask, Type return_type)
+                       public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type)
                        {
                                if ((op_mask & Operator.ValuesOnlyMask) != 0)
                                        throw new InternalErrorException ("Only masked values can be used");
@@ -1744,10 +1698,28 @@ namespace Mono.CSharp {
                                if (left == TypeManager.decimal_type)
                                        return b.ResolveUserOperator (ec, b.left.Type, b.right.Type);
 
+                               var c = b.right as Constant;
+                               if (c != null) {
+                                       if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.BitwiseOr || b.oper == Operator.Subtraction))
+                                               return ReducedExpression.Create (b.left, b).Resolve (ec);
+                                       if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger)
+                                               return ReducedExpression.Create (b.left, b).Resolve (ec);
+                                       return b;
+                               }
+
+                               c = b.left as Constant;
+                               if (c != null) {
+                                       if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.BitwiseOr))
+                                               return ReducedExpression.Create (b.right, b).Resolve (ec);
+                                       if (b.oper == Operator.Multiply && c.IsOneInteger)
+                                               return ReducedExpression.Create (b.right, b).Resolve (ec);
+                                       return b;
+                               }
+
                                return b;
                        }
 
-                       public bool IsPrimitiveApplicable (Type ltype, Type rtype)
+                       public bool IsPrimitiveApplicable (TypeSpec ltype, TypeSpec rtype)
                        {
                                //
                                // We are dealing with primitive types only
@@ -1787,13 +1759,13 @@ namespace Mono.CSharp {
                }
 
                class PredefinedStringOperator : PredefinedOperator {
-                       public PredefinedStringOperator (Type type, Operator op_mask)
+                       public PredefinedStringOperator (TypeSpec type, Operator op_mask)
                                : base (type, op_mask, type)
                        {
                                ReturnType = TypeManager.string_type;
                        }
 
-                       public PredefinedStringOperator (Type ltype, Type rtype, Operator op_mask)
+                       public PredefinedStringOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
                                : base (ltype, rtype, op_mask)
                        {
                                ReturnType = TypeManager.string_type;
@@ -1818,12 +1790,12 @@ namespace Mono.CSharp {
                                //
                                // Start a new concat expression using converted expression
                                //
-                               return new StringConcat (b.loc, b.left, b.right).Resolve (ec);
+                               return StringConcat.Create (ec, b.left, b.right, b.loc);
                        }
                }
 
                class PredefinedShiftOperator : PredefinedOperator {
-                       public PredefinedShiftOperator (Type ltype, Operator op_mask) :
+                       public PredefinedShiftOperator (TypeSpec ltype, Operator op_mask) :
                                base (ltype, TypeManager.int32_type, op_mask)
                        {
                        }
@@ -1840,29 +1812,37 @@ namespace Mono.CSharp {
                                // b = b.left >> b.right & (0x1f|0x3f)
                                //
                                b.right = new Binary (Operator.BitwiseAnd,
-                                       b.right, new IntConstant (right_mask, b.right.Location)).Resolve (ec);
+                                       b.right, new IntConstant (right_mask, b.right.Location), b.loc).Resolve (ec);
 
                                //
                                // Expression tree representation does not use & mask
                                //
                                b.right = ReducedExpression.Create (b.right, expr_tree_expr).Resolve (ec);
                                b.type = ReturnType;
+
+                               //
+                               // Optimize shift by 0
+                               //
+                               var c = b.right as Constant;
+                               if (c != null && c.IsDefaultValue)
+                                       return ReducedExpression.Create (b.left, b).Resolve (ec);
+
                                return b;
                        }
                }
 
                class PredefinedPointerOperator : PredefinedOperator {
-                       public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask)
+                       public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
                                : base (ltype, rtype, op_mask)
                        {
                        }
 
-                       public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask, Type retType)
+                       public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)
                                : base (ltype, rtype, op_mask, retType)
                        {
                        }
 
-                       public PredefinedPointerOperator (Type type, Operator op_mask, Type return_type)
+                       public PredefinedPointerOperator (TypeSpec type, Operator op_mask, TypeSpec return_type)
                                : base (type, op_mask, return_type)
                        {
                        }
@@ -1896,7 +1876,7 @@ namespace Mono.CSharp {
                                        b.right = EmptyCast.Create (b.right, right);
                                }
 
-                               Type r_type = ReturnType;
+                               TypeSpec r_type = ReturnType;
                                Expression left_arg, right_arg;
                                if (r_type == null) {
                                        if (left == null) {
@@ -1962,21 +1942,21 @@ namespace Mono.CSharp {
                readonly bool is_compound;
                Expression enum_conversion;
 
-               static PredefinedOperator [] standard_operators;
-               static PredefinedOperator [] pointer_operators;
+               static PredefinedOperator[] standard_operators;
+               static PredefinedOperator[] pointer_operators;
                
-               public Binary (Operator oper, Expression left, Expression right, bool isCompound)
-                       : this (oper, left, right)
+               public Binary (Operator oper, Expression left, Expression right, bool isCompound, Location loc)
+                       : this (oper, left, right, loc)
                {
                        this.is_compound = isCompound;
                }
 
-               public Binary (Operator oper, Expression left, Expression right)
+               public Binary (Operator oper, Expression left, Expression right, Location loc)
                {
                        this.oper = oper;
                        this.left = left;
                        this.right = right;
-                       this.loc = left.Location;
+                       this.loc = loc;
                }
 
                public Operator Oper {
@@ -2059,7 +2039,7 @@ namespace Mono.CSharp {
 
                public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, Operator oper, Location loc)
                {
-                       new Binary (oper, left, right).Error_OperatorCannotBeApplied (ec, left, right);
+                       new Binary (oper, left, right, loc).Error_OperatorCannotBeApplied (ec, left, right);
                }
 
                public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc)
@@ -2167,10 +2147,9 @@ namespace Mono.CSharp {
                        return CSharp.Operator.GetMetadataName (op_type);
                }
 
-               public static void EmitOperatorOpcode (EmitContext ec, Operator oper, Type l)
+               public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l)
                {
                        OpCode opcode;
-                       ILGenerator ig = ec.ig;
 
                        switch (oper){
                        case Operator.Multiply:
@@ -2240,8 +2219,8 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.Inequality:
-                               ig.Emit (OpCodes.Ceq);
-                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ec.Emit (OpCodes.Ceq);
+                               ec.Emit (OpCodes.Ldc_I4_0);
                                
                                opcode = OpCodes.Ceq;
                                break;
@@ -2262,21 +2241,21 @@ namespace Mono.CSharp {
 
                        case Operator.LessThanOrEqual:
                                if (IsUnsigned (l) || IsFloat (l))
-                                       ig.Emit (OpCodes.Cgt_Un);
+                                       ec.Emit (OpCodes.Cgt_Un);
                                else
-                                       ig.Emit (OpCodes.Cgt);
-                               ig.Emit (OpCodes.Ldc_I4_0);
+                                       ec.Emit (OpCodes.Cgt);
+                               ec.Emit (OpCodes.Ldc_I4_0);
                                
                                opcode = OpCodes.Ceq;
                                break;
 
                        case Operator.GreaterThanOrEqual:
                                if (IsUnsigned (l) || IsFloat (l))
-                                       ig.Emit (OpCodes.Clt_Un);
+                                       ec.Emit (OpCodes.Clt_Un);
                                else
-                                       ig.Emit (OpCodes.Clt);
+                                       ec.Emit (OpCodes.Clt);
                                
-                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ec.Emit (OpCodes.Ldc_I4_0);
                                
                                opcode = OpCodes.Ceq;
                                break;
@@ -2297,10 +2276,10 @@ namespace Mono.CSharp {
                                throw new InternalErrorException (oper.ToString ());
                        }
 
-                       ig.Emit (opcode);
+                       ec.Emit (opcode);
                }
 
-               static bool IsUnsigned (Type t)
+               static bool IsUnsigned (TypeSpec t)
                {
                        if (t.IsPointer)
                                return true;
@@ -2309,15 +2288,20 @@ namespace Mono.CSharp {
                                t == TypeManager.ushort_type || t == TypeManager.byte_type);
                }
 
-               static bool IsFloat (Type t)
+               static bool IsFloat (TypeSpec t)
                {
                        return t == TypeManager.float_type || t == TypeManager.double_type;
                }
 
+               public static void Reset ()
+               {
+                       pointer_operators = standard_operators = null;
+               }
+
                Expression ResolveOperator (ResolveContext ec)
                {
-                       Type l = left.Type;
-                       Type r = right.Type;
+                       TypeSpec l = left.Type;
+                       TypeSpec r = right.Type;
                        Expression expr;
                        bool primitives_only = false;
 
@@ -2445,7 +2429,7 @@ namespace Mono.CSharp {
 
                static void CreatePointerOperatorsTable ()
                {
-                       ArrayList temp = new ArrayList ();
+                       var temp = new List<PredefinedPointerOperator> ();
 
                        //
                        // Pointer arithmetic:
@@ -2476,13 +2460,13 @@ namespace Mono.CSharp {
                        //
                        temp.Add (new PredefinedPointerOperator (null, Operator.SubtractionMask, TypeManager.int64_type));
 
-                       pointer_operators = (PredefinedOperator []) temp.ToArray (typeof (PredefinedOperator));
+                       pointer_operators = temp.ToArray ();
                }
 
                static void CreateStandardOperatorsTable ()
                {
-                       ArrayList temp = new ArrayList ();
-                       Type bool_type = TypeManager.bool_type;
+                       var temp = new List<PredefinedOperator> ();
+                       TypeSpec bool_type = TypeManager.bool_type;
 
                        temp.Add (new PredefinedOperator (TypeManager.int32_type, Operator.ArithmeticMask | Operator.BitwiseMask));
                        temp.Add (new PredefinedOperator (TypeManager.uint32_type, Operator.ArithmeticMask | Operator.BitwiseMask));
@@ -2514,20 +2498,20 @@ namespace Mono.CSharp {
                        temp.Add (new PredefinedShiftOperator (TypeManager.int64_type, Operator.ShiftMask));
                        temp.Add (new PredefinedShiftOperator (TypeManager.uint64_type, Operator.ShiftMask));
 
-                       standard_operators = (PredefinedOperator []) temp.ToArray (typeof (PredefinedOperator));
+                       standard_operators = temp.ToArray ();
                }
 
                //
                // Rules used during binary numeric promotion
                //
-               static bool DoNumericPromotion (ref Expression prim_expr, ref Expression second_expr, Type type)
+               static bool DoNumericPromotion (ResolveContext rc, ref Expression prim_expr, ref Expression second_expr, TypeSpec type)
                {
                        Expression temp;
-                       Type etype;
+                       TypeSpec etype;
 
                        Constant c = prim_expr as Constant;
                        if (c != null) {
-                               temp = c.ConvertImplicitly (type);
+                               temp = c.ConvertImplicitly (rc, type);
                                if (temp != null) {
                                        prim_expr = temp;
                                        return true;
@@ -2542,7 +2526,7 @@ namespace Mono.CSharp {
                                        if (type != second_expr.Type) {
                                                c = second_expr as Constant;
                                                if (c != null)
-                                                       temp = c.ConvertImplicitly (type);
+                                                       temp = c.ConvertImplicitly (rc, type);
                                                else
                                                        temp = Convert.ImplicitNumericConversion (second_expr, type);
                                                if (temp == null)
@@ -2555,7 +2539,7 @@ namespace Mono.CSharp {
                                // A compile-time error occurs if the other operand is of type sbyte, short, int, or long
                                //
                                if (type == TypeManager.int32_type || type == TypeManager.int64_type ||
-                                       type == TypeManager.sbyte_type || type == TypeManager.sbyte_type)
+                                       type == TypeManager.short_type || type == TypeManager.sbyte_type)
                                        return false;
                        }
 
@@ -2572,23 +2556,23 @@ namespace Mono.CSharp {
                //
                public bool DoBinaryOperatorPromotion (ResolveContext ec)
                {
-                       Type ltype = left.Type;
-                       Type rtype = right.Type;
+                       TypeSpec ltype = left.Type;
+                       TypeSpec rtype = right.Type;
                        Expression temp;
 
-                       foreach (Type t in ConstantFold.binary_promotions) {
+                       foreach (TypeSpec t in ConstantFold.BinaryPromotionsTypes) {
                                if (t == ltype)
-                                       return t == rtype || DoNumericPromotion (ref right, ref left, t);
+                                       return t == rtype || DoNumericPromotion (ec, ref right, ref left, t);
 
                                if (t == rtype)
-                                       return t == ltype || DoNumericPromotion (ref left, ref right, t);
+                                       return t == ltype || DoNumericPromotion (ec, ref left, ref right, t);
                        }
 
-                       Type int32 = TypeManager.int32_type;
+                       TypeSpec int32 = TypeManager.int32_type;
                        if (ltype != int32) {
                                Constant c = left as Constant;
                                if (c != null)
-                                       temp = c.ConvertImplicitly (int32);
+                                       temp = c.ConvertImplicitly (ec, int32);
                                else
                                        temp = Convert.ImplicitNumericConversion (left, int32);
 
@@ -2600,7 +2584,7 @@ namespace Mono.CSharp {
                        if (rtype != int32) {
                                Constant c = right as Constant;
                                if (c != null)
-                                       temp = c.ConvertImplicitly (int32);
+                                       temp = c.ConvertImplicitly (ec, int32);
                                else
                                        temp = Convert.ImplicitNumericConversion (right, int32);
 
@@ -2612,7 +2596,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (left == null)
                                return null;
@@ -2662,8 +2646,10 @@ namespace Mono.CSharp {
 
                        if (rc != null && lc != null) {
                                int prev_e = ec.Report.Errors;
-                               Expression e = ConstantFold.BinaryFold (
-                                       ec, oper, lc, rc, loc);
+                               Expression e = ConstantFold.BinaryFold (ec, oper, lc, rc, loc);
+                               if (e != null)
+                                       e = e.Resolve (ec);
+
                                if (e != null || ec.Report.Errors != prev_e)
                                        return e;
                        }
@@ -2677,7 +2663,7 @@ namespace Mono.CSharp {
                                CheckUselessComparison (ec, rc, left.Type);
                        }
 
-                       if (TypeManager.IsDynamicType (left.Type) || TypeManager.IsDynamicType (right.Type)) {
+                       if (left.Type == InternalType.Dynamic || right.Type == InternalType.Dynamic) {
                                Arguments args = new Arguments (2);
                                args.Add (new Argument (left));
                                args.Add (new Argument (right));
@@ -2709,7 +2695,6 @@ namespace Mono.CSharp {
                        return expr;
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        var le = left.MakeExpression (ctx);
@@ -2757,13 +2742,6 @@ namespace Mono.CSharp {
                                throw new NotImplementedException (oper.ToString ());
                        }
                }
-#endif
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       left.MutateHoistedGenericType (storey);
-                       right.MutateHoistedGenericType (storey);
-               }
 
                //
                // D operator + (D x, D y)
@@ -2771,10 +2749,10 @@ namespace Mono.CSharp {
                // bool operator == (D x, D y)
                // bool operator != (D x, D y)
                //
-               Expression ResolveOperatorDelegate (ResolveContext ec, Type l, Type r)
+               Expression ResolveOperatorDelegate (ResolveContext ec, TypeSpec l, TypeSpec r)
                {
                        bool is_equality = (oper & Operator.EqualityMask) != 0;
-                       if (!TypeManager.IsEqual (l, r) && !TypeManager.IsVariantOf (r, l)) {
+                       if (!TypeManager.IsEqual (l, r) && !TypeSpecComparer.Variant.IsEqual (r, l)) {
                                Expression tmp;
                                if (right.eclass == ExprClass.MethodGroup || (r == InternalType.AnonymousMethod && !is_equality)) {
                                        tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
@@ -2799,7 +2777,7 @@ namespace Mono.CSharp {
                        if (is_equality)
                                return ResolveUserOperator (ec, l, r);
 
-                       MethodInfo method;
+                       MethodSpec method;
                        Arguments args = new Arguments (2);
                        args.Add (new Argument (left));
                        args.Add (new Argument (right));
@@ -2820,7 +2798,10 @@ namespace Mono.CSharp {
                                method = TypeManager.delegate_remove_delegate_delegate;
                        }
 
-                       MethodGroupExpr mg = new MethodGroupExpr (new MemberInfo [] { method }, TypeManager.delegate_type, loc);
+                       if (method == null)
+                               return new EmptyExpression (TypeManager.decimal_type);
+
+                       MethodGroupExpr mg = new MethodGroupExpr (method, TypeManager.delegate_type, loc);
                        mg = mg.OverloadResolve (ec, ref args, false, loc);
 
                        return new ClassCast (new UserOperatorCall (mg, args, CreateExpressionTree, loc), l);
@@ -2829,7 +2810,7 @@ namespace Mono.CSharp {
                //
                // Enumeration operators
                //
-               Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, Type ltype, Type rtype)
+               Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype)
                {
                        //
                        // bool operator == (E x, E y);
@@ -2856,7 +2837,7 @@ namespace Mono.CSharp {
 
                        Expression ltemp = left;
                        Expression rtemp = right;
-                       Type underlying_type;
+                       TypeSpec underlying_type;
                        Expression expr;
                        
                        if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) {
@@ -2876,19 +2857,19 @@ namespace Mono.CSharp {
                        }                       
 
                        if (TypeManager.IsEqual (ltype, rtype)) {
-                               underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
+                               underlying_type = EnumSpec.GetUnderlyingType (ltype);
 
                                if (left is Constant)
-                                       left = ((Constant) left).ConvertExplicitly (false, underlying_type);
+                                       left = ((Constant) left).ConvertExplicitly (false, underlying_type).Resolve (ec);
                                else
                                        left = EmptyCast.Create (left, underlying_type);
 
                                if (right is Constant)
-                                       right = ((Constant) right).ConvertExplicitly (false, underlying_type);
+                                       right = ((Constant) right).ConvertExplicitly (false, underlying_type).Resolve (ec);
                                else
                                        right = EmptyCast.Create (right, underlying_type);
                        } else if (lenum) {
-                               underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
+                               underlying_type = EnumSpec.GetUnderlyingType (ltype);
 
                                if (oper != Operator.Subtraction && oper != Operator.Addition) {
                                        Constant c = right as Constant;
@@ -2902,12 +2883,12 @@ namespace Mono.CSharp {
                                }
 
                                if (left is Constant)
-                                       left = ((Constant) left).ConvertExplicitly (false, underlying_type);
+                                       left = ((Constant) left).ConvertExplicitly (false, underlying_type).Resolve (ec);
                                else
                                        left = EmptyCast.Create (left, underlying_type);
 
                        } else if (renum) {
-                               underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
+                               underlying_type = EnumSpec.GetUnderlyingType (rtype);
 
                                if (oper != Operator.Addition) {
                                        Constant c = left as Constant;
@@ -2921,7 +2902,7 @@ namespace Mono.CSharp {
                                }
 
                                if (right is Constant)
-                                       right = ((Constant) right).ConvertExplicitly (false, underlying_type);
+                                       right = ((Constant) right).ConvertExplicitly (false, underlying_type).Resolve (ec);
                                else
                                        right = EmptyCast.Create (right, underlying_type);
 
@@ -2939,9 +2920,9 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       Type res_type = null;
+                       TypeSpec res_type = null;
                        if ((oper & Operator.BitwiseMask) != 0 || oper == Operator.Subtraction || oper == Operator.Addition) {
-                               Type promoted_type = lenum ? left.Type : right.Type;
+                               TypeSpec promoted_type = lenum ? left.Type : right.Type;
                                enum_conversion = Convert.ExplicitNumericConversion (
                                        new EmptyExpression (promoted_type), underlying_type);
 
@@ -2986,7 +2967,7 @@ namespace Mono.CSharp {
                //
                // 7.9.6 Reference type equality operators
                //
-               Binary ResolveOperatorEqualityRerefence (ResolveContext ec, Type l, Type r)
+               Binary ResolveOperatorEqualityRerefence (ResolveContext ec, TypeSpec l, TypeSpec r)
                {
                        //
                        // operator != (object a, object b)
@@ -2999,12 +2980,14 @@ namespace Mono.CSharp {
                                return null;
 
                        type = TypeManager.bool_type;
-                       GenericConstraints constraints;
 
-                       bool lgen = TypeManager.IsGenericParameter (l);
+                       var lgen = l as TypeParameterSpec;
 
-                       if (TypeManager.IsEqual (l, r)) {
-                               if (lgen) {
+                       if (l == r) {
+                               if (l is InternalType)
+                                       return null;
+
+                               if (lgen != null) {
                                        //
                                        // Only allow to compare same reference type parameter
                                        //
@@ -3017,16 +3000,13 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
-                               if (l == InternalType.AnonymousMethod)
-                                       return null;
-
                                if (TypeManager.IsValueType (l))
                                        return null;
 
                                return this;
                        }
 
-                       bool rgen = TypeManager.IsGenericParameter (r);
+                       var rgen = r as TypeParameterSpec;
 
                        //
                        // a, Both operands are reference-type values or the value null
@@ -3035,18 +3015,16 @@ namespace Mono.CSharp {
                        // value type constrain
                        //
                        if (left is NullLiteral || right is NullLiteral) {
-                               if (lgen) {
-                                       constraints = TypeManager.GetTypeParameterConstraints (l);
-                                       if (constraints != null && constraints.HasValueTypeConstraint)
+                               if (lgen != null) {
+                                       if (lgen.HasSpecialStruct)
                                                return null;
 
                                        left = new BoxedCast (left, TypeManager.object_type);
                                        return this;
                                }
 
-                               if (rgen) {
-                                       constraints = TypeManager.GetTypeParameterConstraints (r);
-                                       if (constraints != null && constraints.HasValueTypeConstraint)
+                               if (rgen != null) {
+                                       if (rgen.HasSpecialStruct)
                                                return null;
 
                                        right = new BoxedCast (right, TypeManager.object_type);
@@ -3059,7 +3037,7 @@ namespace Mono.CSharp {
                        // standard conversion is applied. It's not clear from the
                        // standard but it looks like it works like that.
                        //
-                       if (lgen) {
+                       if (lgen != null) {
                                if (!TypeManager.IsReferenceType (l))
                                        return null;
 
@@ -3071,7 +3049,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (rgen) {
+                       if (rgen != null) {
                                if (!TypeManager.IsReferenceType (r))
                                        return null;
 
@@ -3109,7 +3087,7 @@ namespace Mono.CSharp {
                }
 
 
-               Expression ResolveOperatorPointer (ResolveContext ec, Type l, Type r)
+               Expression ResolveOperatorPointer (ResolveContext ec, TypeSpec l, TypeSpec r)
                {
                        //
                        // bool operator == (void* x, void* y);
@@ -3148,11 +3126,11 @@ namespace Mono.CSharp {
                //
                // Build-in operators method overloading
                //
-               protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, Type enum_type)
+               protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type)
                {
                        PredefinedOperator best_operator = null;
-                       Type l = left.Type;
-                       Type r = right.Type;
+                       TypeSpec l = left.Type;
+                       TypeSpec r = right.Type;
                        Operator oper_mask = oper & ~Operator.ValuesOnlyMask;
 
                        foreach (PredefinedOperator po in operators) {
@@ -3205,7 +3183,7 @@ namespace Mono.CSharp {
                                                new SideEffectConstant (lc, right, loc) :
                                                new SideEffectConstant (rc, left, loc);
 
-                                       return ReducedExpression.Create (side_effect, expr);
+                                       return ReducedExpression.Create (side_effect.Resolve (ec), expr);
                                }
                        }
 
@@ -3222,7 +3200,7 @@ namespace Mono.CSharp {
                //
                // Performs user-operator overloading
                //
-               protected virtual Expression ResolveUserOperator (ResolveContext ec, Type l, Type r)
+               protected virtual Expression ResolveUserOperator (ResolveContext ec, TypeSpec l, TypeSpec r)
                {
                        Operator user_oper;
                        if (oper == Operator.LogicalAnd)
@@ -3234,11 +3212,11 @@ namespace Mono.CSharp {
 
                        string op = GetOperatorMetadataName (user_oper);
 
-                       MethodGroupExpr left_operators = MemberLookup (ec.Compiler, ec.CurrentType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+                       MethodGroupExpr left_operators = MethodLookup (ec.Compiler, ec.CurrentType, l, MemberKind.Operator, op, 0, loc);
                        MethodGroupExpr right_operators = null;
 
                        if (!TypeManager.IsEqual (r, l)) {
-                               right_operators = MemberLookup (ec.Compiler, ec.CurrentType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+                               right_operators = MethodLookup (ec.Compiler, ec.CurrentType, r, MemberKind.Operator, op, 0, loc);
                                if (right_operators == null && left_operators == null)
                                        return null;
                        } else if (left_operators == null) {
@@ -3297,9 +3275,9 @@ namespace Mono.CSharp {
                                                (right is NullLiteral && IsBuildInEqualityOperator (l))) {
                                                type = TypeManager.bool_type;
                                                if (left is NullLiteral || right is NullLiteral)
-                                                       oper_expr = ReducedExpression.Create (this, oper_expr).Resolve (ec);
+                                                       oper_expr = ReducedExpression.Create (this, oper_expr);
                                        } else if (l != r) {
-                                               MethodInfo mi = (MethodInfo) union;
+                                               var mi = union.BestCandidate;
                                                
                                                //
                                                // Two System.Delegate(s) are never equal
@@ -3320,7 +3298,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               private void CheckUselessComparison (ResolveContext ec, Constant c, Type type)
+               private void CheckUselessComparison (ResolveContext ec, Constant c, TypeSpec type)
                {
                        if (c == null || !IsTypeIntegral (type)
                                || c is StringConstant
@@ -3373,7 +3351,7 @@ namespace Mono.CSharp {
                                WarnUselessComparison (ec, type);
                }
 
-               static bool IsValueOutOfRange (long value, Type type)
+               static bool IsValueOutOfRange (long value, TypeSpec type)
                {
                        if (IsTypeUnsigned (type) && value < 0)
                                return true;
@@ -3385,13 +3363,13 @@ namespace Mono.CSharp {
                                type == TypeManager.uint32_type && value >= 0x100000000;
                }
 
-               static bool IsBuildInEqualityOperator (Type t)
+               static bool IsBuildInEqualityOperator (TypeSpec t)
                {
                        return t == TypeManager.object_type || t == TypeManager.string_type ||
                                t == TypeManager.delegate_type || TypeManager.IsDelegateType (t);
                }
 
-               static bool IsPredefinedUserOperator (Type t, Operator op)
+               static bool IsPredefinedUserOperator (TypeSpec t, Operator op)
                {
                        //
                        // Some predefined types have user operators
@@ -3399,7 +3377,7 @@ namespace Mono.CSharp {
                        return (op & Operator.EqualityMask) != 0 && (t == TypeManager.string_type || t == TypeManager.decimal_type);
                }
 
-               private static bool IsTypeIntegral (Type type)
+               private static bool IsTypeIntegral (TypeSpec type)
                {
                        return type == TypeManager.uint64_type ||
                                type == TypeManager.int64_type ||
@@ -3412,7 +3390,7 @@ namespace Mono.CSharp {
                                type == TypeManager.char_type;
                }
 
-               private static bool IsTypeUnsigned (Type type)
+               private static bool IsTypeUnsigned (TypeSpec type)
                {
                        return type == TypeManager.uint64_type ||
                                type == TypeManager.uint32_type ||
@@ -3421,7 +3399,7 @@ namespace Mono.CSharp {
                                type == TypeManager.char_type;
                }
 
-               private void WarnUselessComparison (ResolveContext ec, Type type)
+               private void WarnUselessComparison (ResolveContext ec, TypeSpec type)
                {
                        ec.Report.Warning (652, 2, loc, "A comparison between a constant and a variable is useless. The constant is out of the range of the variable type `{0}'",
                                TypeManager.CSharpName (type));
@@ -3437,15 +3415,13 @@ namespace Mono.CSharp {
                /// </remarks>
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
-                       ILGenerator ig = ec.ig;
-
                        //
                        // This is more complicated than it looks, but its just to avoid
                        // duplicated tests: basically, we allow ==, !=, >, <, >= and <=
                        // but on top of that we want for == and != to use a special path
                        // if we are comparing against null
                        //
-                       if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
+                       if ((oper & Operator.EqualityMask) != 0 && (left is Constant || right is Constant)) {
                                bool my_on_true = oper == Operator.Inequality ? on_true : !on_true;
                                
                                //
@@ -3457,7 +3433,10 @@ namespace Mono.CSharp {
                                        left = swap;
                                }
                                
-                               if (((Constant) right).IsZeroInteger) {
+                               //
+                               // brtrue/brfalse works with native int only
+                               //
+                               if (((Constant) right).IsZeroInteger && right.Type != TypeManager.int64_type && right.Type != TypeManager.uint64_type) {
                                        left.EmitBranchable (ec, target, my_on_true);
                                        return;
                                }
@@ -3470,11 +3449,11 @@ namespace Mono.CSharp {
                        } else if (oper == Operator.LogicalAnd) {
 
                                if (on_true) {
-                                       Label tests_end = ig.DefineLabel ();
+                                       Label tests_end = ec.DefineLabel ();
                                        
                                        left.EmitBranchable (ec, tests_end, false);
                                        right.EmitBranchable (ec, target, true);
-                                       ig.MarkLabel (tests_end);                                       
+                                       ec.MarkLabel (tests_end);                                       
                                } else {
                                        //
                                        // This optimizes code like this 
@@ -3495,17 +3474,15 @@ namespace Mono.CSharp {
                                        right.EmitBranchable (ec, target, true);
                                        
                                } else {
-                                       Label tests_end = ig.DefineLabel ();
+                                       Label tests_end = ec.DefineLabel ();
                                        left.EmitBranchable (ec, tests_end, true);
                                        right.EmitBranchable (ec, target, false);
-                                       ig.MarkLabel (tests_end);
+                                       ec.MarkLabel (tests_end);
                                }
                                
                                return;
-                               
-                       } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
-                                    oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
-                                    oper == Operator.Equality        || oper == Operator.Inequality)) {
+
+                       } else if ((oper & Operator.ComparisonMask) == 0) {
                                base.EmitBranchable (ec, target, on_true);
                                return;
                        }
@@ -3513,76 +3490,76 @@ namespace Mono.CSharp {
                        left.Emit (ec);
                        right.Emit (ec);
 
-                       Type t = left.Type;
+                       TypeSpec t = left.Type;
                        bool is_float = IsFloat (t);
                        bool is_unsigned = is_float || IsUnsigned (t);
                        
                        switch (oper){
                        case Operator.Equality:
                                if (on_true)
-                                       ig.Emit (OpCodes.Beq, target);
+                                       ec.Emit (OpCodes.Beq, target);
                                else
-                                       ig.Emit (OpCodes.Bne_Un, target);
+                                       ec.Emit (OpCodes.Bne_Un, target);
                                break;
 
                        case Operator.Inequality:
                                if (on_true)
-                                       ig.Emit (OpCodes.Bne_Un, target);
+                                       ec.Emit (OpCodes.Bne_Un, target);
                                else
-                                       ig.Emit (OpCodes.Beq, target);
+                                       ec.Emit (OpCodes.Beq, target);
                                break;
 
                        case Operator.LessThan:
                                if (on_true)
                                        if (is_unsigned && !is_float)
-                                               ig.Emit (OpCodes.Blt_Un, target);
+                                               ec.Emit (OpCodes.Blt_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Blt, target);
+                                               ec.Emit (OpCodes.Blt, target);
                                else
                                        if (is_unsigned)
-                                               ig.Emit (OpCodes.Bge_Un, target);
+                                               ec.Emit (OpCodes.Bge_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Bge, target);
+                                               ec.Emit (OpCodes.Bge, target);
                                break;
 
                        case Operator.GreaterThan:
                                if (on_true)
                                        if (is_unsigned && !is_float)
-                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                               ec.Emit (OpCodes.Bgt_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Bgt, target);
+                                               ec.Emit (OpCodes.Bgt, target);
                                else
                                        if (is_unsigned)
-                                               ig.Emit (OpCodes.Ble_Un, target);
+                                               ec.Emit (OpCodes.Ble_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Ble, target);
+                                               ec.Emit (OpCodes.Ble, target);
                                break;
 
                        case Operator.LessThanOrEqual:
                                if (on_true)
                                        if (is_unsigned && !is_float)
-                                               ig.Emit (OpCodes.Ble_Un, target);
+                                               ec.Emit (OpCodes.Ble_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Ble, target);
+                                               ec.Emit (OpCodes.Ble, target);
                                else
                                        if (is_unsigned)
-                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                               ec.Emit (OpCodes.Bgt_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Bgt, target);
+                                               ec.Emit (OpCodes.Bgt, target);
                                break;
 
 
                        case Operator.GreaterThanOrEqual:
                                if (on_true)
                                        if (is_unsigned && !is_float)
-                                               ig.Emit (OpCodes.Bge_Un, target);
+                                               ec.Emit (OpCodes.Bge_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Bge, target);
+                                               ec.Emit (OpCodes.Bge, target);
                                else
                                        if (is_unsigned)
-                                               ig.Emit (OpCodes.Blt_Un, target);
+                                               ec.Emit (OpCodes.Blt_Un, target);
                                        else
-                                               ig.Emit (OpCodes.Blt, target);
+                                               ec.Emit (OpCodes.Blt, target);
                                break;
                        default:
                                throw new InternalErrorException (oper.ToString ());
@@ -3594,43 +3571,40 @@ namespace Mono.CSharp {
                        EmitOperator (ec, left.Type);
                }
 
-               protected virtual void EmitOperator (EmitContext ec, Type l)
+               protected virtual void EmitOperator (EmitContext ec, TypeSpec l)
                {
-                       ILGenerator ig = ec.ig;
-
                        //
                        // Handle short-circuit operators differently
                        // than the rest
                        //
                        if ((oper & Operator.LogicalMask) != 0) {
-                               Label load_result = ig.DefineLabel ();
-                               Label end = ig.DefineLabel ();
+                               Label load_result = ec.DefineLabel ();
+                               Label end = ec.DefineLabel ();
 
                                bool is_or = oper == Operator.LogicalOr;
                                left.EmitBranchable (ec, load_result, is_or);
                                right.Emit (ec);
-                               ig.Emit (OpCodes.Br_S, end);
+                               ec.Emit (OpCodes.Br_S, end);
                                
-                               ig.MarkLabel (load_result);
-                               ig.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
-                               ig.MarkLabel (end);
+                               ec.MarkLabel (load_result);
+                               ec.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
+                               ec.MarkLabel (end);
                                return;
                        }
 
-                       left.Emit (ec);
-
                        //
-                       // Optimize zero-based operations
+                       // Optimize zero-based operations which cannot be optimized at expression level
                        //
-                       // TODO: Implement more optimizations, but it should probably go to PredefinedOperators
-                       //
-                       if ((oper & Operator.ShiftMask) != 0 || oper == Operator.Addition || oper == Operator.Subtraction) {
-                               Constant rc = right as Constant;
-                               if (rc != null && rc.IsDefaultValue) {
+                       if (oper == Operator.Subtraction) {
+                               var lc = left as IntegralConstant;
+                               if (lc != null && lc.IsDefaultValue) {
+                                       right.Emit (ec);
+                                       ec.Emit (OpCodes.Neg);
                                        return;
                                }
                        }
 
+                       left.Emit (ec);
                        right.Emit (ec);
                        EmitOperatorOpcode (ec, oper, l);
 
@@ -3663,7 +3637,7 @@ namespace Mono.CSharp {
 
                public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
                {
-                       Arguments binder_args = new Arguments (3);
+                       Arguments binder_args = new Arguments (4);
 
                        MemberAccess sle = new MemberAccess (new MemberAccess (
                                new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);
@@ -3677,7 +3651,8 @@ namespace Mono.CSharp {
 
                        binder_args.Add (new Argument (new EnumConstant (new IntLiteral ((int) flags, loc), TypeManager.binder_flags)));
                        binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
-                       binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (ec), loc)));
+                       binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));                                                                    
+                       binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc)));
 
                        return new Invocation (DynamicExpressionStatement.GetBinder ("BinaryOperation", loc), binder_args);
                }
@@ -3788,15 +3763,24 @@ namespace Mono.CSharp {
        public class StringConcat : Expression {
                Arguments arguments;
                
-               public StringConcat (Location loc, Expression left, Expression right)
+               public StringConcat (Expression left, Expression right, Location loc)
                {
                        this.loc = loc;
                        type = TypeManager.string_type;
                        eclass = ExprClass.Value;
 
                        arguments = new Arguments (2);
-                       Append (left);
-                       Append (right);
+               }
+
+               public static StringConcat Create (ResolveContext rc, Expression left, Expression right, Location loc)
+               {
+                       if (left.eclass == ExprClass.Unresolved || right.eclass == ExprClass.Unresolved)
+                               throw new ArgumentException ();
+
+                       var s = new StringConcat (left, right, loc);
+                       s.Append (rc, left);
+                       s.Append (rc, right);
+                       return s;
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
@@ -3833,16 +3817,16 @@ namespace Mono.CSharp {
                        if (++pos == arguments.Count)
                                return expr;
 
-                       left = new Argument (new EmptyExpression (((MethodInfo)method).ReturnType));
+                       left = new Argument (new EmptyExpression (method.BestCandidate.ReturnType));
                        return CreateExpressionAddCall (ec, left, expr, pos);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        return this;
                }
                
-               public void Append (Expression operand)
+               void Append (ResolveContext rc, Expression operand)
                {
                        //
                        // Constant folding
@@ -3854,7 +3838,7 @@ namespace Mono.CSharp {
                                        StringConstant last_expr_constant = last_argument.Expr as StringConstant;
                                        if (last_expr_constant != null) {
                                                last_argument.Expr = new StringConstant (
-                                                       last_expr_constant.Value + sc.Value, sc.Location);
+                                                       last_expr_constant.Value + sc.Value, sc.Location).Resolve (rc);
                                                return;
                                        }
                                }
@@ -3885,21 +3869,14 @@ namespace Mono.CSharp {
                                concat.Emit (ec);
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        if (arguments.Count != 2)
                                throw new NotImplementedException ("arguments.Count != 2");
 
-                       var concat = TypeManager.string_type.GetMethod ("Concat", new[] { typeof (object), typeof (object) });
+                       var concat = typeof (string).GetMethod ("Concat", new[] { typeof (object), typeof (object) });
                        return SLE.Expression.Add (arguments[0].Expr.MakeExpression (ctx), arguments[1].Expr.MakeExpression (ctx), concat);
                }
-#endif
-               
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       arguments.MutateHoistedGenericType (storey);
-               }               
        }
 
        //
@@ -3914,13 +3891,14 @@ namespace Mono.CSharp {
                        : base (oper_method, arguments, expr_tree, loc)
                {
                        this.is_and = is_and;
+                       eclass = ExprClass.Unresolved;
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       MethodInfo method = (MethodInfo)mg;
-                       type = TypeManager.TypeToCoreType (method.ReturnType);
-                       AParametersCollection pd = TypeManager.GetParameterData (method);
+                       var method = mg.BestCandidate;
+                       type = method.ReturnType;
+                       AParametersCollection pd = method.Parameters;
                        if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) {
                                ec.Report.Error (217, loc,
                                        "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
@@ -3945,19 +3923,18 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label end_target = ig.DefineLabel ();
+                       Label end_target = ec.DefineLabel ();
 
                        //
                        // Emit and duplicate left argument
                        //
                        arguments [0].Expr.Emit (ec);
-                       ig.Emit (OpCodes.Dup);
+                       ec.Emit (OpCodes.Dup);
                        arguments.RemoveAt (0);
 
                        oper.EmitBranchable (ec, end_target, true);
                        base.Emit (ec);
-                       ig.MarkLabel (end_target);
+                       ec.MarkLabel (end_target);
                }
        }
 
@@ -3968,7 +3945,7 @@ namespace Mono.CSharp {
                //
                // We assume that `l' is always a pointer
                //
-               public PointerArithmetic (Binary.Operator op, Expression l, Expression r, Type t, Location loc)
+               public PointerArithmetic (Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc)
                {
                        type = t;
                        this.loc = loc;
@@ -3983,7 +3960,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.Variable;
                        
@@ -3997,23 +3974,22 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       Type op_type = left.Type;
-                       ILGenerator ig = ec.ig;
+                       TypeSpec op_type = left.Type;
                        
                        // It must be either array or fixed buffer
-                       Type element;
+                       TypeSpec element;
                        if (TypeManager.HasElementType (op_type)) {
                                element = TypeManager.GetElementType (op_type);
                        } else {
                                FieldExpr fe = left as FieldExpr;
                                if (fe != null)
-                                       element = AttributeTester.GetFixedBuffer (fe.FieldInfo).ElementType;
+                                       element = ((FixedFieldSpec) (fe.Spec)).ElementType;
                                else
                                        element = op_type;
                        }
 
                        int size = GetTypeSize (element);
-                       Type rtype = right.Type;
+                       TypeSpec rtype = right.Type;
                        
                        if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){
                                //
@@ -4021,16 +3997,16 @@ namespace Mono.CSharp {
                                //
                                left.Emit (ec);
                                right.Emit (ec);
-                               ig.Emit (OpCodes.Sub);
+                               ec.Emit (OpCodes.Sub);
 
                                if (size != 1){
                                        if (size == 0)
-                                               ig.Emit (OpCodes.Sizeof, element);
+                                               ec.Emit (OpCodes.Sizeof, element);
                                        else 
-                                               IntLiteral.EmitInt (ig, size);
-                                       ig.Emit (OpCodes.Div);
+                                               ec.EmitInt (size);
+                                       ec.Emit (OpCodes.Div);
                                }
-                               ig.Emit (OpCodes.Conv_I8);
+                               ec.Emit (OpCodes.Conv_I8);
                        } else {
                                //
                                // handle + and - on (pointer op int)
@@ -4049,7 +4025,7 @@ namespace Mono.CSharp {
 
                                left.Emit (ec);
 
-                               Constant right_const = right as Constant;
+                               var right_const = right as Constant;
                                if (right_const != null) {
                                        //
                                        // Optimize 0-based arithmetic
@@ -4057,42 +4033,42 @@ namespace Mono.CSharp {
                                        if (right_const.IsDefaultValue)
                                                return;
 
-                                       if (size != 0) {
-                                               // TODO: Should be the checks resolve context sensitive?
-                                               ResolveContext rc = new ResolveContext (ec.MemberContext);
-                                               right = ConstantFold.BinaryFold (rc, Binary.Operator.Multiply, new IntConstant (size, right.Location), right_const, loc);
-                                               if (right == null)
-                                                       return;
-                                       } else {
-                                               ig.Emit (OpCodes.Sizeof, element);
-                                               right = EmptyExpression.Null;
-                                       }
+                                       if (size != 0)
+                                               right = new IntConstant (size, right.Location);
+                                       else
+                                               right = new SizeOf (new TypeExpression (element, right.Location), right.Location);
+                                       
+                                       // TODO: Should be the checks resolve context sensitive?
+                                       ResolveContext rc = new ResolveContext (ec.MemberContext, ResolveContext.Options.UnsafeScope);
+                                       right = new Binary (Binary.Operator.Multiply, right, right_const, loc).Resolve (rc);
+                                       if (right == null)
+                                               return;
                                }
 
                                right.Emit (ec);
                                if (rtype == TypeManager.sbyte_type || rtype == TypeManager.byte_type ||
                                        rtype == TypeManager.short_type || rtype == TypeManager.ushort_type) {
-                                       ig.Emit (OpCodes.Conv_I);
+                                       ec.Emit (OpCodes.Conv_I);
                                } else if (rtype == TypeManager.uint32_type) {
-                                       ig.Emit (OpCodes.Conv_U);
+                                       ec.Emit (OpCodes.Conv_U);
                                }
 
                                if (right_const == null && size != 1){
                                        if (size == 0)
-                                               ig.Emit (OpCodes.Sizeof, element);
+                                               ec.Emit (OpCodes.Sizeof, element);
                                        else 
-                                               IntLiteral.EmitInt (ig, size);
+                                               ec.EmitInt (size);
                                        if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
-                                               ig.Emit (OpCodes.Conv_I8);
+                                               ec.Emit (OpCodes.Conv_I8);
 
                                        Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype);
                                }
 
                                if (left_const == null) {
                                        if (rtype == TypeManager.int64_type)
-                                               ig.Emit (OpCodes.Conv_I);
+                                               ec.Emit (OpCodes.Conv_I);
                                        else if (rtype == TypeManager.uint64_type)
-                                               ig.Emit (OpCodes.Conv_U);
+                                               ec.Emit (OpCodes.Conv_U);
 
                                        Binary.EmitOperatorOpcode (ec, op, op_type);
                                }
@@ -4119,7 +4095,7 @@ namespace Mono.CSharp {
                        return base.CreateExpressionTree (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        // A boolean-expression is required to be of a type
                        // that can be implicitly converted to bool or of
@@ -4138,7 +4114,7 @@ namespace Mono.CSharp {
                        if (expr.Type == TypeManager.bool_type)
                                return expr;
 
-                       if (TypeManager.IsDynamicType (expr.Type)) {
+                       if (expr.Type == InternalType.Dynamic) {
                                Arguments args = new Arguments (1);
                                args.Add (new Argument (expr));
                                return new DynamicUnaryConversion ("IsTrue", args, loc).Resolve (ec);
@@ -4203,7 +4179,7 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Condition", args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
                        true_expr = true_expr.Resolve (ec);
@@ -4213,8 +4189,8 @@ namespace Mono.CSharp {
                                return null;
 
                        eclass = ExprClass.Value;
-                       Type true_type = true_expr.Type;
-                       Type false_type = false_expr.Type;
+                       TypeSpec true_type = true_expr.Type;
+                       TypeSpec false_type = false_expr.Type;
                        type = true_type;
 
                        //
@@ -4225,14 +4201,12 @@ namespace Mono.CSharp {
                                Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
                                if (conv != null) {
                                        //
-                                       // Check if both can convert implicitl to each other's type
+                                       // Check if both can convert implicitly to each other's type
                                        //
                                        if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) {
-                                               ec.Report.Error (172, loc,
-                                                          "Can not compute type of conditional expression " +
-                                                          "as `" + TypeManager.CSharpName (true_expr.Type) +
-                                                          "' and `" + TypeManager.CSharpName (false_expr.Type) +
-                                                          "' convert implicitly to each other");
+                                               ec.Report.Error (172, true_expr.Location,
+                                                       "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other",
+                                                       TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type));
                                                return null;
                                        }
                                        type = false_type;
@@ -4240,7 +4214,7 @@ namespace Mono.CSharp {
                                } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) {
                                        false_expr = conv;
                                } else {
-                                       ec.Report.Error (173, loc,
+                                       ec.Report.Error (173, true_expr.Location,
                                                "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
                                                TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type));
                                        return null;
@@ -4258,14 +4232,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-                       true_expr.MutateHoistedGenericType (storey);
-                       false_expr.MutateHoistedGenericType (storey);
-                       type = storey.MutateType (type);
-               }
-
                public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
                {
                        return null;
@@ -4273,24 +4239,23 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label false_target = ig.DefineLabel ();
-                       Label end_target = ig.DefineLabel ();
+                       Label false_target = ec.DefineLabel ();
+                       Label end_target = ec.DefineLabel ();
 
                        expr.EmitBranchable (ec, false_target, false);
                        true_expr.Emit (ec);
 
                        if (type.IsInterface) {
                                LocalBuilder temp = ec.GetTemporaryLocal (type);
-                               ig.Emit (OpCodes.Stloc, temp);
-                               ig.Emit (OpCodes.Ldloc, temp);
+                               ec.Emit (OpCodes.Stloc, temp);
+                               ec.Emit (OpCodes.Ldloc, temp);
                                ec.FreeTemporaryLocal (temp, type);
                        }
 
-                       ig.Emit (OpCodes.Br, end_target);
-                       ig.MarkLabel (false_target);
+                       ec.Emit (OpCodes.Br, end_target);
+                       ec.MarkLabel (false_target);
                        false_expr.Emit (ec);
-                       ig.MarkLabel (end_target);
+                       ec.MarkLabel (end_target);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -4324,7 +4289,7 @@ namespace Mono.CSharp {
                public abstract VariableInfo VariableInfo { get; }
                #endregion
 
-               public void AddressOf (EmitContext ec, AddressOp mode)
+               public virtual void AddressOf (EmitContext ec, AddressOp mode)
                {
                        HoistedVariable hv = GetHoistedVariable (ec);
                        if (hv != null) {
@@ -4388,11 +4353,11 @@ namespace Mono.CSharp {
                                // If we are a reference, we loaded on the stack a pointer
                                // Now lets load the real value
                                //
-                               LoadFromPtr (ec.ig, type);
+                               ec.EmitLoadFromPtr (type);
                        }
 
                        if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
 
                                if (IsRef) {
                                        temp = new LocalTemporary (Type);
@@ -4425,7 +4390,7 @@ namespace Mono.CSharp {
                        }
 
                        if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                                if (IsRef) {
                                        temp = new LocalTemporary (Type);
                                        temp.Store (ec);
@@ -4433,7 +4398,7 @@ namespace Mono.CSharp {
                        }
 
                        if (IsRef)
-                               StoreFromPtr (ec.ig, type);
+                               ec.EmitStoreFromPtr (type);
                        else
                                Variable.EmitAssign (ec);
 
@@ -4446,11 +4411,6 @@ namespace Mono.CSharp {
                public bool IsHoisted {
                        get { return GetHoistedVariable ((AnonymousExpression) null) != null; }
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       type = storey.MutateType (type);
-               }
        }
 
        /// <summary>
@@ -4461,7 +4421,6 @@ namespace Mono.CSharp {
                public Block Block;
                public LocalInfo local_info;
                bool is_readonly;
-               bool resolved;  // TODO: merge with eclass
 
                public LocalVariableReference (Block block, string name, Location l)
                {
@@ -4543,8 +4502,6 @@ namespace Mono.CSharp {
 
                Expression DoResolveBase (ResolveContext ec)
                {
-                       type = local_info.VariableType;
-
                        Expression e = Block.GetConstantExpression (Name);
                        if (e != null)
                                return e.Resolve (ec);
@@ -4565,16 +4522,13 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       resolved |= ec.DoFlowAnalysis;
                        eclass = ExprClass.Variable;
+                       type = local_info.VariableType;
                        return this;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       if (resolved)
-                               return this;
-
                        ResolveLocalInfo ();
                        local_info.Used = true;
 
@@ -4793,6 +4747,19 @@ namespace Mono.CSharp {
 
                        return Name == pr.Name;
                }
+
+               public override void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       //
+                       // ParameterReferences might already be a reference
+                       //
+                       if (IsRef) {
+                               EmitLoad (ec);
+                               return;
+                       }
+
+                       base.AddressOf (ec, mode);
+               }
                
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
@@ -4820,7 +4787,7 @@ namespace Mono.CSharp {
                // the type as it is expected, but when we generate the code, we generate
                // the alternate kind of code.
                //
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (!DoResolveBase (ec))
                                return null;
@@ -4841,25 +4808,22 @@ namespace Mono.CSharp {
                        if (!DoResolveBase (ec))
                                return null;
 
-                       // HACK: parameters are not captured when probing is on
-                       if (!ec.IsInProbingMode)
-                               SetAssigned (ec);
-
+                       SetAssigned (ec);
                        return this;
                }
 
-               static public void EmitLdArg (ILGenerator ig, int x)
+               static public void EmitLdArg (EmitContext ec, int x)
                {
                        switch (x) {
-                       case 0: ig.Emit (OpCodes.Ldarg_0); break;
-                       case 1: ig.Emit (OpCodes.Ldarg_1); break;
-                       case 2: ig.Emit (OpCodes.Ldarg_2); break;
-                       case 3: ig.Emit (OpCodes.Ldarg_3); break;
+                       case 0: ec.Emit (OpCodes.Ldarg_0); break;
+                       case 1: ec.Emit (OpCodes.Ldarg_1); break;
+                       case 2: ec.Emit (OpCodes.Ldarg_2); break;
+                       case 3: ec.Emit (OpCodes.Ldarg_3); break;
                        default:
                                if (x > byte.MaxValue)
-                                       ig.Emit (OpCodes.Ldarg, x);
+                                       ec.Emit (OpCodes.Ldarg, x);
                                else
-                                       ig.Emit (OpCodes.Ldarg_S, (byte) x);
+                                       ec.Emit (OpCodes.Ldarg_S, (byte) x);
                                break;
                        }
                }
@@ -4914,14 +4878,10 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Call", args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       // Don't resolve already resolved expression
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-                       
-                       Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
-                       if (expr_resolved == null)
+                       Expression member_expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+                       if (member_expr == null)
                                return null;
 
                        //
@@ -4931,99 +4891,51 @@ namespace Mono.CSharp {
                        if (arguments != null && !arguments_resolved)
                                arguments.Resolve (ec, out dynamic_arg);
 
-                       Type expr_type = expr_resolved.Type;
-                       mg = expr_resolved as MethodGroupExpr;
-
-                       if (dynamic_arg || TypeManager.IsDynamicType (expr_type)) {
-                               Arguments args;
-                               DynamicMemberBinder dmb = expr_resolved as DynamicMemberBinder;
-                               if (dmb != null) {
-                                       args = dmb.Arguments;
-                                       if (arguments != null)
-                                               args.AddRange (arguments);
-                               } else if (mg == null) {
-                                       if (arguments == null)
-                                               args = new Arguments (1);
-                                       else
-                                               args = arguments;
-
-                                       args.Insert (0, new Argument (expr_resolved));
-                                       expr = null;
-                               } else {
-                                       if (mg.IsBase) {
-                                               ec.Report.Error (1971, loc,
-                                                       "The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access",
-                                                       mg.Name);
-                                               return null;
-                                       }
+                       TypeSpec expr_type = member_expr.Type;
+                       mg = member_expr as MethodGroupExpr;
 
-                                       args = arguments;
+                       bool dynamic_member = expr_type == InternalType.Dynamic;
 
-                                       if (mg.IsStatic != mg.IsInstance) {
-                                               if (args == null)
-                                                       args = new Arguments (1);
+                       if (!dynamic_member) {
+                               Expression invoke = null;
 
-                                               if (mg.IsStatic) {
-                                                       args.Insert (0, new Argument (new TypeOf (new TypeExpression (mg.DeclaringType, loc), loc).Resolve (ec), Argument.AType.DynamicTypeName));
-                                               } else {
-                                                       MemberAccess ma = expr as MemberAccess;
-                                                       if (ma != null)
-                                                               args.Insert (0, new Argument (ma.Left.Resolve (ec)));
-                                                       else
-                                                               args.Insert (0, new Argument (new This (loc).Resolve (ec)));
+                               if (mg == null) {
+                                       if (expr_type != null && TypeManager.IsDelegateType (expr_type)) {
+                                               invoke = new DelegateInvocation (member_expr, arguments, loc);
+                                               invoke = invoke.Resolve (ec);
+                                               if (invoke == null || !dynamic_arg)
+                                                       return invoke;
+                                       } else {
+                                               MemberExpr me = member_expr as MemberExpr;
+                                               if (me == null) {
+                                                       member_expr.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc);
+                                                       return null;
                                                }
-                                       }
-                               }
 
-                               return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec);
-                       }
+                                               mg = ec.LookupExtensionMethod (me.Type, me.Name, -1, loc);
+                                               if (mg == null) {
+                                                       ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
+                                                               member_expr.GetSignatureForError ());
+                                                       return null;
+                                               }
 
-                       if (mg == null) {
-                               if (expr_type != null && TypeManager.IsDelegateType (expr_type)){
-                                       return (new DelegateInvocation (
-                                               expr_resolved, arguments, loc)).Resolve (ec);
+                                               ((ExtensionMethodGroupExpr) mg).ExtensionExpression = me.InstanceExpression;
+                                       }
                                }
 
-                               MemberExpr me = expr_resolved as MemberExpr;
-                               if (me == null) {
-                                       expr_resolved.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc);
-                                       return null;
-                               }
-                               
-                               mg = ec.LookupExtensionMethod (me.Type, me.Name, loc);
-                               if (mg == null) {
-                                       ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
-                                               expr_resolved.GetSignatureForError ());
-                                       return null;
+                               if (invoke == null) {
+                                       mg = DoResolveOverload (ec);
+                                       if (mg == null)
+                                               return null;
                                }
-
-                               ((ExtensionMethodGroupExpr)mg).ExtensionExpression = me.InstanceExpression;
                        }
 
-                       mg = DoResolveOverload (ec);
-                       if (mg == null)
-                               return null;
+                       if (dynamic_arg || dynamic_member)
+                               return DoResolveDynamic (ec, member_expr);
 
-                       MethodInfo method = (MethodInfo)mg;
+                       var method = mg.BestCandidate;
                        if (method != null) {
-                               type = TypeManager.TypeToCoreType (method.ReturnType);
-
-                               // TODO: this is a copy of mg.ResolveMemberAccess method
-                               Expression iexpr = mg.InstanceExpression;
-                               if (method.IsStatic) {
-                                       if (iexpr == null ||
-                                               iexpr is This || iexpr is EmptyExpression ||
-                                               mg.IdenticalTypeName) {
-                                               mg.InstanceExpression = null;
-                                       } else {
-                                               MemberExpr.error176 (ec, loc, mg.GetSignatureForError ());
-                                               return null;
-                                       }
-                               } else {
-                                       if (iexpr == null || iexpr == EmptyExpression.Null) {
-                                               SimpleName.Error_ObjectRefRequired (ec, loc, mg.GetSignatureForError ());
-                                       }
-                               }
+                               type = method.ReturnType;
                        }
                
                        //
@@ -5051,14 +4963,63 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
+               {
+                       Arguments args;
+                       DynamicMemberBinder dmb = memberExpr as DynamicMemberBinder;
+                       if (dmb != null) {
+                               args = dmb.Arguments;
+                               if (arguments != null)
+                                       args.AddRange (arguments);
+                       } else if (mg == null) {
+                               if (arguments == null)
+                                       args = new Arguments (1);
+                               else
+                                       args = arguments;
+
+                               args.Insert (0, new Argument (memberExpr));
+                               this.expr = null;
+                       } else {
+                               if (mg.IsBase) {
+                                       ec.Report.Error (1971, loc,
+                                               "The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access",
+                                               mg.Name);
+                                       return null;
+                               }
+
+                               if (arguments == null)
+                                       args = new Arguments (1);
+                               else
+                                       args = arguments;
+
+                               MemberAccess ma = expr as MemberAccess;
+                               if (ma != null) {
+                                       var left_type = ma.Left as TypeExpr;
+                                       if (left_type != null) {
+                                               args.Insert (0, new Argument (new TypeOf (left_type, loc).Resolve (ec), Argument.AType.DynamicTypeName));
+                                       } else {
+                                               args.Insert (0, new Argument (ma.Left));
+                                       }
+                               } else {        // is SimpleName
+                                       if (ec.IsStatic) {
+                                               args.Insert (0, new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc).Resolve (ec), Argument.AType.DynamicTypeName));
+                                       } else {
+                                               args.Insert (0, new Argument (new This (loc).Resolve (ec)));
+                                       }
+                               }
+                       }
+
+                       return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec);
+               }
+
                protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec)
                {
                        return mg.OverloadResolve (ec, ref arguments, false, loc);
                }
 
-               public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodBase method, Location loc)
+               public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodSpec method, Location loc)
                {
-                       if (!TypeManager.IsSpecialMethod (method))
+                       if (!method.IsReservedMethod)
                                return false;
 
                        if (ec.HasSet (ResolveContext.Options.InvokeSpecialName))
@@ -5066,14 +5027,14 @@ namespace Mono.CSharp {
 
                        ec.Report.SymbolRelatedToPreviousError (method);
                        ec.Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor",
-                               TypeManager.CSharpSignature (method, true));
+                               method.GetSignatureForError ());
        
                        return true;
                }
 
-               static Type[] GetVarargsTypes (MethodBase mb, Arguments arguments)
+               static Type[] GetVarargsTypes (MethodSpec mb, Arguments arguments)
                {
-                       AParametersCollection pd = TypeManager.GetParameterData (mb);
+                       AParametersCollection pd = mb.Parameters;
                        
                        Argument a = arguments [pd.Count - 1];
                        Arglist list = (Arglist) a.Expr;
@@ -5081,28 +5042,6 @@ namespace Mono.CSharp {
                        return list.ArgumentTypes;
                }
 
-               /// <summary>
-               /// This checks the ConditionalAttribute on the method 
-               /// </summary>
-               public static bool IsMethodExcluded (MethodBase method, Location loc)
-               {
-                       if (method.IsConstructor)
-                               return false;
-
-                       method = TypeManager.DropGenericMethodArguments (method);
-                       if (TypeManager.IsBeingCompiled (method)) {
-                               IMethodData md = TypeManager.GetMethod (method);
-                               if (md != null)
-                                       return md.IsExcluded ();
-
-                               // For some methods (generated by delegate class) GetMethod returns null
-                               // because they are not included in builder_to_method table
-                               return false;
-                       }
-
-                       return AttributeTester.IsConditionalMethodExcluded (method, loc);
-               }
-
                /// <remarks>
                ///   is_base tells whether we want to force the use of the `call'
                ///   opcode instead of using callvirt.  Call is required to call
@@ -5120,7 +5059,7 @@ namespace Mono.CSharp {
                /// </remarks>
                public static void EmitCall (EmitContext ec, bool is_base,
                                             Expression instance_expr,
-                                            MethodBase method, Arguments Arguments, Location loc)
+                                            MethodSpec method, Arguments Arguments, Location loc)
                {
                        EmitCall (ec, is_base, instance_expr, method, Arguments, loc, false, false);
                }
@@ -5133,77 +5072,73 @@ namespace Mono.CSharp {
                // only have been evaluated once.
                public static void EmitCall (EmitContext ec, bool is_base,
                                             Expression instance_expr,
-                                            MethodBase method, Arguments Arguments, Location loc,
+                                            MethodSpec method, Arguments Arguments, Location loc,
                                             bool dup_args, bool omit_args)
                {
-                       ILGenerator ig = ec.ig;
-                       bool struct_call = false;
-                       bool this_call = false;
                        LocalTemporary this_arg = null;
 
-                       Type decl_type = method.DeclaringType;
+                       TypeSpec decl_type = method.DeclaringType;
 
-                       if (IsMethodExcluded (method, loc))
+                       // Speed up the check by not doing it on not allowed targets
+                       if (method.ReturnType == TypeManager.void_type && method.IsConditionallyExcluded (loc))
                                return;
-                       
-                       bool is_static = method.IsStatic;
-                       if (!is_static){
-                               this_call = instance_expr is This;
-                               if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type))
-                                       struct_call = true;
+
+                       OpCode call_op;
+                       TypeSpec iexpr_type;
+
+                       if (method.IsStatic) {
+                               iexpr_type = null;
+                               call_op = OpCodes.Call;
+                       } else {
+                               iexpr_type = instance_expr.Type;
+
+                               if (is_base || decl_type.IsStruct || decl_type.IsEnum || (instance_expr is This && !method.IsVirtual)) {
+                                       call_op = OpCodes.Call;
+                               } else {
+                                       call_op = OpCodes.Callvirt;
+                               }
 
                                //
                                // If this is ourselves, push "this"
                                //
                                if (!omit_args) {
-                                       Type t = null;
-                                       Type iexpr_type = instance_expr.Type;
+                                       TypeSpec t = iexpr_type;
 
                                        //
                                        // Push the instance expression
                                        //
-                                       if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) {
+                                       if ((iexpr_type.IsStruct && (call_op == OpCodes.Callvirt || (call_op == OpCodes.Call && decl_type == iexpr_type))) ||
+                                               iexpr_type.IsGenericParameter || TypeManager.IsNullableType (decl_type)) {
                                                //
-                                               // Special case: calls to a function declared in a 
-                                               // reference-type with a value-type argument need
-                                               // to have their value boxed.
-                                               if (TypeManager.IsStruct (decl_type) ||
-                                                   TypeManager.IsGenericParameter (iexpr_type)) {
-                                                       //
-                                                       // If the expression implements IMemoryLocation, then
-                                                       // we can optimize and use AddressOf on the
-                                                       // return.
-                                                       //
-                                                       // If not we have to use some temporary storage for
-                                                       // it.
-                                                       if (instance_expr is IMemoryLocation) {
-                                                               ((IMemoryLocation)instance_expr).
-                                                                       AddressOf (ec, AddressOp.LoadStore);
-                                                       } else {
-                                                               LocalTemporary temp = new LocalTemporary (iexpr_type);
-                                                               instance_expr.Emit (ec);
-                                                               temp.Store (ec);
-                                                               temp.AddressOf (ec, AddressOp.Load);
-                                                       }
-
-                                                       // avoid the overhead of doing this all the time.
-                                                       if (dup_args)
-                                                               t = TypeManager.GetReferenceType (iexpr_type);
+                                               // If the expression implements IMemoryLocation, then
+                                               // we can optimize and use AddressOf on the
+                                               // return.
+                                               //
+                                               // If not we have to use some temporary storage for
+                                               // it.
+                                               var iml = instance_expr as IMemoryLocation;
+                                               if (iml != null) {
+                                                       iml.AddressOf (ec, AddressOp.LoadStore);
                                                } else {
+                                                       LocalTemporary temp = new LocalTemporary (iexpr_type);
                                                        instance_expr.Emit (ec);
-                                                       
-                                                       // FIXME: should use instance_expr is IMemoryLocation + constraint.
-                                                       // to help JIT to produce better code
-                                                       ig.Emit (OpCodes.Box, instance_expr.Type);
-                                                       t = TypeManager.object_type;
+                                                       temp.Store (ec);
+                                                       temp.AddressOf (ec, AddressOp.Load);
                                                }
+
+                                               // avoid the overhead of doing this all the time.
+                                               if (dup_args)
+                                                       t = ReferenceContainer.MakeType (iexpr_type);
+                                       } else if (iexpr_type.IsEnum || iexpr_type.IsStruct) {
+                                               instance_expr.Emit (ec);
+                                               ec.Emit (OpCodes.Box, iexpr_type);
+                                               t = iexpr_type = TypeManager.object_type;
                                        } else {
                                                instance_expr.Emit (ec);
-                                               t = instance_expr.Type;
                                        }
 
                                        if (dup_args) {
-                                               ig.Emit (OpCodes.Dup);
+                                               ec.Emit (OpCodes.Dup);
                                                if (Arguments != null && Arguments.Count != 0) {
                                                        this_arg = new LocalTemporary (t);
                                                        this_arg.Store (ec);
@@ -5215,19 +5150,13 @@ namespace Mono.CSharp {
                        if (!omit_args && Arguments != null)
                                Arguments.Emit (ec, dup_args, this_arg);
 
-                       OpCode call_op;
-                       if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) {
-                               call_op = OpCodes.Call;
-                       } else {
-                               call_op = OpCodes.Callvirt;
-                               
-                               if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
-                                       ig.Emit (OpCodes.Constrained, instance_expr.Type);
+                       if (call_op == OpCodes.Callvirt && (iexpr_type.IsGenericParameter || iexpr_type.IsStruct)) {
+                               ec.Emit (OpCodes.Constrained, iexpr_type);
                        }
 
-                       if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
+                       if (method.Parameters.HasArglist) {
                                Type[] varargs_types = GetVarargsTypes (method, Arguments);
-                               ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
+                               ec.Emit (call_op, method, varargs_types);
                                return;
                        }
 
@@ -5237,10 +5166,7 @@ namespace Mono.CSharp {
                        // and DoFoo is not virtual, you can omit the callvirt,
                        // because you don't need the null checking behavior.
                        //
-                       if (method is MethodInfo)
-                               ig.Emit (call_op, (MethodInfo) method);
-                       else
-                               ig.Emit (call_op, (ConstructorInfo) method);
+                       ec.Emit (call_op, method);
                }
 
                public override void Emit (EmitContext ec)
@@ -5255,8 +5181,8 @@ namespace Mono.CSharp {
                        // 
                        // Pop the return value if there is one
                        //
-                       if (TypeManager.TypeToCoreType (type) != TypeManager.void_type)
-                               ec.ig.Emit (OpCodes.Pop);
+                       if (type != TypeManager.void_type)
+                               ec.Emit (OpCodes.Pop);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -5269,35 +5195,15 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       return MakeExpression (ctx, mg.InstanceExpression, (MethodInfo) mg, arguments);
+                       return MakeExpression (ctx, mg.InstanceExpression, (MethodSpec) mg, arguments);
                }
 
-               public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodInfo mi, Arguments args)
+               public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args)
                {
                        var instance_expr = instance == null ? null : instance.MakeExpression (ctx);
-                       SLE.Expression expr = SLE.Expression.Call (instance_expr, mi,
-                               Arguments.MakeExpression (args, ctx));
-
-                       if (mi.ReturnType == typeof (void)) {
-                               expr = SLE.Expression.Block (
-                                       expr,
-                                       SLE.Expression.Default (typeof (object)));
-                       }
-
-                       return expr;
-               }
-#endif
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       mg.MutateHoistedGenericType (storey);
-                       type = storey.MutateType (type);
-                       if (arguments != null) {
-                               arguments.MutateHoistedGenericType (storey);
-                       }
+                       return SLE.Expression.Call (instance_expr, (MethodInfo) mi.GetMetaInfo (), Arguments.MakeExpression (args, ctx));
                }
        }
 
@@ -5305,18 +5211,16 @@ namespace Mono.CSharp {
        ///    Implements the new expression 
        /// </summary>
        public class New : ExpressionStatement, IMemoryLocation {
-               Arguments Arguments;
+               protected Arguments Arguments;
 
                //
                // During bootstrap, it contains the RequestedType,
                // but if `type' is not null, it *might* contain a NewDelegate
                // (because of field multi-initialization)
                //
-               Expression RequestedType;
-
-               MethodGroupExpr method;
+               protected Expression RequestedType;
 
-               bool is_type_parameter;
+               protected MethodGroupExpr method;
 
                public New (Expression requested_type, Arguments arguments, Location l)
                {
@@ -5328,7 +5232,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// Converts complex core type syntax like 'new int ()' to simple constant
                /// </summary>
-               public static Constant Constantify (Type t)
+               public static Constant Constantify (TypeSpec t)
                {
                        if (t == TypeManager.int32_type)
                                return new IntConstant (0, Location.Null);
@@ -5357,7 +5261,7 @@ namespace Mono.CSharp {
                        if (t == TypeManager.decimal_type)
                                return new DecimalConstant (0, Location.Null);
                        if (TypeManager.IsEnumType (t))
-                               return new EnumConstant (Constantify (TypeManager.GetEnumUnderlyingType (t)), t);
+                               return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t)), t);
                        if (TypeManager.IsNullableType (t))
                                return Nullable.LiftedNull.Create (t, Location.Null);
 
@@ -5378,7 +5282,7 @@ namespace Mono.CSharp {
                        // Turn the call into:
                        // (the-interface-stated) (new class-referenced-in-coclassattribute ())
                        //
-                       Type real_class = AttributeTester.GetCoClassAttribute (type);
+                       var real_class = type.MemberDefinition.GetAttributeCoClass ();
                        if (real_class == null)
                                return null;
 
@@ -5394,29 +5298,16 @@ namespace Mono.CSharp {
                                args = new Arguments (1);
                                args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
                        } else {
-                               args = Arguments.CreateForExpressionTree (ec, Arguments,
+                               args = Arguments.CreateForExpressionTree (ec,
+                                       Arguments,
                                        method.CreateExpressionTree (ec));
                        }
 
                        return CreateExpressionFactoryCall (ec, "New", args);
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       //
-                       // The New DoResolve might be called twice when initializing field
-                       // expressions (see EmitFieldInitializers, the call to
-                       // GetInitializerExpression will perform a resolve on the expression,
-                       // and later the assign will trigger another resolution
-                       //
-                       // This leads to bugs (#37014)
-                       //
-                       if (type != null){
-                               if (RequestedType is NewDelegate)
-                                       return RequestedType;
-                               return this;
-                       }
-
                        TypeExpr texpr = RequestedType.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return null;
@@ -5432,44 +5323,40 @@ namespace Mono.CSharp {
                        if (Arguments == null) {
                                Constant c = Constantify (type);
                                if (c != null)
-                                       return ReducedExpression.Create (c, this);
+                                       return ReducedExpression.Create (c.Resolve (ec), this);
                        }
 
                        if (TypeManager.IsDelegateType (type)) {
                                return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
                        }
 
-                       if (TypeManager.IsGenericParameter (type)) {
-                               GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type);
-
-                               if ((gc == null) || (!gc.HasConstructorConstraint && !gc.IsValueType)) {
+                       var tparam = type as TypeParameterSpec;
+                       if (tparam != null) {
+                               if (!tparam.HasSpecialConstructor && !tparam.HasSpecialStruct) {
                                        ec.Report.Error (304, loc,
-                                               "Cannot create an instance of the variable type '{0}' because it doesn't have the new() constraint",
+                                               "Cannot create an instance of the variable type `{0}' because it does not have the new() constraint",
                                                TypeManager.CSharpName (type));
-                                       return null;
                                }
 
                                if ((Arguments != null) && (Arguments.Count != 0)) {
                                        ec.Report.Error (417, loc,
                                                "`{0}': cannot provide arguments when creating an instance of a variable type",
                                                TypeManager.CSharpName (type));
-                                       return null;
                                }
 
                                if (TypeManager.activator_create_instance == null) {
-                                       Type activator_type = TypeManager.CoreLookupType (ec.Compiler, "System", "Activator", Kind.Class, true);
+                                       TypeSpec activator_type = TypeManager.CoreLookupType (ec.Compiler, "System", "Activator", MemberKind.Class, true);
                                        if (activator_type != null) {
                                                TypeManager.activator_create_instance = TypeManager.GetPredefinedMethod (
-                                                       activator_type, "CreateInstance", loc, Type.EmptyTypes);
+                                                       activator_type, MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null), loc);
                                        }
                                }
 
-                               is_type_parameter = true;
                                eclass = ExprClass.Value;
                                return this;
                        }
 
-                       if (type.IsAbstract && type.IsSealed) {
+                       if (type.IsStatic) {
                                ec.Report.SymbolRelatedToPreviousError (type);
                                ec.Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type));
                                return null;
@@ -5498,17 +5385,14 @@ namespace Mono.CSharp {
                                return this;
 
                        // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
-                       Expression ml = MemberLookupFinal (ec, type, type, ConstructorInfo.ConstructorName,
-                               MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+                       Expression ml = MemberLookupFinal (ec, type, type, ConstructorInfo.ConstructorName, 0,
+                               MemberKind.Constructor, BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly, loc);
 
+                       bool dynamic;
                        if (Arguments != null) {
-                               bool dynamic;
                                Arguments.Resolve (ec, out dynamic);
-
-                               if (dynamic) {
-                                       Arguments.Insert (0, new Argument (new TypeOf (texpr, loc).Resolve (ec), Argument.AType.DynamicTypeName));
-                                       return new DynamicConstructorBinder (type, Arguments, loc).Resolve (ec);
-                               }
+                       } else {
+                               dynamic = false;
                        }
 
                        if (ml == null)
@@ -5524,19 +5408,21 @@ namespace Mono.CSharp {
                        if (method == null)
                                return null;
 
+                       if (dynamic) {
+                               Arguments.Insert (0, new Argument (new TypeOf (texpr, loc).Resolve (ec), Argument.AType.DynamicTypeName));
+                               return new DynamicConstructorBinder (type, Arguments, loc).Resolve (ec);
+                       }
+
                        return this;
                }
 
                bool DoEmitTypeParameter (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
-                       MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod (
-                               new Type [] { type });
+                       var ctor_factory = TypeManager.activator_create_instance.MakeGenericMethod (type);
+                       var tparam = (TypeParameterSpec) type;
 
-                       GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type);
-                       if (gc.HasReferenceTypeConstraint || gc.HasClassConstraint) {
-                               ig.Emit (OpCodes.Call, ci);
+                       if (tparam.IsReferenceType) {
+                               ec.Emit (OpCodes.Call, ctor_factory);
                                return true;
                        }
 
@@ -5545,25 +5431,25 @@ namespace Mono.CSharp {
                        // you can't share LocalBuilders among ILGeneators.
                        LocalTemporary temp = new LocalTemporary (type);
 
-                       Label label_activator = ig.DefineLabel ();
-                       Label label_end = ig.DefineLabel ();
+                       Label label_activator = ec.DefineLabel ();
+                       Label label_end = ec.DefineLabel ();
 
                        temp.AddressOf (ec, AddressOp.Store);
-                       ig.Emit (OpCodes.Initobj, type);
+                       ec.Emit (OpCodes.Initobj, type);
 
                        temp.Emit (ec);
-                       ig.Emit (OpCodes.Box, type);
-                       ig.Emit (OpCodes.Brfalse, label_activator);
+                       ec.Emit (OpCodes.Box, type);
+                       ec.Emit (OpCodes.Brfalse, label_activator);
 
                        temp.AddressOf (ec, AddressOp.Store);
-                       ig.Emit (OpCodes.Initobj, type);
+                       ec.Emit (OpCodes.Initobj, type);
                        temp.Emit (ec);
-                       ig.Emit (OpCodes.Br_S, label_end);
+                       ec.Emit (OpCodes.Br_S, label_end);
 
-                       ig.MarkLabel (label_activator);
+                       ec.MarkLabel (label_activator);
 
-                       ig.Emit (OpCodes.Call, ci);
-                       ig.MarkLabel (label_end);
+                       ec.Emit (OpCodes.Call, ctor_factory);
+                       ec.MarkLabel (label_end);
                        return true;
                }
 
@@ -5597,7 +5483,6 @@ namespace Mono.CSharp {
                public virtual bool Emit (EmitContext ec, IMemoryLocation target)
                {
                        bool is_value_type = TypeManager.IsValueType (type);
-                       ILGenerator ig = ec.ig;
                        VariableReference vr = target as VariableReference;
 
                        if (target != null && is_value_type && (vr != null || method == null)) {
@@ -5611,26 +5496,20 @@ namespace Mono.CSharp {
 
                        if (is_value_type) {
                                if (method == null) {
-                                       ig.Emit (OpCodes.Initobj, type);
+                                       ec.Emit (OpCodes.Initobj, type);
                                        return false;
                                }
 
                                if (vr != null) {
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                                       ec.Emit (OpCodes.Call, method.BestCandidate);
                                        return false;
                                }
                        }
                        
-                       if (is_type_parameter)
+                       if (type is TypeParameterSpec)
                                return DoEmitTypeParameter (ec);                        
 
-                       ConstructorInfo ci = (ConstructorInfo) method;
-#if MS_COMPATIBLE
-                       if (TypeManager.IsGenericType (type) && type.IsGenericTypeDefinition)
-                               ci = TypeBuilder.GetConstructor (type, ci);
-#endif
-
-                       ig.Emit (OpCodes.Newobj, ci);
+                       ec.Emit (OpCodes.Newobj, method.BestCandidate);
                        return true;
                }
 
@@ -5655,7 +5534,7 @@ namespace Mono.CSharp {
                        }
 
                        if (Emit (ec, v))
-                               ec.ig.Emit (OpCodes.Pop);
+                               ec.Emit (OpCodes.Pop);
                }
 
                public virtual bool HasInitializer {
@@ -5673,7 +5552,7 @@ namespace Mono.CSharp {
                {
                        LocalTemporary value_target = new LocalTemporary (type);
 
-                       if (is_type_parameter) {
+                       if (type is TypeParameterSpec) {
                                DoEmitTypeParameter (ec);
                                value_target.Store (ec);
                                value_target.AddressOf (ec, mode);
@@ -5693,12 +5572,12 @@ namespace Mono.CSharp {
                        value_target.AddressOf (ec, AddressOp.Store);
 
                        if (method == null) {
-                               ec.ig.Emit (OpCodes.Initobj, type);
+                               ec.Emit (OpCodes.Initobj, type);
                        } else {
                                if (Arguments != null)
                                        Arguments.Emit (ec);
 
-                               ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                               ec.Emit (OpCodes.Call, method.BestCandidate);
                        }
                        
                        value_target.AddressOf (ec, mode);
@@ -5715,90 +5594,142 @@ namespace Mono.CSharp {
                        }
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       return SLE.Expression.New ((ConstructorInfo) method, Arguments.MakeExpression (Arguments, ctx));
+                       return SLE.Expression.New ((ConstructorInfo) method.BestCandidate.GetMetaInfo (), Arguments.MakeExpression (Arguments, ctx));
                }
-#endif
+       }
+
+       public class ArrayInitializer : Expression
+       {
+               List<Expression> elements;
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               public ArrayInitializer (List<Expression> init, Location loc)
                {
-                       if (method != null) {
-                               method.MutateHoistedGenericType (storey);
-                               if (Arguments != null) {
-                                       Arguments.MutateHoistedGenericType (storey);
-                               }
-                       }
+                       elements = init;
+                       this.loc = loc;
+               }
 
-                       type = storey.MutateType (type);
+               public ArrayInitializer (int count, Location loc)
+               {
+                       elements = new List<Expression> (count);
+                       this.loc = loc;
                }
-       }
 
-       /// <summary>
-       ///   14.5.10.2: Represents an array creation expression.
-       /// </summary>
-       ///
-       /// <remarks>
-       ///   There are two possible scenarios here: one is an array creation
-       ///   expression that specifies the dimensions and optionally the
-       ///   initialization data and the other which does not need dimensions
-       ///   specified but where initialization data is mandatory.
+               public ArrayInitializer (Location loc)
+                       : this (4, loc)
+               {
+               }
+
+               public void Add (Expression expr)
+               {
+                       elements.Add (expr);
+               }
+
+               public override Expression CreateExpressionTree (ResolveContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       var target = (ArrayInitializer) t;
+
+                       target.elements = new List<Expression> (elements.Count);
+                       foreach (var element in elements)
+                               target.elements.Add (element.Clone (clonectx));
+               }
+
+               public int Count {
+                       get { return elements.Count; }
+               }
+
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new InternalErrorException ("Missing Resolve call");
+               }
+
+               public Expression this [int index] {
+                       get { return elements [index]; }
+               }
+       }
+
+       /// <summary>
+       ///   14.5.10.2: Represents an array creation expression.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   There are two possible scenarios here: one is an array creation
+       ///   expression that specifies the dimensions and optionally the
+       ///   initialization data and the other which does not need dimensions
+       ///   specified but where initialization data is mandatory.
        /// </remarks>
-       public class ArrayCreation : Expression {
+       public class ArrayCreation : Expression
+       {
                FullNamedExpression requested_base_type;
-               ArrayList initializers;
+               ArrayInitializer initializers;
 
                //
                // The list of Argument types.
                // This is used to construct the `newarray' or constructor signature
                //
-               protected ArrayList arguments;
+               protected List<Expression> arguments;
                
-               protected Type array_element_type;
-               bool expect_initializers = false;
+               protected TypeSpec array_element_type;
                int num_arguments = 0;
                protected int dimensions;
-               protected readonly string rank;
+               protected readonly ComposedTypeSpecifier rank;
                Expression first_emit;
                LocalTemporary first_emit_temp;
 
                protected List<Expression> array_data;
 
-               IDictionary bounds;
+               Dictionary<int, int> bounds;
 
                // The number of constants in array initializers
                int const_initializers_count;
                bool only_constant_initializers;
-               
-               public ArrayCreation (FullNamedExpression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
+
+               public ArrayCreation (FullNamedExpression requested_base_type, List<Expression> exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l)
+                       : this (requested_base_type, rank, initializers, l)
+               {
+                       arguments = new List<Expression> (exprs);
+                       num_arguments = arguments.Count;
+               }
+
+               //
+               // For expressions like int[] foo = new int[] { 1, 2, 3 };
+               //
+               public ArrayCreation (FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)
                {
                        this.requested_base_type = requested_base_type;
-                       this.initializers = initializers;
                        this.rank = rank;
-                       loc = l;
-
-                       arguments = new ArrayList (exprs.Count);
+                       this.initializers = initializers;
+                       this.loc = loc;
 
-                       foreach (Expression e in exprs) {
-                               arguments.Add (e);
-                               num_arguments++;
-                       }
+                       if (rank != null)
+                               num_arguments = rank.Dimension;
                }
 
-               public ArrayCreation (FullNamedExpression requested_base_type, string rank, ArrayList initializers, Location l)
+               //
+               // For compiler generated single dimensional arrays only
+               //
+               public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc)
+                       : this (requested_base_type, ComposedTypeSpecifier.SingleDimension, initializers, loc)
                {
-                       this.requested_base_type = requested_base_type;
-                       this.initializers = initializers;
-                       this.rank = rank;
-                       loc = l;
+               }
 
-                       //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
-                       //
-                       //string tmp = rank.Substring (rank.LastIndexOf ('['));
-                       //
-                       //dimensions = tmp.Length - 1;
-                       expect_initializers = true;
+               //
+               // For expressions like int[] foo = { 1, 2, 3 };
+               //
+               public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers)
+                       : this (requested_base_type, null, initializers, initializers.Location)
+               {
                }
 
                protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
@@ -5806,39 +5737,65 @@ namespace Mono.CSharp {
                        ec.Report.Error (248, loc, "Cannot create an array with a negative size");
                }
 
-               bool CheckIndices (ResolveContext ec, ArrayList probe, int idx, bool specified_dims, int child_bounds)
+               bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds)
                {
+                       if (initializers != null && bounds == null) {
+                               //
+                               // We use this to store all the date values in the order in which we
+                               // will need to store them in the byte blob later
+                               //
+                               array_data = new List<Expression> ();
+                               bounds = new Dictionary<int, int> ();
+                       }
+
                        if (specified_dims) { 
-                               Expression a = (Expression) arguments [idx];
+                               Expression a = arguments [idx];
                                a = a.Resolve (ec);
                                if (a == null)
                                        return false;
 
-                               Constant c = a as Constant;
-                               if (c != null) {
-                                       c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Location);
-                               }
-
-                               if (c == null) {
-                                       ec.Report.Error (150, a.Location, "A constant value is expected");
+                               a = ConvertExpressionToArrayIndex (ec, a);
+                               if (a == null)
                                        return false;
-                               }
 
-                               int value = (int) c.GetValue ();
-                               
-                               if (value != probe.Count) {
-                                       ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value);
-                                       return false;
+                               arguments[idx] = a;
+
+                               if (initializers != null) {
+                                       Constant c = a as Constant;
+                                       if (c == null && a is ArrayIndexCast)
+                                               c = ((ArrayIndexCast) a).Child as Constant;
+
+                                       if (c == null) {
+                                               ec.Report.Error (150, a.Location, "A constant value is expected");
+                                               return false;
+                                       }
+
+                                       int value;
+                                       try {
+                                               value = System.Convert.ToInt32 (c.GetValue ());
+                                       } catch {
+                                               ec.Report.Error (150, a.Location, "A constant value is expected");
+                                               return false;
+                                       }
+
+                                       // TODO: probe.Count does not fit ulong in
+                                       if (value != probe.Count) {
+                                               ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value.ToString ());
+                                               return false;
+                                       }
+
+                                       bounds[idx] = value;
                                }
-                               
-                               bounds [idx] = value;
                        }
 
+                       if (initializers == null)
+                               return true;
+
                        only_constant_initializers = true;
                        for (int i = 0; i < probe.Count; ++i) {
-                               object o = probe [i];
-                               if (o is ArrayList) {
-                                       ArrayList sub_probe = o as ArrayList;
+                               var o = probe [i];
+                               if (o is ArrayInitializer) {
+                                       var sub_probe = o as ArrayInitializer;
                                        if (idx + 1 >= dimensions){
                                                ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead");
                                                return false;
@@ -5848,19 +5805,16 @@ namespace Mono.CSharp {
                                        if (!ret)
                                                return false;
                                } else if (child_bounds > 1) {
-                                       ec.Report.Error (846, ((Expression) o).Location, "A nested array initializer was expected");
+                                       ec.Report.Error (846, o.Location, "A nested array initializer was expected");
                                } else {
-                                       Expression element = ResolveArrayElement (ec, (Expression) o);
+                                       Expression element = ResolveArrayElement (ec, o);
                                        if (element == null)
                                                continue;
 
                                        // Initializers with the default values can be ignored
                                        Constant c = element as Constant;
                                        if (c != null) {
-                                               if (c.IsDefaultInitializer (array_element_type)) {
-                                                       element = null;
-                                               }
-                                               else {
+                                               if (!c.IsDefaultInitializer (array_element_type)) {
                                                        ++const_initializers_count;
                                                }
                                        } else {
@@ -5897,9 +5851,6 @@ namespace Mono.CSharp {
                        if (array_data != null) {
                                for (int i = 0; i < array_data.Count; ++i) {
                                        Expression e = array_data [i];
-                                       if (e == null)
-                                               e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc);
-
                                        args.Add (new Argument (e.CreateExpressionTree (ec)));
                                }
                        }
@@ -5910,14 +5861,14 @@ namespace Mono.CSharp {
                public void UpdateIndices ()
                {
                        int i = 0;
-                       for (ArrayList probe = initializers; probe != null;) {
-                               if (probe.Count > 0 && probe [0] is ArrayList) {
+                       for (var probe = initializers; probe != null;) {
+                               if (probe.Count > 0 && probe [0] is ArrayInitializer) {
                                        Expression e = new IntConstant (probe.Count, Location.Null);
                                        arguments.Add (e);
 
-                                       bounds [i++] =  probe.Count;
-                                       
-                                       probe = (ArrayList) probe [0];
+                                       bounds [i++] = probe.Count;
+
+                                       probe = (ArrayInitializer) probe[0];
                                        
                                } else {
                                        Expression e = new IntConstant (probe.Count, Location.Null);
@@ -5948,21 +5899,18 @@ namespace Mono.CSharp {
 
                protected bool ResolveInitializers (ResolveContext ec)
                {
-                       if (initializers == null) {
-                               return !expect_initializers;
+                       if (arguments != null) {
+                               bool res = true;
+                               for (int i = 0; i < arguments.Count; ++i) {
+                                       res &= CheckIndices (ec, initializers, i, true, dimensions);
+                                       if (initializers != null)
+                                               break;
+                               }
+
+                               return res;
                        }
-                                               
-                       //
-                       // We use this to store all the date values in the order in which we
-                       // will need to store them in the byte blob later
-                       //
-                       array_data = new List<Expression> ();
-                       bounds = new System.Collections.Specialized.HybridDictionary ();
-                       
-                       if (arguments != null)
-                               return CheckIndices (ec, initializers, 0, true, dimensions);
 
-                       arguments = new ArrayList ();
+                       arguments = new List<Expression> ();
 
                        if (!CheckIndices (ec, initializers, 0, false, dimensions))
                                return false;
@@ -5977,46 +5925,39 @@ namespace Mono.CSharp {
                //
                bool ResolveArrayType (ResolveContext ec)
                {
-                       if (requested_base_type == null) {
-                               ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
-                               return false;
-                       }
-
                        if (requested_base_type is VarExpr) {
                                ec.Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer");
                                return false;
                        }
                        
-                       StringBuilder array_qualifier = new StringBuilder (rank);
-
                        //
-                       // `In the first form allocates an array instace of the type that results
-                       // from deleting each of the individual expression from the expression list'
+                       // Lookup the type
                        //
+                       FullNamedExpression array_type_expr;
                        if (num_arguments > 0) {
-                               array_qualifier.Append ("[");
-                               for (int i = num_arguments-1; i > 0; i--)
-                                       array_qualifier.Append (",");
-                               array_qualifier.Append ("]");
+                               array_type_expr = new ComposedCast (requested_base_type, rank);
+                       } else {
+                               array_type_expr = requested_base_type;
                        }
 
-                       //
-                       // Lookup the type
-                       //
-                       TypeExpr array_type_expr;
-                       array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
                        array_type_expr = array_type_expr.ResolveAsTypeTerminal (ec, false);
                        if (array_type_expr == null)
                                return false;
 
                        type = array_type_expr.Type;
-                       array_element_type = TypeManager.GetElementType (type);
-                       dimensions = type.GetArrayRank ();
+                       var ac = type as ArrayContainer;
+                       if (ac == null) {
+                               ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
+                               return false;
+                       }
+
+                       array_element_type = ac.Element;
+                       dimensions = ac.Rank;
 
                        return true;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (type != null)
                                return this;
@@ -6025,44 +5966,15 @@ namespace Mono.CSharp {
                                return null;
 
                        //
-                       // First step is to validate the initializers and fill
-                       // in any missing bits
+                       // validate the initializers and fill in any missing bits
                        //
                        if (!ResolveInitializers (ec))
                                return null;
 
-                       for (int i = 0; i < arguments.Count; ++i) {
-                               Expression e = ((Expression) arguments[i]).Resolve (ec);
-                               if (e == null)
-                                       continue;
-
-                               arguments [i] = ConvertExpressionToArrayIndex (ec, e);
-                       }
-                                                       
                        eclass = ExprClass.Value;
                        return this;
                }
 
-               MethodInfo GetArrayMethod (int arguments)
-               {
-                       ModuleBuilder mb = RootContext.ToplevelTypes.Builder;
-
-                       Type[] arg_types = new Type[arguments];
-                       for (int i = 0; i < arguments; i++)
-                               arg_types[i] = TypeManager.int32_type;
-
-                       MethodInfo mi = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
-                                                       arg_types);
-
-                       if (mi == null) {
-                               RootContext.ToplevelTypes.Compiler.Report.Error (-6, "New invocation: Can not find a constructor for " +
-                                                 "this argument list");
-                               return null;
-                       }
-
-                       return mi; 
-               }
-
                byte [] MakeByteBlob ()
                {
                        int factor;
@@ -6070,9 +5982,9 @@ namespace Mono.CSharp {
                        byte [] element;
                        int count = array_data.Count;
 
-                       Type element_type = array_element_type;
+                       TypeSpec element_type = array_element_type;
                        if (TypeManager.IsEnumType (element_type))
-                               element_type = TypeManager.GetEnumUnderlyingType (element_type);
+                               element_type = EnumSpec.GetUnderlyingType (element_type);
 
                        factor = GetTypeSize (element_type);
                        if (factor == 0)
@@ -6221,35 +6133,14 @@ namespace Mono.CSharp {
                        var initializers = new SLE.Expression [array_data.Count];
                        for (var i = 0; i < initializers.Length; i++) {
                                if (array_data [i] == null)
-                                       initializers [i] = SLE.Expression.Default (array_element_type);
+                                       initializers [i] = SLE.Expression.Default (array_element_type.GetMetaInfo ());
                                else
                                        initializers [i] = array_data [i].MakeExpression (ctx);
                        }
 
-                       return SLE.Expression.NewArrayInit (array_element_type, initializers);
+                       return SLE.Expression.NewArrayInit (array_element_type.GetMetaInfo (), initializers);
                }
 #endif
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       array_element_type = storey.MutateType (array_element_type);
-                       type = storey.MutateType (type);
-                       if (arguments != null) {
-                               foreach (Expression e in arguments)
-                                       e.MutateHoistedGenericType (storey);
-                       }
-                       
-                       if (array_data != null) {
-                               foreach (Expression e in array_data) {
-                                       // Don't mutate values optimized away
-                                       if (e == null)
-                                               continue;
-
-                                       e.MutateHoistedGenericType (storey);
-                               }
-                       }
-               }
-
                //
                // Emits the initializers for the array
                //
@@ -6268,16 +6159,14 @@ namespace Mono.CSharp {
                        // First, the static data
                        //
                        FieldBuilder fb;
-                       ILGenerator ig = ec.ig;
                        
                        byte [] data = MakeByteBlob ();
 
                        fb = RootContext.MakeStaticData (data);
 
-                       ig.Emit (OpCodes.Dup);
-                       ig.Emit (OpCodes.Ldtoken, fb);
-                       ig.Emit (OpCodes.Call,
-                                TypeManager.void_initializearray_array_fieldhandle);
+                       ec.Emit (OpCodes.Dup);
+                       ec.Emit (OpCodes.Ldtoken, fb);
+                       ec.Emit (OpCodes.Call, TypeManager.void_initializearray_array_fieldhandle);
                }
 
                //
@@ -6288,37 +6177,22 @@ namespace Mono.CSharp {
                //
                void EmitDynamicInitializers (EmitContext ec, bool emitConstants)
                {
-                       ILGenerator ig = ec.ig;
                        int dims = bounds.Count;
-                       int [] current_pos = new int [dims];
-
-                       MethodInfo set = null;
-
-                       if (dims != 1){
-                               Type [] args = new Type [dims + 1];
-
-                               for (int j = 0; j < dims; j++)
-                                       args [j] = TypeManager.int32_type;
-                               args [dims] = array_element_type;
-
-                               set = RootContext.ToplevelTypes.Builder.GetArrayMethod (
-                                       type, "Set",
-                                       CallingConventions.HasThis | CallingConventions.Standard,
-                                       TypeManager.void_type, args);
-                       }
+                       var current_pos = new int [dims];
 
                        for (int i = 0; i < array_data.Count; i++){
 
-                               Expression e = (Expression)array_data [i];
+                               Expression e = array_data [i];
+                               var c = e as Constant;
 
                                // Constant can be initialized via StaticInitializer
-                               if (e != null && !(!emitConstants && e is Constant)) {
-                                       Type etype = e.Type;
+                               if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) {
+                                       TypeSpec etype = e.Type;
 
-                                       ig.Emit (OpCodes.Dup);
+                                       ec.Emit (OpCodes.Dup);
 
                                        for (int idx = 0; idx < dims; idx++) 
-                                               IntConstant.EmitInt (ig, current_pos [idx]);
+                                               ec.EmitInt (current_pos [idx]);
 
                                        //
                                        // If we are dealing with a struct, get the
@@ -6328,23 +6202,12 @@ namespace Mono.CSharp {
                                            (!TypeManager.IsBuiltinOrEnum (etype) ||
                                             etype == TypeManager.decimal_type)) {
 
-                                               ig.Emit (OpCodes.Ldelema, etype);
+                                               ec.Emit (OpCodes.Ldelema, etype);
                                        }
 
                                        e.Emit (ec);
 
-                                       if (dims == 1) {
-                                               bool is_stobj, has_type_arg;
-                                               OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj, out has_type_arg);
-                                               if (is_stobj)
-                                                       ig.Emit (OpCodes.Stobj, etype);
-                                               else if (has_type_arg)
-                                                       ig.Emit (op, etype);
-                                               else
-                                                       ig.Emit (op);
-                                       } else 
-                                               ig.Emit (OpCodes.Call, set);
-
+                                       ec.EmitArrayStore ((ArrayContainer) type);
                                }
                                
                                //
@@ -6352,7 +6215,7 @@ namespace Mono.CSharp {
                                //
                                for (int j = dims - 1; j >= 0; j--){
                                        current_pos [j]++;
-                                       if (current_pos [j] < (int) bounds [j])
+                                       if (current_pos [j] < bounds [j])
                                                break;
                                        current_pos [j] = 0;
                                }
@@ -6361,8 +6224,6 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        if (first_emit != null) {
                                first_emit.Emit (ec);
                                first_emit_temp.Store (ec);
@@ -6371,19 +6232,15 @@ namespace Mono.CSharp {
                        foreach (Expression e in arguments)
                                e.Emit (ec);
 
-                       if (arguments.Count == 1)
-                               ig.Emit (OpCodes.Newarr, TypeManager.TypeToReflectionType (array_element_type));
-                       else {
-                               ig.Emit (OpCodes.Newobj, GetArrayMethod (arguments.Count));
-                       }
+                       ec.EmitArrayNew ((ArrayContainer) type);
                        
                        if (initializers == null)
                                return;
 
-                       // Emit static initializer for arrays which have contain more than 4 items and
+                       // Emit static initializer for arrays which have contain more than 2 items and
                        // the static initializer will initialize at least 25% of array values.
                        // NOTE: const_initializers_count does not contain default constant values.
-                       if (const_initializers_count >= 4 && const_initializers_count * 4 > (array_data.Count) &&
+                       if (const_initializers_count > 2 && const_initializers_count * 4 > (array_data.Count) &&
                                (TypeManager.IsPrimitiveType (array_element_type) || TypeManager.IsEnumType (array_element_type))) {
                                EmitStaticInitializers (ec);
 
@@ -6397,43 +6254,40 @@ namespace Mono.CSharp {
                                first_emit_temp.Release (ec);
                }
 
-               public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
+               public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
                {
-                       if (arguments.Count != 1) {
-                               // ec.Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
-                               return base.GetAttributableValue (ec, null, out value);
+                       // no multi dimensional or jagged arrays
+                       if (arguments.Count != 1 || array_element_type.IsArray) {
+                               base.EncodeAttributeValue (rc, enc, targetType);
+                               return;
                        }
 
-                       if (array_data == null) {
-                               Expression arg = (Expression) arguments[0];
-                               object arg_value;
-                               if (arg.GetAttributableValue (ec, arg.Type, out arg_value) && arg_value is int && (int)arg_value == 0) {
-                                       value = Array.CreateInstance (array_element_type, 0);
-                                       return true;
+                       // No array covariance, except for array -> object
+                       if (type != targetType) {
+                               if (targetType != TypeManager.object_type) {
+                                       base.EncodeAttributeValue (rc, enc, targetType);
+                                       return;
                                }
 
-                               // ec.Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
-                               return base.GetAttributableValue (ec, null, out value);
+                               enc.Encode (type);
                        }
-                       
-                       Array ret = Array.CreateInstance (array_element_type, array_data.Count);
-                       object element_value;
-                       for (int i = 0; i < ret.Length; ++i)
-                       {
-                               Expression e = (Expression)array_data [i];
 
-                               // Is null when an initializer is optimized (value == predefined value)
-                               if (e == null) 
-                                       continue;
-
-                               if (!e.GetAttributableValue (ec, array_element_type, out element_value)) {
-                                       value = null;
-                                       return false;
+                       // Single dimensional array of 0 size
+                       if (array_data == null) {
+                               IntConstant ic = arguments[0] as IntConstant;
+                               if (ic == null || !ic.IsDefaultValue) {
+                                       base.EncodeAttributeValue (rc, enc, targetType);
+                               } else {
+                                       enc.Stream.Write (0);
                                }
-                               ret.SetValue (element_value, i);
+
+                               return;
+                       }
+
+                       enc.Stream.Write ((int) array_data.Count);
+                       foreach (var element in array_data) {
+                               element.EncodeAttributeValue (rc, enc, array_element_type);
                        }
-                       value = ret;
-                       return true;
                }
                
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -6444,54 +6298,45 @@ namespace Mono.CSharp {
                                target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx);
 
                        if (arguments != null){
-                               target.arguments = new ArrayList (arguments.Count);
+                               target.arguments = new List<Expression> (arguments.Count);
                                foreach (Expression e in arguments)
                                        target.arguments.Add (e.Clone (clonectx));
                        }
 
-                       if (initializers != null){
-                               target.initializers = new ArrayList (initializers.Count);
-                               foreach (object initializer in initializers)
-                                       if (initializer is ArrayList) {
-                                               ArrayList this_al = (ArrayList)initializer;
-                                               ArrayList al = new ArrayList (this_al.Count);
-                                               target.initializers.Add (al);
-                                               foreach (Expression e in this_al)
-                                                       al.Add (e.Clone (clonectx));
-                                       } else {
-                                               target.initializers.Add (((Expression)initializer).Clone (clonectx));
-                                       }
-                       }
+                       if (initializers != null)
+                               target.initializers = (ArrayInitializer) initializers.Clone (clonectx);
                }
        }
        
        //
        // Represents an implicitly typed array epxression
        //
-       public class ImplicitlyTypedArrayCreation : ArrayCreation
+       class ImplicitlyTypedArrayCreation : ArrayCreation
        {
-               public ImplicitlyTypedArrayCreation (string rank, ArrayList initializers, Location loc)
+               public ImplicitlyTypedArrayCreation (ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)
                        : base (null, rank, initializers, loc)
                {                       
-                       if (rank.Length > 2) {
-                               while (rank [++dimensions] == ',');
-                       } else {
-                               dimensions = 1;
-                       }
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               public ImplicitlyTypedArrayCreation (ArrayInitializer initializers, Location loc)
+                       : base (null, initializers, loc)
+               {
+               }
+
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (type != null)
                                return this;
 
+                       dimensions = rank.Dimension;
+
                        if (!ResolveInitializers (ec))
                                return null;
 
                        if (array_element_type == null || array_element_type == TypeManager.null_type ||
                                array_element_type == TypeManager.void_type || array_element_type == InternalType.AnonymousMethod ||
                                array_element_type == InternalType.MethodGroup ||
-                               arguments.Count != dimensions) {
+                               arguments.Count != rank.Dimension) {
                                Error_NoBestType (ec);
                                return null;
                        }
@@ -6503,7 +6348,7 @@ namespace Mono.CSharp {
                        //
                        UnifyInitializerElement (ec);
 
-                       type = TypeManager.GetConstructedType (array_element_type, rank);
+                       type = ArrayContainer.MakeType (array_element_type, dimensions);
                        eclass = ExprClass.Value;
                        return this;
                }
@@ -6562,19 +6407,18 @@ namespace Mono.CSharp {
                {
                }
 
-               public CompilerGeneratedThis (Type type, Location loc)
+               public CompilerGeneratedThis (TypeSpec type, Location loc)
                        : base (loc)
                {
                        this.type = type;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.Variable;
                        if (type == null)
                                type = ec.CurrentType;
 
-                       is_struct = type.IsValueType;
                        return this;
                }
 
@@ -6596,7 +6440,7 @@ namespace Mono.CSharp {
 
                        public void Emit (EmitContext ec)
                        {
-                               ec.ig.Emit (OpCodes.Ldarg_0);
+                               ec.Emit (OpCodes.Ldarg_0);
                        }
 
                        public void EmitAssign (EmitContext ec)
@@ -6606,19 +6450,11 @@ namespace Mono.CSharp {
 
                        public void EmitAddressOf (EmitContext ec)
                        {
-                               ec.ig.Emit (OpCodes.Ldarg_0);
+                               ec.Emit (OpCodes.Ldarg_0);
                        }
                }
 
-               Block block;
                VariableInfo variable_info;
-               protected bool is_struct;
-
-               public This (Block block, Location loc)
-               {
-                       this.loc = loc;
-                       this.block = block;
-               }
 
                public This (Location loc)
                {
@@ -6651,22 +6487,22 @@ namespace Mono.CSharp {
                }
 
                public override bool IsRef {
-                       get { return is_struct; }
+                       get { return type.IsStruct; }
                }
 
                protected override ILocalVariable Variable {
                        get { return ThisVariable.Instance; }
                }
 
-               public static bool IsThisAvailable (ResolveContext ec)
+               public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous)
                {
                        if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope))
                                return false;
 
-                       if (ec.CurrentAnonymousMethod == null)
+                       if (ignoreAnonymous || ec.CurrentAnonymousMethod == null)
                                return true;
 
-                       if (ec.CurrentType.IsValueType && ec.CurrentIterator == null)
+                       if (TypeManager.IsStruct (ec.CurrentType) && ec.CurrentIterator == null)
                                return false;
 
                        return true;
@@ -6674,13 +6510,10 @@ namespace Mono.CSharp {
 
                public bool ResolveBase (ResolveContext ec)
                {
-                       if (eclass != ExprClass.Invalid)
-                               return true;
-
                        eclass = ExprClass.Variable;
                        type = ec.CurrentType;
 
-                       if (!IsThisAvailable (ec)) {
+                       if (!IsThisAvailable (ec, false)) {
                                if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) {
                                        ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer");
                                } else if (ec.CurrentAnonymousMethod != null) {
@@ -6692,8 +6525,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       is_struct = type.IsValueType;
-
+                       var block = ec.CurrentBlock;
                        if (block != null) {
                                if (block.Toplevel.ThisVariable != null)
                                        variable_info = block.Toplevel.ThisVariable.VariableInfo;
@@ -6730,7 +6562,7 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Constant", args);
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        ResolveBase (ec);
                        return this;
@@ -6758,7 +6590,7 @@ namespace Mono.CSharp {
 
                public override int GetHashCode()
                {
-                       return block.GetHashCode ();
+                       throw new NotImplementedException ();
                }
 
                public override string Name {
@@ -6771,14 +6603,12 @@ namespace Mono.CSharp {
                        if (t == null)
                                return false;
 
-                       return block == t.block;
+                       return true;
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
-                       This target = (This) t;
-
-                       target.block = clonectx.LookupBlock (block);
+                       // Nothing
                }
 
                public override void SetHasAddressTaken ()
@@ -6802,7 +6632,7 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ("ET");
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.Variable;
                        type = TypeManager.runtime_argument_handle_type;
@@ -6817,7 +6647,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Arglist);
+                       ec.Emit (OpCodes.Arglist);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression target)
@@ -6829,7 +6659,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Represents the `__arglist (....)' construct
        /// </summary>
-       class Arglist : Expression
+       public class Arglist : Expression
        {
                Arguments Arguments;
 
@@ -6847,11 +6677,11 @@ namespace Mono.CSharp {
                public Type[] ArgumentTypes {
                    get {
                                if (Arguments == null)
-                                       return Type.EmptyTypes;
+                                       return System.Type.EmptyTypes;
 
-                       Type[] retval = new Type [Arguments.Count];
+                       var retval = new Type [Arguments.Count];
                        for (int i = 0; i < retval.Length; i++)
-                           retval [i] = Arguments [i].Expr.Type;
+                                       retval[i] = Arguments[i].Expr.Type.GetMetaInfo ();
 
                        return retval;
                    }
@@ -6863,7 +6693,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.Variable;
                        type = InternalType.Arglist;
@@ -6881,12 +6711,6 @@ namespace Mono.CSharp {
                                Arguments.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       if (Arguments != null)
-                               Arguments.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Arglist target = (Arglist) t;
@@ -6900,15 +6724,30 @@ namespace Mono.CSharp {
        ///   Implements the typeof operator
        /// </summary>
        public class TypeOf : Expression {
-               Expression QueriedType;
-               protected Type typearg;
-               
-               public TypeOf (Expression queried_type, Location l)
+               FullNamedExpression QueriedType;
+               TypeSpec typearg;
+
+               public TypeOf (FullNamedExpression queried_type, Location l)
                {
                        QueriedType = queried_type;
                        loc = l;
                }
 
+               #region Properties
+               public TypeSpec TypeArgument {
+                       get {
+                               return typearg;
+                       }
+               }
+
+               public FullNamedExpression TypeExpression {
+                       get {
+                               return QueriedType;
+                       }
+               }
+
+               #endregion
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        Arguments args = new Arguments (2);
@@ -6917,18 +6756,22 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Constant", args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-
                        TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return null;
 
                        typearg = texpr.Type;
 
-                       if (typearg == TypeManager.void_type) {
+                       //
+                       // Get generic type definition for unbounded type arguments
+                       //
+                       var tne = QueriedType as ATypeNameExpression;
+                       if (tne != null && typearg.IsGeneric && !tne.HasTypeArguments)
+                               typearg = typearg.GetDefinition ();
+
+                       if (typearg == TypeManager.void_type && !(QueriedType is TypeExpression)) {
                                ec.Report.Error (673, loc, "System.Void cannot be used from C#. Use typeof (void) to get the void type object");
                        } else if (typearg.IsPointer && !ec.IsUnsafe){
                                UnsafeError (ec, loc);
@@ -6955,85 +6798,71 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override void Emit (EmitContext ec)
+               static bool ContainsTypeParameter (TypeSpec type)
                {
-                       ec.ig.Emit (OpCodes.Ldtoken, TypeManager.TypeToReflectionType (typearg));
-                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
-               }
+                       if (type.Kind == MemberKind.TypeParameter)
+                               return true;
 
-               public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
-               {
-                       if (TypeManager.ContainsGenericParameters (typearg) &&
-                               !TypeManager.IsGenericTypeDefinition (typearg)) {
-                               ec.Report.SymbolRelatedToPreviousError (typearg);
-                               ec.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters",
-                                            TypeManager.CSharpName (typearg));
-                               value = null;
-                               return false;
-                       }
+                       var element_container = type as ElementTypeSpec;
+                       if (element_container != null)
+                               return ContainsTypeParameter (element_container.Element);
 
-                       if (value_type == TypeManager.object_type) {
-                               value = (object)typearg;
-                               return true;
+                       foreach (var t in type.TypeArguments) {
+                               if (ContainsTypeParameter (t)) {
+                                       return true;
+                               }
                        }
-                       value = typearg;
-                       return true;
+
+                       return false;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
                {
-                       typearg = storey.MutateType (typearg);
-               }
+                       // Target type is not System.Type therefore must be object
+                       // and we need to use different encoding sequence
+                       if (targetType != type)
+                               enc.Encode (type);
 
-               public Type TypeArgument {
-                       get {
-                               return typearg;
+                       if (ContainsTypeParameter (typearg)) {
+                               rc.Compiler.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters",
+                                       TypeManager.CSharpName (typearg));
+                               return;
                        }
-               }
 
-               protected override void CloneTo (CloneContext clonectx, Expression t)
-               {
-                       TypeOf target = (TypeOf) t;
-                       if (QueriedType != null)
-                               target.QueriedType = QueriedType.Clone (clonectx);
+                       enc.EncodeTypeName (typearg);
                }
-       }
 
-       /// <summary>
-       ///   Implements the `typeof (void)' operator
-       /// </summary>
-       public class TypeOfVoid : TypeOf {
-               public TypeOfVoid (Location l) : base (null, l)
+               public override void Emit (EmitContext ec)
                {
-                       loc = l;
+                       ec.Emit (OpCodes.Ldtoken, typearg);
+                       ec.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override void CloneTo (CloneContext clonectx, Expression t)
                {
-                       type = TypeManager.type_type;
-                       typearg = TypeManager.void_type;
-
-                       return DoResolveBase ();
+                       TypeOf target = (TypeOf) t;
+                       if (QueriedType != null)
+                               target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx);
                }
        }
 
-       class TypeOfMethod : TypeOfMember
+       class TypeOfMethod : TypeOfMember<MethodSpec>
        {
-               public TypeOfMethod (MethodBase method, Location loc)
+               public TypeOfMethod (MethodSpec method, Location loc)
                        : base (method, loc)
                {
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       if (member is MethodInfo) {
-                               type = TypeManager.methodinfo_type;
+                       if (member.IsConstructor) {
+                               type = TypeManager.ctorinfo_type;
                                if (type == null)
-                                       type = TypeManager.methodinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "MethodInfo", Kind.Class, true);
+                                       type = TypeManager.ctorinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "ConstructorInfo", MemberKind.Class, true);
                        } else {
-                               type = TypeManager.ctorinfo_type;
+                               type = TypeManager.methodinfo_type;
                                if (type == null)
-                                       type = TypeManager.ctorinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "ConstructorInfo", Kind.Class, true);
+                                       type = TypeManager.methodinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", "MethodInfo", MemberKind.Class, true);
                        }
 
                        return base.DoResolve (ec);
@@ -7041,13 +6870,10 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       if (member is ConstructorInfo)
-                               ec.ig.Emit (OpCodes.Ldtoken, (ConstructorInfo) member);
-                       else
-                               ec.ig.Emit (OpCodes.Ldtoken, (MethodInfo) member);
+                       ec.Emit (OpCodes.Ldtoken, member);
 
                        base.Emit (ec);
-                       ec.ig.Emit (OpCodes.Castclass, type);
+                       ec.Emit (OpCodes.Castclass, type);
                }
 
                protected override string GetMethodName {
@@ -7058,7 +6884,7 @@ namespace Mono.CSharp {
                        get { return "RuntimeMethodHandle"; }
                }
 
-               protected override MethodInfo TypeFromHandle {
+               protected override MethodSpec TypeFromHandle {
                        get {
                                return TypeManager.methodbase_get_type_from_handle;
                        }
@@ -7067,7 +6893,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected override MethodInfo TypeFromHandleGeneric {
+               protected override MethodSpec TypeFromHandleGeneric {
                        get {
                                return TypeManager.methodbase_get_type_from_handle_generic;
                        }
@@ -7081,11 +6907,11 @@ namespace Mono.CSharp {
                }
        }
 
-       abstract class TypeOfMember : Expression
+       abstract class TypeOfMember<T> : Expression where T : MemberSpec
        {
-               protected readonly MemberInfo member;
+               protected readonly T member;
 
-               protected TypeOfMember (MemberInfo member, Location loc)
+               protected TypeOfMember (T member, Location loc)
                {
                        this.member = member;
                        this.loc = loc;
@@ -7099,22 +6925,22 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Constant", args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       bool is_generic = TypeManager.IsGenericType (member.DeclaringType);
-                       MethodInfo mi = is_generic ? TypeFromHandleGeneric : TypeFromHandle;
+                       bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric;
+                       var mi = is_generic ? TypeFromHandleGeneric : TypeFromHandle;
 
                        if (mi == null) {
-                               Type t = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, Kind.Class, true);
-                               Type handle_type = TypeManager.CoreLookupType (ec.Compiler, "System", RuntimeHandleName, Kind.Class, true);
+                               TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, MemberKind.Class, true);
+                               TypeSpec handle_type = TypeManager.CoreLookupType (ec.Compiler, "System", RuntimeHandleName, MemberKind.Struct, true);
 
                                if (t == null || handle_type == null)
                                        return null;
 
                                mi = TypeManager.GetPredefinedMethod (t, GetMethodName, loc,
                                        is_generic ?
-                                       new Type[] { handle_type, TypeManager.runtime_handle_type } :
-                                       new Type[] { handle_type } );
+                                       new TypeSpec[] { handle_type, TypeManager.runtime_handle_type } :
+                                       new TypeSpec[] { handle_type } );
 
                                if (is_generic)
                                        TypeFromHandleGeneric = mi;
@@ -7128,36 +6954,36 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       bool is_generic = TypeManager.IsGenericType (member.DeclaringType);
-                       MethodInfo mi;
+                       bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric;
+                       MethodSpec mi;
                        if (is_generic) {
                                mi = TypeFromHandleGeneric;
-                               ec.ig.Emit (OpCodes.Ldtoken, member.DeclaringType);
+                               ec.Emit (OpCodes.Ldtoken, member.DeclaringType);
                        } else {
                                mi = TypeFromHandle;
                        }
 
-                       ec.ig.Emit (OpCodes.Call, mi);
+                       ec.Emit (OpCodes.Call, mi);
                }
 
                protected abstract string GetMethodName { get; }
                protected abstract string RuntimeHandleName { get; }
-               protected abstract MethodInfo TypeFromHandle { get; set; }
-               protected abstract MethodInfo TypeFromHandleGeneric { get; set; }
+               protected abstract MethodSpec TypeFromHandle { get; set; }
+               protected abstract MethodSpec TypeFromHandleGeneric { get; set; }
                protected abstract string TypeName { get; }
        }
 
-       class TypeOfField : TypeOfMember
+       class TypeOfField : TypeOfMember<FieldSpec>
        {
-               public TypeOfField (FieldInfo field, Location loc)
+               public TypeOfField (FieldSpec field, Location loc)
                        : base (field, loc)
                {
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (TypeManager.fieldinfo_type == null)
-                               TypeManager.fieldinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, Kind.Class, true);
+                               TypeManager.fieldinfo_type = TypeManager.CoreLookupType (ec.Compiler, "System.Reflection", TypeName, MemberKind.Class, true);
 
                        type = TypeManager.fieldinfo_type;
                        return base.DoResolve (ec);
@@ -7165,7 +6991,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldtoken, (FieldInfo) member);
+                       ec.Emit (OpCodes.Ldtoken, member);
                        base.Emit (ec);
                }
 
@@ -7177,7 +7003,7 @@ namespace Mono.CSharp {
                        get { return "RuntimeFieldHandle"; }
                }
 
-               protected override MethodInfo TypeFromHandle {
+               protected override MethodSpec TypeFromHandle {
                        get {
                                return TypeManager.fieldinfo_get_field_from_handle;
                        }
@@ -7186,7 +7012,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected override MethodInfo TypeFromHandleGeneric {
+               protected override MethodSpec TypeFromHandleGeneric {
                        get {
                                return TypeManager.fieldinfo_get_field_from_handle_generic;
                        }
@@ -7205,7 +7031,7 @@ namespace Mono.CSharp {
        /// </summary>
        public class SizeOf : Expression {
                readonly Expression QueriedType;
-               Type type_queried;
+               TypeSpec type_queried;
                
                public SizeOf (Expression queried_type, Location l)
                {
@@ -7219,7 +7045,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
@@ -7227,14 +7053,14 @@ namespace Mono.CSharp {
 
                        type_queried = texpr.Type;
                        if (TypeManager.IsEnumType (type_queried))
-                               type_queried = TypeManager.GetEnumUnderlyingType (type_queried);
+                               type_queried = EnumSpec.GetUnderlyingType (type_queried);
 
                        int size_of = GetTypeSize (type_queried);
                        if (size_of > 0) {
-                               return new IntConstant (size_of, loc);
+                               return new IntConstant (size_of, loc).Resolve (ec);
                        }
 
-                       if (!TypeManager.VerifyUnManaged (type_queried, loc)){
+                       if (!TypeManager.VerifyUnmanaged (ec.Compiler, type_queried, loc)){
                                return null;
                        }
 
@@ -7251,7 +7077,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Sizeof, type_queried);
+                       ec.Emit (OpCodes.Sizeof, type_queried);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -7267,14 +7093,20 @@ namespace Mono.CSharp {
                readonly string alias;
                public static readonly string GlobalAlias = "global";
 
+               public QualifiedAliasMember (string alias, string identifier, Location l)
+                       : base (null, identifier, l)
+               {
+                       this.alias = alias;
+               }
+
                public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
                        : base (null, identifier, targs, l)
                {
                        this.alias = alias;
                }
 
-               public QualifiedAliasMember (string alias, string identifier, Location l)
-                       : base (null, identifier, l)
+               public QualifiedAliasMember (string alias, string identifier, int arity, Location l)
+                       : base (null, identifier, arity, l)
                {
                        this.alias = alias;
                }
@@ -7309,12 +7141,12 @@ namespace Mono.CSharp {
                        return fne;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        return ResolveAsTypeStep (ec, false);
                }
 
-               protected override void Error_IdentifierNotFound (IMemberContext rc, FullNamedExpression expr_type, string identifier)
+               protected override void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier)
                {
                        rc.Compiler.Report.Error (687, loc,
                                "A namespace alias qualifier `{0}' did not resolve to a namespace or a type",
@@ -7325,8 +7157,7 @@ namespace Mono.CSharp {
                {
                        string name = Name;
                        if (targs != null) {
-                               name = TypeManager.RemoveGenericArity (Name) + "<" +
-                                       targs.GetSignatureForError () + ">";
+                               name = Name + "<" + targs.GetSignatureForError () + ">";
                        }
 
                        return alias + "::" + name;
@@ -7362,6 +7193,12 @@ namespace Mono.CSharp {
                        this.expr = expr;
                }
 
+               public MemberAccess (Expression expr, string identifier, int arity, Location loc)
+                       : base (identifier, arity, loc)
+               {
+                       this.expr = expr;
+               }
+
                Expression DoResolve (ResolveContext ec, Expression right_side)
                {
                        if (type != null)
@@ -7375,29 +7212,46 @@ namespace Mono.CSharp {
                        //
 
                        SimpleName original = expr as SimpleName;
-                       Expression expr_resolved = expr.Resolve (ec,
-                               ResolveFlags.VariableOrValue | ResolveFlags.Type |
-                               ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis);
+                       Expression expr_resolved;
+                       const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
+
+                       using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
+                               if (original != null) {
+                                       expr_resolved = original.DoResolve (ec, true);
+                                       if (expr_resolved != null) {
+                                               // Ugly, simulate skipped Resolve
+                                               if (expr_resolved is ConstantExpr) {
+                                                       expr_resolved = expr_resolved.Resolve (ec);
+                                               } else if (expr_resolved is FieldExpr || expr_resolved is PropertyExpr) {
+                                                       // nothing yet
+                                               } else if ((flags & expr_resolved.ExprClassToResolveFlags) == 0) {
+                                                       expr_resolved.Error_UnexpectedKind (ec, flags, expr.Location);
+                                                       expr_resolved = null;
+                                               }
+                                       }
+                               } else {
+                                       expr_resolved = expr.Resolve (ec, flags);
+                               }
+                       }
 
                        if (expr_resolved == null)
                                return null;
 
-                       string LookupIdentifier = MemberName.MakeName (Name, targs);
-
                        Namespace ns = expr_resolved as Namespace;
                        if (ns != null) {
-                               FullNamedExpression retval = ns.Lookup (ec.Compiler, LookupIdentifier, loc);
+                               FullNamedExpression retval = ns.Lookup (ec.Compiler, Name, Arity, loc);
 
                                if (retval == null)
-                                       ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, ec.Report);
-                               else if (targs != null)
+                                       ns.Error_NamespaceDoesNotExist (loc, Name, Arity, ec);
+                               else if (HasTypeArguments)
                                        retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false);
 
+                               expr = expr_resolved;
                                return retval;
                        }
 
-                       Type expr_type = expr_resolved.Type;
-                       if (TypeManager.IsDynamicType (expr_type)) {
+                       TypeSpec expr_type = expr_resolved.Type;
+                       if (expr_type == InternalType.Dynamic) {
                                Arguments args = new Arguments (1);
                                args.Add (new Argument (expr_resolved.Resolve (ec)));
                                expr = new DynamicMemberBinder (Name, args, loc);
@@ -7407,34 +7261,24 @@ namespace Mono.CSharp {
                                return expr.Resolve (ec);
                        }
 
-                       if (expr_type.IsPointer || expr_type == TypeManager.void_type ||
-                               expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) {
-                               Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
-                               return null;
-                       }
 
-                       Constant c = expr_resolved as Constant;
-                       if (c != null && c.GetValue () == null) {
-                               ec.Report.Warning (1720, 1, loc, "Expression will always cause a `{0}'",
-                                       "System.NullReferenceException");
-                       }
+                       const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum |
+                               MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType;
 
-                       if (targs != null) {
-                               if (!targs.Resolve (ec))
-                                       return null;
+                       if ((expr_type.Kind & dot_kinds) == 0 || expr_type == TypeManager.void_type) {
+                               Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
+                               return null;
                        }
 
-                       Expression member_lookup;
-                       member_lookup = MemberLookup (ec.Compiler,
-                               ec.CurrentType, expr_type, expr_type, Name, loc);
+                       var arity = HasTypeArguments ? targs.Count : -1;
 
-                       if (member_lookup == null && targs != null) {
-                               member_lookup = MemberLookup (ec.Compiler,
-                                       ec.CurrentType, expr_type, expr_type, LookupIdentifier, loc);
-                       }
+                       var member_lookup = MemberLookup (ec.Compiler,
+                               ec.CurrentType, expr_type, expr_type, Name, arity, BindingRestriction.NoOverrides, loc);
 
                        if (member_lookup == null) {
-                               ExprClass expr_eclass = expr_resolved.eclass;
+                               expr = expr_resolved.Resolve (ec);
+
+                               ExprClass expr_eclass = expr.eclass;
 
                                //
                                // Extension methods are not allowed on all expression types
@@ -7442,33 +7286,40 @@ namespace Mono.CSharp {
                                if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable ||
                                        expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess ||
                                        expr_eclass == ExprClass.EventAccess) {
-                                       ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc);
+                                       ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, arity, loc);
                                        if (ex_method_lookup != null) {
-                                               ex_method_lookup.ExtensionExpression = expr_resolved;
+                                               ex_method_lookup.ExtensionExpression = expr;
+
+                                               if (HasTypeArguments) {
+                                                       if (!targs.Resolve (ec))
+                                                               return null;
 
-                                               if (targs != null) {
                                                        ex_method_lookup.SetTypeArguments (ec, targs);
                                                }
 
-                                               return ex_method_lookup.DoResolve (ec);
+                                               return ex_method_lookup.Resolve (ec);
                                        }
                                }
 
-                               expr = expr_resolved;
                                member_lookup = Error_MemberLookupFailed (ec,
-                                       ec.CurrentType, expr_type, expr_type, Name, null,
-                                       AllMemberTypes, AllBindingFlags);
+                                       ec.CurrentType, expr_type, expr_type, Name, arity, null,
+                                       MemberKind.All, BindingRestriction.AccessibleOnly);
                                if (member_lookup == null)
                                        return null;
                        }
 
+                       expr = expr_resolved;
+
+                       MemberExpr me;
                        TypeExpr texpr = member_lookup as TypeExpr;
                        if (texpr != null) {
-                               if (!(expr_resolved is TypeExpr) && 
-                                   (original == null || !original.IdenticalNameAndTypeName (ec, expr_resolved, loc))) {
-                                       ec.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead",
-                                               Name, member_lookup.GetSignatureForError ());
-                                       return null;
+                               if (!(expr_resolved is TypeExpr)) {
+                                       me = expr_resolved as MemberExpr;
+                                       if (me == null || me.ProbeIdenticalTypeName (ec, expr_resolved, original) == expr_resolved) {
+                                               ec.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead",
+                                                       Name, member_lookup.GetSignatureForError ());
+                                               return null;
+                                       }
                                }
 
                                if (!texpr.CheckAccessLevel (ec.MemberContext)) {
@@ -7477,42 +7328,29 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
-                               GenericTypeExpr ct = expr_resolved as GenericTypeExpr;
-                               if (ct != null) {
-                                       //
-                                       // When looking up a nested type in a generic instance
-                                       // via reflection, we always get a generic type definition
-                                       // and not a generic instance - so we have to do this here.
-                                       //
-                                       // See gtest-172-lib.cs and gtest-172.cs for an example.
-                                       //
-
-                                       TypeArguments nested_targs;
-                                       if (HasTypeArguments) {
-                                               nested_targs = ct.TypeArguments.Clone ();
-                                               nested_targs.Add (targs);
-                                       } else {
-                                               nested_targs = ct.TypeArguments;
-                                       }
-
-                                       ct = new GenericTypeExpr (member_lookup.Type, nested_targs, loc);
-
+                               if (HasTypeArguments) {
+                                       var ct = new GenericTypeExpr (member_lookup.Type, targs, loc);
                                        return ct.ResolveAsTypeStep (ec, false);
                                }
 
                                return member_lookup;
                        }
 
-                       MemberExpr me = (MemberExpr) member_lookup;
-                       me = me.ResolveMemberAccess (ec, expr_resolved, loc, original);
-                       if (me == null)
-                               return null;
+                       me = (MemberExpr) member_lookup;
+
+                       if (original != null && me.IsStatic)
+                               expr_resolved = me.ProbeIdenticalTypeName (ec, expr_resolved, original);
+
+                       me = me.ResolveMemberAccess (ec, expr_resolved, original);
+
+                       if (HasTypeArguments) {
+                               if (!targs.Resolve (ec))
+                                       return null;
 
-                       if (targs != null) {
                                me.SetTypeArguments (ec, targs);
                        }
 
-                       if (original != null && !TypeManager.IsValueType (expr_type)) {
+                       if (original != null && (!TypeManager.IsValueType (expr_type) || me is PropertyExpr)) {
                                if (me.IsInstance) {
                                        LocalVariableReference var = expr_resolved as LocalVariableReference;
                                        if (var != null && !var.VerifyAssigned (ec))
@@ -7526,10 +7364,10 @@ namespace Mono.CSharp {
                        if (right_side != null)
                                return me.DoResolveLValue (ec, right_side);
                        else
-                               return me.DoResolve (ec);
+                               return me.Resolve (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        return DoResolve (ec, null);
                }
@@ -7551,16 +7389,16 @@ namespace Mono.CSharp {
                        if (expr_resolved == null)
                                return null;
 
-                       string LookupIdentifier = MemberName.MakeName (Name, targs);
-
                        Namespace ns = expr_resolved as Namespace;
                        if (ns != null) {
-                               FullNamedExpression retval = ns.Lookup (rc.Compiler, LookupIdentifier, loc);
+                               FullNamedExpression retval = ns.Lookup (rc.Compiler, Name, Arity, loc);
 
-                               if (retval == null && !silent)
-                                       ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, rc.Compiler.Report);
-                               else if (targs != null)
+                               if (retval == null) {
+                                       if (!silent)
+                                               ns.Error_NamespaceDoesNotExist (loc, Name, Arity, rc);
+                               } else if (HasTypeArguments) {
                                        retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent);
+                               }
 
                                return retval;
                        }
@@ -7569,71 +7407,49 @@ namespace Mono.CSharp {
                        if (tnew_expr == null)
                                return null;
 
-                       Type expr_type = tnew_expr.Type;
+                       TypeSpec expr_type = tnew_expr.Type;
                        if (TypeManager.IsGenericParameter (expr_type)) {
                                rc.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'",
                                        tnew_expr.GetSignatureForError ());
                                return null;
                        }
 
-                       Expression member_lookup = MemberLookup (rc.Compiler,
-                               rc.CurrentType, expr_type, expr_type, LookupIdentifier,
-                               MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
-                       if (member_lookup == null) {
+                       var nested = MemberCache.FindNestedType (expr_type, Name, Arity);
+                       if (nested == null) {
                                if (silent)
                                        return null;
 
-                               Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier);
+                               Error_IdentifierNotFound (rc, expr_type, Name);
                                return null;
                        }
 
-                       TypeExpr texpr = member_lookup.ResolveAsTypeTerminal (rc, false);
-                       if (texpr == null)
-                               return null;
-
-                       TypeArguments the_args = targs;
-                       Type declaring_type = texpr.Type.DeclaringType;
-                       if (TypeManager.HasGenericArguments (declaring_type) && !TypeManager.IsGenericTypeDefinition (expr_type)) {
-                               while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) {
-                                       expr_type = expr_type.BaseType;
-                               }
-                               
-                               TypeArguments new_args = new TypeArguments ();
-                               foreach (Type decl in TypeManager.GetTypeArguments (expr_type))
-                                       new_args.Add (new TypeExpression (TypeManager.TypeToCoreType (decl), loc));
-
-                               if (targs != null)
-                                       new_args.Add (targs);
-
-                               the_args = new_args;
+                       bool extra_check;
+                       if (!IsMemberAccessible (rc.CurrentType ?? InternalType.FakeInternalType, nested, out extra_check)) {
+                               ErrorIsInaccesible (loc, nested.GetSignatureForError (), rc.Compiler.Report);
                        }
-
-                       if (the_args != null) {
-                               GenericTypeExpr ctype = new GenericTypeExpr (texpr.Type, the_args, loc);
-                               return ctype.ResolveAsTypeStep (rc, false);
+                       
+                       TypeExpr texpr;
+                       if (HasTypeArguments) {
+                               texpr = new GenericTypeExpr (nested, targs, loc);
+                       } else {
+                               texpr = new TypeExpression (nested, loc);
                        }
 
-                       return texpr;
+                       return texpr.ResolveAsTypeStep (rc, false);
                }
 
-               protected virtual void Error_IdentifierNotFound (IMemberContext rc, FullNamedExpression expr_type, string identifier)
+               protected virtual void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier)
                {
-                       Expression member_lookup = MemberLookup (rc.Compiler,
-                               rc.CurrentType, expr_type.Type, expr_type.Type, SimpleName.RemoveGenericArity (identifier),
-                               MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
-
-                       if (member_lookup != null) {
-                               expr_type = member_lookup.ResolveAsTypeTerminal (rc, false);
-                               if (expr_type == null)
-                                       return;
+                       var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity));
 
-                               expr_type.Error_TypeArgumentsCannotBeUsed (rc.Compiler.Report, loc);
+                       if (nested != null) {
+                               Error_TypeArgumentsCannotBeUsed (rc.Compiler.Report, expr.Location, nested, Arity);
                                return;
                        }
 
-                       member_lookup = MemberLookup (rc.Compiler,
-                               rc.CurrentType, expr_type.Type, expr_type.Type, identifier,
-                                       MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic, loc);
+                       var member_lookup = MemberLookup (rc.Compiler,
+                               rc.CurrentType, expr_type, expr_type, identifier, -1,
+                                       MemberKind.All, BindingRestriction.None, loc);
 
                        if (member_lookup == null) {
                                rc.Compiler.Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
@@ -7644,9 +7460,9 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, Type type, string name)
+               protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
                {
-                       if (RootContext.Version > LanguageVersion.ISO_2 &&
+                       if (RootContext.Version > LanguageVersion.ISO_2 && !ec.Compiler.IsRuntimeBinder &&
                                ((expr.eclass & (ExprClass.Value | ExprClass.Variable)) != 0)) {
                                ec.Report.Error (1061, loc, "Type `{0}' does not contain a definition for `{1}' and no " +
                                        "extension method `{1}' of type `{0}' could be found " +
@@ -7696,7 +7512,7 @@ namespace Mono.CSharp {
                                return Expr.CreateExpressionTree (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        using (ec.With (ResolveContext.Options.AllCheckStateFlags, true))
                                Expr = Expr.Resolve (ec);
@@ -7724,19 +7540,12 @@ namespace Mono.CSharp {
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) {
                                return Expr.MakeExpression (ctx);
                        }
                }
-#endif
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Expr.MutateHoistedGenericType (storey);
-               }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
@@ -7765,7 +7574,7 @@ namespace Mono.CSharp {
                                return Expr.CreateExpressionTree (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        using (ec.With (ResolveContext.Options.AllCheckStateFlags, false))
                                Expr = Expr.Resolve (ec);
@@ -7793,11 +7602,6 @@ namespace Mono.CSharp {
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Expr.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        UnCheckedExpr target = (UnCheckedExpr) t;
@@ -7816,10 +7620,10 @@ namespace Mono.CSharp {
                public Arguments Arguments;
                public Expression Expr;
 
-               public ElementAccess (Expression e, Arguments args)
+               public ElementAccess (Expression e, Arguments args, Location loc)
                {
                        Expr = e;
-                       loc  = e.Location;
+                       this.loc = loc;
                        this.Arguments = args;
                }
 
@@ -7831,7 +7635,7 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "ArrayIndex", args);
                }
 
-               Expression MakePointerAccess (ResolveContext ec, Type t)
+               Expression MakePointerAccess (ResolveContext ec, TypeSpec t)
                {
                        if (Arguments.Count != 1){
                                ec.Report.Error (196, loc, "A pointer must be indexed by only one value");
@@ -7845,7 +7649,7 @@ namespace Mono.CSharp {
                        return new Indirection (p, loc).Resolve (ec);
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        Expr = Expr.Resolve (ec);
                        if (Expr == null)
@@ -7857,7 +7661,7 @@ namespace Mono.CSharp {
                        //
                        // I am experimenting with this pattern.
                        //
-                       Type t = Expr.Type;
+                       TypeSpec t = Expr.Type;
 
                        if (t == TypeManager.array_type){
                                ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `System.Array'");
@@ -7871,7 +7675,7 @@ namespace Mono.CSharp {
 
                        FieldExpr fe = Expr as FieldExpr;
                        if (fe != null) {
-                               IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
+                               var ff = fe.Spec as FixedFieldSpec;
                                if (ff != null) {
                                        return MakePointerAccess (ec, ff.ElementType);
                                }
@@ -7905,7 +7709,7 @@ namespace Mono.CSharp {
 
                public static void Error_NamedArgument (NamedArgument na, Report Report)
                {
-                       Report.Error (1742, na.Name.Location, "An element access expression cannot use named argument");
+                       Report.Error (1742, na.Location, "An element access expression cannot use named argument");
                }
 
                public override string GetSignatureForError ()
@@ -7952,187 +7756,40 @@ namespace Mono.CSharp {
                        return DoResolve (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-#if false
-                       ExprClass eclass = ea.Expr.eclass;
-
-                       // As long as the type is valid
-                       if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
-                             eclass == ExprClass.Value)) {
-                               ea.Expr.Error_UnexpectedKind ("variable or value");
-                               return null;
-                       }
-#endif
-
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-
                        // dynamic is used per argument in ConvertExpressionToArrayIndex case
                        bool dynamic;
                        ea.Arguments.Resolve (ec, out dynamic);
 
-                       Type t = ea.Expr.Type;
+                       var ac = ea.Expr.Type as ArrayContainer;
                        int rank = ea.Arguments.Count;
-                       if (t.GetArrayRank () != rank) {
+                       if (ac.Rank != rank) {
                                ec.Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'",
-                                         ea.Arguments.Count.ToString (), t.GetArrayRank ().ToString ());
+                                         rank.ToString (), ac.Rank.ToString ());
                                return null;
-                       }
-
-                       type = TypeManager.GetElementType (t);
-                       if (type.IsPointer && !ec.IsUnsafe) {
-                               UnsafeError (ec, ea.Location);
-                       }
-
-                       foreach (Argument a in ea.Arguments) {
-                               if (a is NamedArgument)
-                                       ElementAccess.Error_NamedArgument ((NamedArgument) a, ec.Report);
-
-                               a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
-                       }
-                       
-                       eclass = ExprClass.Variable;
-
-                       return this;
-               }
-
-               /// <summary>
-               ///    Emits the right opcode to load an object of Type `t'
-               ///    from an array of T
-               /// </summary>
-               void EmitLoadOpcode (ILGenerator ig, Type type, int rank)
-               {
-                       if (rank > 1) {
-                               MethodInfo get = FetchGetMethod ();
-                               ig.Emit (OpCodes.Call, get);
-                               return;
-                       }
-
-                       if (type == TypeManager.byte_type || type == TypeManager.bool_type)
-                               ig.Emit (OpCodes.Ldelem_U1);
-                       else if (type == TypeManager.sbyte_type)
-                               ig.Emit (OpCodes.Ldelem_I1);
-                       else if (type == TypeManager.short_type)
-                               ig.Emit (OpCodes.Ldelem_I2);
-                       else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
-                               ig.Emit (OpCodes.Ldelem_U2);
-                       else if (type == TypeManager.int32_type)
-                               ig.Emit (OpCodes.Ldelem_I4);
-                       else if (type == TypeManager.uint32_type)
-                               ig.Emit (OpCodes.Ldelem_U4);
-                       else if (type == TypeManager.uint64_type)
-                               ig.Emit (OpCodes.Ldelem_I8);
-                       else if (type == TypeManager.int64_type)
-                               ig.Emit (OpCodes.Ldelem_I8);
-                       else if (type == TypeManager.float_type)
-                               ig.Emit (OpCodes.Ldelem_R4);
-                       else if (type == TypeManager.double_type)
-                               ig.Emit (OpCodes.Ldelem_R8);
-                       else if (type == TypeManager.intptr_type)
-                               ig.Emit (OpCodes.Ldelem_I);
-                       else if (TypeManager.IsEnumType (type)){
-                               EmitLoadOpcode (ig, TypeManager.GetEnumUnderlyingType (type), rank);
-                       } else if (TypeManager.IsStruct (type)){
-                               ig.Emit (OpCodes.Ldelema, type);
-                               ig.Emit (OpCodes.Ldobj, type);
-                       } else if (type.IsGenericParameter) {
-                               ig.Emit (OpCodes.Ldelem, type);
-                       } else if (type.IsPointer)
-                               ig.Emit (OpCodes.Ldelem_I);
-                       else
-                               ig.Emit (OpCodes.Ldelem_Ref);
-               }
-
-               protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
-               {
-                       ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
-               }
+                       }
 
-               /// <summary>
-               ///    Returns the right opcode to store an object of Type `t'
-               ///    from an array of T.  
-               /// </summary>
-               static public OpCode GetStoreOpcode (Type t, out bool is_stobj, out bool has_type_arg)
-               {
-                       has_type_arg = false; is_stobj = false;
-                       t = TypeManager.TypeToCoreType (t);
-                       if (TypeManager.IsEnumType (t))
-                               t = TypeManager.GetEnumUnderlyingType (t);
-                       if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
-                           t == TypeManager.bool_type)
-                               return OpCodes.Stelem_I1;
-                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type ||
-                                t == TypeManager.char_type)
-                               return OpCodes.Stelem_I2;
-                       else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
-                               return OpCodes.Stelem_I4;
-                       else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
-                               return OpCodes.Stelem_I8;
-                       else if (t == TypeManager.float_type)
-                               return OpCodes.Stelem_R4;
-                       else if (t == TypeManager.double_type)
-                               return OpCodes.Stelem_R8;
-                       else if (t == TypeManager.intptr_type) {
-                                has_type_arg = true;
-                               is_stobj = true;
-                                return OpCodes.Stobj;
-                       } else if (TypeManager.IsStruct (t)) {
-                               has_type_arg = true;
-                               is_stobj = true;
-                               return OpCodes.Stobj;
-                       } else if (t.IsGenericParameter) {
-                               has_type_arg = true;
-                               return OpCodes.Stelem;
-                       } else if (t.IsPointer)
-                               return OpCodes.Stelem_I;
-                       else
-                               return OpCodes.Stelem_Ref;
-               }
+                       type = ac.Element;
+                       if (type.IsPointer && !ec.IsUnsafe) {
+                               UnsafeError (ec, ea.Location);
+                       }
 
-               MethodInfo FetchGetMethod ()
-               {
-                       ModuleBuilder mb = RootContext.ToplevelTypes.Builder;
-                       int arg_count = ea.Arguments.Count;
-                       Type [] args = new Type [arg_count];
-                       MethodInfo get;
-                       
-                       for (int i = 0; i < arg_count; i++){
-                               //args [i++] = a.Type;
-                               args [i] = TypeManager.int32_type;
+                       foreach (Argument a in ea.Arguments) {
+                               if (a is NamedArgument)
+                                       ElementAccess.Error_NamedArgument ((NamedArgument) a, ec.Report);
+
+                               a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
                        }
                        
-                       get = mb.GetArrayMethod (
-                               ea.Expr.Type, "Get",
-                               CallingConventions.HasThis |
-                               CallingConventions.Standard,
-                               type, args);
-                       return get;
+                       eclass = ExprClass.Variable;
+
+                       return this;
                }
-                               
 
-               MethodInfo FetchAddressMethod ()
+               protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
                {
-                       ModuleBuilder mb = RootContext.ToplevelTypes.Builder;
-                       int arg_count = ea.Arguments.Count;
-                       Type [] args = new Type [arg_count];
-                       MethodInfo address;
-                       Type ret_type;
-                       
-                       ret_type = TypeManager.GetReferenceType (type);
-                       
-                       for (int i = 0; i < arg_count; i++){
-                               //args [i++] = a.Type;
-                               args [i] = TypeManager.int32_type;
-                       }
-                       
-                       address = mb.GetArrayMethod (
-                               ea.Expr.Type, "Address",
-                               CallingConventions.HasThis |
-                               CallingConventions.Standard,
-                               ret_type, args);
-
-                       return address;
+                       ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
                }
 
                //
@@ -8149,18 +7806,17 @@ namespace Mono.CSharp {
 
                public void Emit (EmitContext ec, bool leave_copy)
                {
-                       int rank = ea.Expr.Type.GetArrayRank ();
-                       ILGenerator ig = ec.ig;
+                       var ac = ea.Expr.Type as ArrayContainer;
 
                        if (prepared) {
-                               LoadFromPtr (ig, this.type);
+                               ec.EmitLoadFromPtr (type);
                        } else {
                                LoadArrayAndArguments (ec);
-                               EmitLoadOpcode (ig, type, rank);
+                               ec.EmitArrayLoad (ac);
                        }       
 
                        if (leave_copy) {
-                               ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                                temp = new LocalTemporary (this.type);
                                temp.Store (ec);
                        }
@@ -8173,74 +7829,43 @@ namespace Mono.CSharp {
 
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       int rank = ea.Expr.Type.GetArrayRank ();
-                       ILGenerator ig = ec.ig;
-                       Type t = source.Type;
+                       var ac = (ArrayContainer) ea.Expr.Type;
+                       TypeSpec t = source.Type;
                        prepared = prepare_for_load;
 
                        if (prepared) {
                                AddressOf (ec, AddressOp.LoadStore);
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                        } else {
                                LoadArrayAndArguments (ec);
-                       }
 
-                       if (rank == 1) {
-                               bool is_stobj, has_type_arg;
-                               OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);
+                               //
+                               // If we are dealing with a struct, get the
+                               // address of it, so we can store it.
+                               //
+                               // The stobj opcode used by value types will need
+                               // an address on the stack, not really an array/array
+                               // pair
+                               //
+                               if (ac.Rank == 1 && TypeManager.IsStruct (t) &&
+                                       (!TypeManager.IsBuiltinOrEnum (t) ||
+                                        t == TypeManager.decimal_type)) {
 
-                               if (!prepared) {
-                                       //
-                                       // The stobj opcode used by value types will need
-                                       // an address on the stack, not really an array/array
-                                       // pair
-                                       //
-                                       if (is_stobj)
-                                               ig.Emit (OpCodes.Ldelema, t);
-                               }
-                               
-                               source.Emit (ec);
-                               if (leave_copy) {
-                                       ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (this.type);
-                                       temp.Store (ec);
-                               }
-                               
-                               if (prepared)
-                                       StoreFromPtr (ig, t);
-                               else if (is_stobj)
-                                       ig.Emit (OpCodes.Stobj, t);
-                               else if (has_type_arg)
-                                       ig.Emit (op, t);
-                               else
-                                       ig.Emit (op);
-                       } else {
-                               source.Emit (ec);
-                               if (leave_copy) {
-                                       ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (this.type);
-                                       temp.Store (ec);
+                                       ec.Emit (OpCodes.Ldelema, t);
                                }
+                       }
 
-                               if (prepared) {
-                                       StoreFromPtr (ig, t);
-                               } else {
-                                       int arg_count = ea.Arguments.Count;
-                                       Type [] args = new Type [arg_count + 1];
-                                       for (int i = 0; i < arg_count; i++) {
-                                               //args [i++] = a.Type;
-                                               args [i] = TypeManager.int32_type;
-                                       }
-                                       args [arg_count] = type;
-
-                                       MethodInfo set = RootContext.ToplevelTypes.Builder.GetArrayMethod (
-                                               ea.Expr.Type, "Set",
-                                               CallingConventions.HasThis |
-                                               CallingConventions.Standard,
-                                               TypeManager.void_type, args);
+                       source.Emit (ec);
+                       if (leave_copy) {
+                               ec.Emit (OpCodes.Dup);
+                               temp = new LocalTemporary (this.type);
+                               temp.Store (ec);
+                       }
 
-                                       ig.Emit (OpCodes.Call, set);
-                               }
+                       if (prepared) {
+                               ec.EmitStoreFromPtr (t);
+                       } else {
+                               ec.EmitArrayStore (ac);
                        }
                        
                        if (temp != null) {
@@ -8263,17 +7888,10 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       int rank = ea.Expr.Type.GetArrayRank ();
-                       ILGenerator ig = ec.ig;
+                       var ac = (ArrayContainer) ea.Expr.Type;
 
                        LoadArrayAndArguments (ec);
-
-                       if (rank == 1){
-                               ig.Emit (OpCodes.Ldelema, type);
-                       } else {
-                               MethodInfo address = FetchAddressMethod ();
-                               ig.Emit (OpCodes.Call, address);
-                       }
+                       ec.EmitArrayAddress (ac);
                }
 
 #if NET_4_0
@@ -8283,6 +7901,7 @@ namespace Mono.CSharp {
                                ea.Expr.MakeExpression (ctx),
                                Arguments.MakeExpression (ea.Arguments, ctx));
                }
+#endif
 
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
@@ -8290,13 +7909,6 @@ namespace Mono.CSharp {
                                ea.Expr.MakeExpression (ctx),
                                Arguments.MakeExpression (ea.Arguments, ctx));
                }
-#endif
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       type = storey.MutateType (type);
-                       ea.Expr.Type = storey.MutateType (ea.Expr.Type);
-               }
        }
 
        /// <summary>
@@ -8306,10 +7918,39 @@ namespace Mono.CSharp {
        {
                class IndexerMethodGroupExpr : MethodGroupExpr
                {
-                       public IndexerMethodGroupExpr (Indexers indexers, Location loc)
-                               : base (null, loc)
+                       IEnumerable<IndexerSpec> candidates;
+
+                       public IndexerMethodGroupExpr (IEnumerable<IndexerSpec> indexers, Location loc)
+                               : base (FilterAccessors (indexers).ToList (), null, loc)
+                       {
+                               candidates = indexers;
+                       }
+
+                       public IndexerSpec BestIndexer ()
+                       {
+                               return MemberCache.FindIndexers (BestCandidate.DeclaringType, BindingRestriction.None).
+                                       Where (l => 
+                                               (l.HasGet && l.Get.MemberDefinition == BestCandidate.MemberDefinition) ||
+                                               (l.HasSet && l.Set.MemberDefinition == BestCandidate.MemberDefinition)).First ();
+                       }
+
+                       static IEnumerable<MemberSpec> FilterAccessors (IEnumerable<IndexerSpec> indexers)
+                       {
+                               foreach (IndexerSpec i in indexers) {
+                                       if (i.HasGet)
+                                               yield return i.Get;
+                                       else
+                                               yield return i.Set;
+                               }
+                       }
+
+                       protected override IList<MemberSpec> GetBaseTypeMethods (ResolveContext rc, TypeSpec type)
                        {
-                               Methods = (MethodBase []) indexers.Methods.ToArray (typeof (MethodBase));
+                               candidates = GetIndexersForType (type);
+                               if (candidates == null)
+                                       return null;
+
+                               return FilterAccessors (candidates).ToList ();
                        }
 
                        public override string Name {
@@ -8318,7 +7959,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       protected override int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters)
+                       protected override int GetApplicableParametersCount (MethodSpec method, AParametersCollection parameters)
                        {
                                //
                                // Here is the trick, decrease number of arguments by 1 when only
@@ -8333,100 +7974,18 @@ namespace Mono.CSharp {
                        }
                }
 
-               class Indexers
-               {
-                       // Contains either property getter or setter
-                       public ArrayList Methods;
-                       public ArrayList Properties;
-
-                       Indexers ()
-                       {
-                       }
-
-                       void Append (Type caller_type, MemberInfo [] mi)
-                       {
-                               if (mi == null)
-                                       return;
-
-                               foreach (PropertyInfo property in mi) {
-                                       MethodInfo accessor = property.GetGetMethod (true);
-                                       if (accessor == null)
-                                               accessor = property.GetSetMethod (true);
-
-                                       if (Methods == null) {
-                                               Methods = new ArrayList ();
-                                               Properties = new ArrayList ();
-                                       }
-
-                                       Methods.Add (accessor);
-                                       Properties.Add (property);
-                               }
-                       }
-
-                       static MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
-                       {
-                               string p_name = TypeManager.IndexerPropertyName (lookup_type);
-
-                               return TypeManager.MemberLookup (
-                                       caller_type, caller_type, lookup_type, MemberTypes.Property,
-                                       BindingFlags.Public | BindingFlags.Instance |
-                                       BindingFlags.DeclaredOnly, p_name, null);
-                       }
-                       
-                       public static Indexers GetIndexersForType (Type caller_type, Type lookup_type) 
-                       {
-                               Indexers ix = new Indexers ();
-
-                               if (TypeManager.IsGenericParameter (lookup_type)) {
-                                       GenericConstraints gc = TypeManager.GetTypeParameterConstraints (lookup_type);
-                                       if (gc == null)
-                                               return ix;
-
-                                       if (gc.HasClassConstraint) {
-                                               Type class_contraint = gc.ClassConstraint;
-                                               while (class_contraint != TypeManager.object_type && class_contraint != null) {
-                                                       ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, class_contraint));
-                                                       class_contraint = class_contraint.BaseType;
-                                               }
-                                       }
-
-                                       Type[] ifaces = gc.InterfaceConstraints;
-                                       foreach (Type itype in ifaces)
-                                               ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
-
-                                       return ix;
-                               }
-
-                               Type copy = lookup_type;
-                               while (copy != TypeManager.object_type && copy != null){
-                                       ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, copy));
-                                       copy = copy.BaseType;
-                               }
-
-                               if (lookup_type.IsInterface) {
-                                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
-                                       if (ifaces != null) {
-                                               foreach (Type itype in ifaces)
-                                                       ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
-                                       }
-                               }
-
-                               return ix;
-                       }
-               }
-
                //
                // Points to our "data" repository
                //
-               MethodInfo get, set;
+               IndexerSpec spec;
                bool is_base_indexer;
                bool prepared;
                LocalTemporary temp;
                LocalTemporary prepared_value;
                Expression set_expr;
 
-               protected Type indexer_type;
-               protected Type current_type;
+               protected TypeSpec indexer_type;
+               protected TypeSpec current_type;
                protected Expression instance_expr;
                protected Arguments arguments;
                
@@ -8441,7 +8000,6 @@ namespace Mono.CSharp {
                {
                        this.instance_expr = instance_expr;
                        this.is_base_indexer = is_base_indexer;
-                       this.eclass = ExprClass.Value;
                        this.loc = loc;
                }
 
@@ -8454,18 +8012,23 @@ namespace Mono.CSharp {
                {
                        Arguments args = Arguments.CreateForExpressionTree (ec, arguments,
                                instance_expr.CreateExpressionTree (ec),
-                               new TypeOfMethod (get, loc));
+                               new TypeOfMethod (spec.Get, loc));
 
                        return CreateExpressionFactoryCall (ec, "Call", args);
                }
 
+               static IEnumerable<IndexerSpec> GetIndexersForType (TypeSpec lookup_type)
+               {
+                       return MemberCache.FindIndexers (lookup_type, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides);
+               }
+
                protected virtual void CommonResolve (ResolveContext ec)
                {
                        indexer_type = instance_expr.Type;
                        current_type = ec.CurrentType;
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        return ResolveAccessor (ec, null);
                }
@@ -8490,8 +8053,35 @@ namespace Mono.CSharp {
                        CommonResolve (ec);
 
                        bool dynamic;
+
                        arguments.Resolve (ec, out dynamic);
-                       if (dynamic || TypeManager.IsDynamicType (indexer_type)) {
+
+                       if (indexer_type == InternalType.Dynamic) {
+                               dynamic = true;
+                       } else {
+                               var ilist = GetIndexersForType (indexer_type);
+                               if (ilist == null) {
+                                       ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
+                                                         TypeManager.CSharpName (indexer_type));
+                                       return null;
+                               }
+
+                               var mg = new IndexerMethodGroupExpr (ilist, loc) {
+                                       InstanceExpression = instance_expr
+                               };
+
+                               if (is_base_indexer)
+                                       mg.QueriedBaseType = current_type;
+
+                               mg = mg.OverloadResolve (ec, ref arguments, false, loc) as IndexerMethodGroupExpr;
+                               if (mg == null)
+                                       return null;
+
+                               if (!dynamic)
+                                       spec = mg.BestIndexer ();
+                       }
+
+                       if (dynamic) {
                                Arguments args = new Arguments (arguments.Count + 1);
                                if (is_base_indexer) {
                                        ec.Report.Error (1972, loc, "The indexer base access cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access");
@@ -8507,40 +8097,19 @@ namespace Mono.CSharp {
                                return expr.Resolve (ec);
                        }
 
-                       Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type);
-                       if (ilist.Methods == null) {
-                               ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
-                                                 TypeManager.CSharpName (indexer_type));
-                               return null;
-                       }
-
-                       MethodGroupExpr mg = new IndexerMethodGroupExpr (ilist, loc);
-                       mg = mg.OverloadResolve (ec, ref arguments, false, loc);
-                       if (mg == null)
-                               return null;
-
-                       MethodInfo mi = (MethodInfo) mg;
-                       PropertyInfo pi = null;
-                       for (int i = 0; i < ilist.Methods.Count; ++i) {
-                               if (ilist.Methods [i] == mi) {
-                                       pi = (PropertyInfo) ilist.Properties [i];
-                                       break;
-                               }
-                       }
-
-                       type = TypeManager.TypeToCoreType (pi.PropertyType);
+                       type = spec.MemberType;
                        if (type.IsPointer && !ec.IsUnsafe)
                                UnsafeError (ec, loc);
 
-                       MethodInfo accessor;
+                       MethodSpec accessor;
                        if (right_side == null) {
-                               accessor = get = pi.GetGetMethod (true);
+                               accessor = spec.Get;
                        } else {
-                               accessor = set = pi.GetSetMethod (true);
-                               if (accessor == null && pi.GetGetMethod (true) != null) {
-                                       ec.Report.SymbolRelatedToPreviousError (pi);
+                               accessor = spec.Set;
+                               if (!spec.HasSet && spec.HasGet) {
+                                       ec.Report.SymbolRelatedToPreviousError (spec);
                                        ec.Report.Error (200, loc, "The read only property or indexer `{0}' cannot be assigned to",
-                                               TypeManager.GetFullNameSignature (pi));
+                                               spec.GetSignatureForError ());
                                        return null;
                                }
 
@@ -8548,38 +8117,42 @@ namespace Mono.CSharp {
                        }
 
                        if (accessor == null) {
-                               ec.Report.SymbolRelatedToPreviousError (pi);
+                               ec.Report.SymbolRelatedToPreviousError (spec);
                                ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks a `{1}' accessor",
-                                       TypeManager.GetFullNameSignature (pi), GetAccessorName (right_side != null));
+                                       spec.GetSignatureForError (), GetAccessorName (right_side != null));
                                return null;
                        }
 
                        //
                        // Only base will allow this invocation to happen.
                        //
-                       if (accessor.IsAbstract && this is BaseIndexerAccess) {
-                               Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (pi));
+                       if (spec.IsAbstract && this is BaseIndexerAccess) {
+                               Error_CannotCallAbstractBase (ec, spec.GetSignatureForError ());
                        }
 
                        bool must_do_cs1540_check;
-                       if (!IsAccessorAccessible (ec.CurrentType, accessor, out must_do_cs1540_check)) {
-                               if (set == null)
-                                       set = pi.GetSetMethod (true);
-                               else
-                                       get = pi.GetGetMethod (true);
-
-                               if (set != null && get != null &&
-                                       (set.Attributes & MethodAttributes.MemberAccessMask) != (get.Attributes & MethodAttributes.MemberAccessMask)) {
+                       if (!IsMemberAccessible (ec.CurrentType, accessor, out must_do_cs1540_check)) {
+                               if (spec.HasDifferentAccessibility) {
                                        ec.Report.SymbolRelatedToPreviousError (accessor);
                                        ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because a `{1}' accessor is inaccessible",
-                                               TypeManager.GetFullNameSignature (pi), GetAccessorName (right_side != null));
+                                               TypeManager.GetFullNameSignature (spec), GetAccessorName (right_side != null));
                                } else {
-                                       ec.Report.SymbolRelatedToPreviousError (pi);
-                                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (pi), ec.Report);
+                                       ec.Report.SymbolRelatedToPreviousError (spec);
+                                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (spec), ec.Report);
                                }
                        }
 
                        instance_expr.CheckMarshalByRefAccess (ec);
+
+                       if (must_do_cs1540_check && (instance_expr != EmptyExpression.Null) &&
+                           !TypeManager.IsInstantiationOfSameGenericType (instance_expr.Type, ec.CurrentType) &&
+                           !TypeManager.IsNestedChildOf (ec.CurrentType, instance_expr.Type) &&
+                           !TypeManager.IsSubclassOf (instance_expr.Type, ec.CurrentType)) {
+                               ec.Report.SymbolRelatedToPreviousError (accessor);
+                               Error_CannotAccessProtected (ec, loc, spec, instance_expr.Type, ec.CurrentType);
+                               return null;
+                       }
+
                        eclass = ExprClass.IndexerAccess;
                        return this;
                }
@@ -8594,12 +8167,12 @@ namespace Mono.CSharp {
                        if (prepared) {
                                prepared_value.Emit (ec);
                        } else {
-                               Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
+                               Invocation.EmitCall (ec, is_base_indexer, instance_expr, spec.Get,
                                        arguments, loc, false, false);
                        }
 
                        if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
+                               ec.Emit (OpCodes.Dup);
                                temp = new LocalTemporary (Type);
                                temp.Store (ec);
                        }
@@ -8616,7 +8189,7 @@ namespace Mono.CSharp {
                        Expression value = set_expr;
 
                        if (prepared) {
-                               Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
+                               Invocation.EmitCall (ec, is_base_indexer, instance_expr, spec.Get,
                                        arguments, loc, true, false);
 
                                prepared_value = new LocalTemporary (type);
@@ -8625,7 +8198,7 @@ namespace Mono.CSharp {
                                prepared_value.Release (ec);
 
                                if (leave_copy) {
-                                       ec.ig.Emit (OpCodes.Dup);
+                                       ec.Emit (OpCodes.Dup);
                                        temp = new LocalTemporary (Type);
                                        temp.Store (ec);
                                }
@@ -8639,7 +8212,7 @@ namespace Mono.CSharp {
                        if (!prepared)
                                arguments.Add (new Argument (value));
 
-                       Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared);
+                       Invocation.EmitCall (ec, is_base_indexer, instance_expr, spec.Set, arguments, loc, false, prepared);
                        
                        if (temp != null) {
                                temp.Emit (ec);
@@ -8649,7 +8222,7 @@ namespace Mono.CSharp {
                
                public override string GetSignatureForError ()
                {
-                       return TypeManager.CSharpSignature (get != null ? get : set, false);
+                       return spec.GetSignatureForError ();
                }
 
 #if NET_4_0
@@ -8659,29 +8232,15 @@ namespace Mono.CSharp {
                        var args = Arguments.MakeExpression (arguments, ctx).Concat (value);
 
                        return SLE.Expression.Block (
-                                       SLE.Expression.Call (instance_expr.MakeExpression (ctx), set, args),
+                                       SLE.Expression.Call (instance_expr.MakeExpression (ctx), (MethodInfo) spec.Set.GetMetaInfo (), args),
                                        value [0]);
                }
+#endif
 
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        var args = Arguments.MakeExpression (arguments, ctx);
-                       return SLE.Expression.Call (instance_expr.MakeExpression (ctx), get, args);
-               }
-#endif
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       if (get != null)
-                               get = storey.MutateGenericMethod (get);
-                       if (set != null)
-                               set = storey.MutateGenericMethod (set);
-
-                       instance_expr.MutateHoistedGenericType (storey);
-                       if (arguments != null)
-                               arguments.MutateHoistedGenericType (storey);
-
-                       type = storey.MutateType (type);
+                       return SLE.Expression.Call (instance_expr.MakeExpression (ctx), (MethodInfo) spec.Get.GetMetaInfo (), args);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -8720,7 +8279,7 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ("ET");
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        Expression c = CommonResolve (ec);
 
@@ -8754,10 +8313,10 @@ namespace Mono.CSharp {
                Expression CommonResolve (ResolveContext ec)
                {
                        Expression member_lookup;
-                       Type current_type = ec.CurrentType;
-                       Type base_type = current_type.BaseType;
+                       TypeSpec current_type = ec.CurrentType;
+                       TypeSpec base_type = current_type.BaseType;
 
-                       if (!This.IsThisAvailable (ec)) {
+                       if (!This.IsThisAvailable (ec, false)) {
                                if (ec.IsStatic) {
                                        ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method");
                                } else {
@@ -8765,22 +8324,16 @@ namespace Mono.CSharp {
                                }
                                return null;
                        }
-                       
-                       member_lookup = MemberLookup (ec.Compiler, ec.CurrentType, null, base_type, Identifier,
-                                                     AllMemberTypes, AllBindingFlags, loc);
+
+                       var arity = args == null ? -1 : args.Count;
+                       member_lookup = MemberLookup (ec.Compiler, ec.CurrentType, null, base_type, Identifier, arity,
+                                                     MemberKind.All, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides, loc);
                        if (member_lookup == null) {
-                               Error_MemberLookupFailed (ec, ec.CurrentType, base_type, base_type, Identifier,
-                                       null, AllMemberTypes, AllBindingFlags);
+                               Error_MemberLookupFailed (ec, ec.CurrentType, base_type, base_type, Identifier, arity,
+                                       null, MemberKind.All, BindingRestriction.AccessibleOnly);
                                return null;
                        }
 
-                       Expression left;
-                       
-                       if (ec.IsStatic)
-                               left = new TypeExpression (base_type, loc);
-                       else
-                               left = ec.GetThis (loc);
-
                        MemberExpr me = member_lookup as MemberExpr;
                        if (me == null){
                                if (member_lookup is TypeExpression){
@@ -8794,11 +8347,8 @@ namespace Mono.CSharp {
                                return null;
                        }
                        
-                       me = me.ResolveMemberAccess (ec, left, loc, null);
-                       if (me == null)
-                               return null;
+                       me.QueriedBaseType = base_type;
 
-                       me.IsBase = true;
                        if (args != null) {
                                args.Resolve (ec);
                                me.SetTypeArguments (ec, args);
@@ -8897,7 +8447,7 @@ namespace Mono.CSharp {
                        loc = Location.Null;
                }
 
-               public EmptyExpression (Type t)
+               public EmptyExpression (TypeSpec t)
                {
                        type = t;
                        eclass = ExprClass.Value;
@@ -8909,7 +8459,7 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ("ET");
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        return this;
                }
@@ -8928,7 +8478,7 @@ namespace Mono.CSharp {
                // instead of creating gazillions of EmptyExpressions.
                // (CanImplicitConversion uses it)
                //
-               public void SetType (Type t)
+               public void SetType (TypeSpec t)
                {
                        type = t;
                }
@@ -8943,7 +8493,6 @@ namespace Mono.CSharp {
 
                private EmptyExpressionStatement ()
                {
-                       eclass = ExprClass.Value;
                        loc = Location.Null;
                }
 
@@ -8957,8 +8506,9 @@ namespace Mono.CSharp {
                        // Do nothing
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
+                       eclass = ExprClass.Value;
                        type = TypeManager.object_type;
                        return this;
                }
@@ -8970,14 +8520,14 @@ namespace Mono.CSharp {
        }       
 
        public class UserCast : Expression {
-               MethodInfo method;
+               MethodSpec method;
                Expression source;
                
-               public UserCast (MethodInfo method, Expression source, Location l)
+               public UserCast (MethodSpec method, Expression source, Location l)
                {
                        this.method = method;
                        this.source = source;
-                       type = TypeManager.TypeToCoreType (method.ReturnType);
+                       type = method.ReturnType;
                        loc = l;
                }
 
@@ -8996,9 +8546,9 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Convert", args);
                }
                        
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
+                       ObsoleteAttribute oa = method.GetAttributeObsolete ();
                        if (oa != null)
                                AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
 
@@ -9009,7 +8559,7 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        source.Emit (ec);
-                       ec.ig.Emit (OpCodes.Call, method);
+                       ec.Emit (OpCodes.Call, method);
                }
 
                public override string GetSignatureForError ()
@@ -9017,17 +8567,68 @@ namespace Mono.CSharp {
                        return TypeManager.CSharpSignature (method);
                }
 
-#if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       return SLE.Expression.Convert (source.MakeExpression (ctx), type, method);
+                       return SLE.Expression.Convert (source.MakeExpression (ctx), type.GetMetaInfo (), (MethodInfo) method.GetMetaInfo ());
+               }
+       }
+
+       //
+       // Holds additional type specifiers like ?, *, []
+       //
+       public class ComposedTypeSpecifier
+       {
+               public static readonly ComposedTypeSpecifier SingleDimension = new ComposedTypeSpecifier (1, Location.Null);
+
+               public readonly int Dimension;
+               public readonly Location Location;
+
+               public ComposedTypeSpecifier (int specifier, Location loc)
+               {
+                       this.Dimension = specifier;
+                       this.Location = loc;
+               }
+
+               #region Properties
+               public bool IsNullable {
+                       get {
+                               return Dimension == -1;
+                       }
+               }
+
+               public bool IsPointer {
+                       get {
+                               return Dimension == -2;
+                       }
+               }
+
+               public ComposedTypeSpecifier Next { get; set; }
+
+               #endregion
+
+               public static ComposedTypeSpecifier CreateArrayDimension (int dimension, Location loc)
+               {
+                       return new ComposedTypeSpecifier (dimension, loc);
+               }
+
+               public static ComposedTypeSpecifier CreateNullable (Location loc)
+               {
+                       return new ComposedTypeSpecifier (-1, loc);
+               }
+
+               public static ComposedTypeSpecifier CreatePointer (Location loc)
+               {
+                       return new ComposedTypeSpecifier (-2, loc);
                }
-#endif
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               public string GetSignatureForError ()
                {
-                       source.MutateHoistedGenericType (storey);
-                       method = storey.MutateGenericMethod (method);
+                       string s =
+                               IsPointer ? "*" :
+                               IsNullable ? "?" :
+                               ArrayContainer.GetPostfixSignature (Dimension);
+
+                       return Next != null ? s + Next.GetSignatureForError () : s;
                }
        }
 
@@ -9039,18 +8640,16 @@ namespace Mono.CSharp {
        // </summary>
        public class ComposedCast : TypeExpr {
                FullNamedExpression left;
-               string dim;
+               ComposedTypeSpecifier spec;
                
-               public ComposedCast (FullNamedExpression left, string dim)
-                       : this (left, dim, left.Location)
+               public ComposedCast (FullNamedExpression left, ComposedTypeSpecifier spec)
                {
-               }
+                       if (spec == null)
+                               throw new ArgumentNullException ("spec");
 
-               public ComposedCast (FullNamedExpression left, string dim, Location l)
-               {
                        this.left = left;
-                       this.dim = dim;
-                       loc = l;
+                       this.spec = spec;
+                       this.loc = spec.Location;
                }
 
                protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
@@ -9059,66 +8658,68 @@ namespace Mono.CSharp {
                        if (lexpr == null)
                                return null;
 
-                       Type ltype = lexpr.Type;
-                       if ((dim.Length > 0) && (dim [0] == '?')) {
-                               TypeExpr nullable = new Nullable.NullableType (lexpr, loc);
-                               if (dim.Length > 1)
-                                       nullable = new ComposedCast (nullable, dim.Substring (1), loc);
-                               return nullable.ResolveAsTypeTerminal (ec, false);
-                       }
+                       type = lexpr.Type;
+                       eclass = ExprClass.Type;
 
-                       if (dim == "*" && !TypeManager.VerifyUnManaged (ltype, loc))
-                               return null;
+                       var single_spec = spec;
+
+                       if (single_spec.IsNullable) {
+                               lexpr = new Nullable.NullableType (lexpr, loc);
+                               lexpr = lexpr.ResolveAsTypeTerminal (ec, false);
+                               if (lexpr != null)
+                                       type = lexpr.Type;
 
-                       if (dim.Length != 0 && dim [0] == '[') {
-                               if (TypeManager.IsSpecialType (ltype)) {
-                                       ec.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
+                               single_spec = single_spec.Next;
+                       } else if (single_spec.IsPointer) {
+                               if (!TypeManager.VerifyUnmanaged (ec.Compiler, type, loc))
                                        return null;
-                               }
 
-                               if ((ltype.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
-                                       ec.Compiler.Report.SymbolRelatedToPreviousError (ltype);
-                                       ec.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'", 
-                                               TypeManager.CSharpName (ltype));
+                               if (!ec.IsUnsafe) {
+                                       UnsafeError (ec.Compiler.Report, loc);
                                }
-                       }
-
-                       if (dim != "")
-                               type = TypeManager.GetConstructedType (ltype, dim);
-                       else
-                               type = ltype;
 
-                       if (type == null)
-                               throw new InternalErrorException ("Couldn't create computed type " + ltype + dim);
+                               type = PointerContainer.MakeType (type);
+                               single_spec = single_spec.Next;
+                       }
 
-                       if (type.IsPointer && !ec.IsUnsafe){
-                               UnsafeError (ec.Compiler.Report, loc);
+                       if (single_spec != null && single_spec.Dimension > 0) {
+                               if (TypeManager.IsSpecialType (type)) {
+                                       ec.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ());
+                               } else if (type.IsStatic) {
+                                       ec.Compiler.Report.SymbolRelatedToPreviousError (type);
+                                       ec.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'",
+                                               type.GetSignatureForError ());
+                               } else {
+                                       MakeArray (single_spec);
+                               }
                        }
 
-                       eclass = ExprClass.Type;
                        return this;
                }
 
-               public override string GetSignatureForError ()
+               void MakeArray (ComposedTypeSpecifier spec)
                {
-                       return left.GetSignatureForError () + dim;
+                       if (spec.Next != null)
+                               MakeArray (spec.Next);
+
+                       type = ArrayContainer.MakeType (type, spec.Dimension);
                }
 
-               public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
+               public override string GetSignatureForError ()
                {
-                       return ResolveAsBaseTerminal (ec, silent);
-               }               
+                       return left.GetSignatureForError () + spec.GetSignatureForError ();
+               }
        }
 
        public class FixedBufferPtr : Expression {
                Expression array;
 
-               public FixedBufferPtr (Expression array, Type array_type, Location l)
+               public FixedBufferPtr (Expression array, TypeSpec array_type, Location l)
                {
                        this.array = array;
                        this.loc = l;
 
-                       type = TypeManager.GetPointerType (array_type);
+                       type = PointerContainer.MakeType (array_type);
                        eclass = ExprClass.Value;
                }
 
@@ -9133,7 +8734,7 @@ namespace Mono.CSharp {
                        array.Emit (ec);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        //
                        // We are born fully resolved
@@ -9149,9 +8750,9 @@ namespace Mono.CSharp {
        // for fixed (char *pa = a)
        //
        public class ArrayPtr : FixedBufferPtr {
-               Type array_type;
+               TypeSpec array_type;
                
-               public ArrayPtr (Expression array, Type array_type, Location l):
+               public ArrayPtr (Expression array, TypeSpec array_type, Location l):
                        base (array, array_type, l)
                {
                        this.array_type = array_type;
@@ -9161,9 +8762,8 @@ namespace Mono.CSharp {
                {
                        base.Emit (ec);
                        
-                       ILGenerator ig = ec.ig;
-                       IntLiteral.EmitInt (ig, 0);
-                       ig.Emit (OpCodes.Ldelema, array_type);
+                       ec.EmitInt (0);
+                       ec.Emit (OpCodes.Ldelema, array_type);
                }
        }
 
@@ -9193,26 +8793,21 @@ namespace Mono.CSharp {
                        var expr_type = child.Type;
 
                        if (expr_type == TypeManager.uint32_type)
-                               ec.ig.Emit (OpCodes.Conv_U);
+                               ec.Emit (OpCodes.Conv_U);
                        else if (expr_type == TypeManager.int64_type)
-                               ec.ig.Emit (OpCodes.Conv_Ovf_I);
+                               ec.Emit (OpCodes.Conv_Ovf_I);
                        else if (expr_type == TypeManager.uint64_type)
-                               ec.ig.Emit (OpCodes.Conv_Ovf_I_Un);
+                               ec.Emit (OpCodes.Conv_Ovf_I_Un);
                        else
                                throw new InternalErrorException ("Cannot emit cast to unknown array element type", type);
                }
-
-               public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
-               {
-                       return child.GetAttributableValue (ec, value_type, out value);
-               }
        }
 
        //
        // Implements the `stackalloc' keyword
        //
        public class StackAlloc : Expression {
-               Type otype;
+               TypeSpec otype;
                Expression t;
                Expression count;
                
@@ -9228,7 +8823,7 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ("ET");
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        count = count.Resolve (ec);
                        if (count == null)
@@ -9255,10 +8850,10 @@ namespace Mono.CSharp {
 
                        otype = texpr.Type;
 
-                       if (!TypeManager.VerifyUnManaged (otype, loc))
+                       if (!TypeManager.VerifyUnmanaged (ec.Compiler, otype, loc))
                                return null;
 
-                       type = TypeManager.GetPointerType (otype);
+                       type = PointerContainer.MakeType (otype);
                        eclass = ExprClass.Value;
 
                        return this;
@@ -9267,17 +8862,16 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        int size = GetTypeSize (otype);
-                       ILGenerator ig = ec.ig;
 
                        count.Emit (ec);
 
                        if (size == 0)
-                               ig.Emit (OpCodes.Sizeof, otype);
+                               ec.Emit (OpCodes.Sizeof, otype);
                        else
-                               IntConstant.EmitInt (ig, size);
+                               ec.EmitInt (size);
 
-                       ig.Emit (OpCodes.Mul_Ovf_Un);
-                       ig.Emit (OpCodes.Localloc);
+                       ec.Emit (OpCodes.Mul_Ovf_Un);
+                       ec.Emit (OpCodes.Localloc);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -9322,13 +8916,13 @@ namespace Mono.CSharp {
                                args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        if (source == null)
                                return EmptyExpressionStatement.Instance;
                        
                        MemberExpr me = MemberLookupFinal (ec, ec.CurrentInitializerVariable.Type, ec.CurrentInitializerVariable.Type,
-                               Name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, loc) as MemberExpr;
+                               Name, 0, MemberKind.Field | MemberKind.Property, BindingRestriction.AccessibleOnly | BindingRestriction.InstanceOnly, loc) as MemberExpr;
 
                        if (me == null)
                                return null;
@@ -9349,24 +8943,13 @@ namespace Mono.CSharp {
                                return this;
                        }
 
-                       Expression expr = base.DoResolve (ec);
-                       if (expr == null)
-                               return null;
-
-                       //
-                       // Ignore field initializers with default value
-                       //
-                       Constant c = source as Constant;
-                       if (c != null && c.IsDefaultInitializer (type) && target.eclass == ExprClass.Variable)
-                               return EmptyExpressionStatement.Instance.DoResolve (ec);
-
-                       return expr;
+                       return base.DoResolve (ec);
                }
 
-               protected override Expression Error_MemberLookupFailed (ResolveContext ec, Type type, MemberInfo[] members)
+               protected override MemberExpr Error_MemberLookupFailed (ResolveContext ec, TypeSpec type, IList<MemberSpec> members)
                {
-                       MemberInfo member = members [0];
-                       if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field)
+                       var member = members.First ();
+                       if (member.Kind != MemberKind.Property && member.Kind != MemberKind.Field)
                                ec.Report.Error (1913, loc, "Member `{0}' cannot be initialized. An object " +
                                        "initializer may only be used for fields, or properties", TypeManager.GetFullNameSignature (member));
                        else
@@ -9405,7 +8988,7 @@ namespace Mono.CSharp {
                        {
                        }
 
-                       protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, Type type, string name)
+                       protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
                        {
                                if (TypeManager.HasElementType (type))
                                        return;
@@ -9421,7 +9004,7 @@ namespace Mono.CSharp {
                        this.loc = argument.Location;
                }
 
-               public CollectionElementInitializer (ArrayList arguments, Location loc)
+               public CollectionElementInitializer (List<Expression> arguments, Location loc)
                        : base (null, new Arguments (arguments.Count))
                {
                        foreach (Expression e in arguments)
@@ -9435,12 +9018,12 @@ namespace Mono.CSharp {
                        Arguments args = new Arguments (2);
                        args.Add (new Argument (mg.CreateExpressionTree (ec)));
 
-                       ArrayList expr_initializers = new ArrayList (arguments.Count);
+                       var expr_initializers = new ArrayInitializer (arguments.Count, loc);
                        foreach (Argument a in arguments)
                                expr_initializers.Add (a.CreateExpressionTree (ec));
 
                        args.Add (new Argument (new ArrayCreation (
-                               CreateExpressionTypeExpression (ec, loc), "[]", expr_initializers, loc)));
+                               CreateExpressionTypeExpression (ec, loc), expr_initializers, loc)));
                        return CreateExpressionFactoryCall (ec, "ElementInit", args);
                }
 
@@ -9451,11 +9034,8 @@ namespace Mono.CSharp {
                                target.arguments = arguments.Clone (clonectx);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-
                        base.expr = new AddMemberAccess (ec.CurrentInitializerVariable, loc);
 
                        return base.DoResolve (ec);
@@ -9467,13 +9047,13 @@ namespace Mono.CSharp {
        //
        public class CollectionOrObjectInitializers : ExpressionStatement
        {
-               ArrayList initializers;
+               IList<Expression> initializers;
                bool is_collection_initialization;
                
                public static readonly CollectionOrObjectInitializers Empty = 
-                       new CollectionOrObjectInitializers (new ArrayList (0), Location.Null);
+                       new CollectionOrObjectInitializers (Array.AsReadOnly (new Expression [0]), Location.Null);
 
-               public CollectionOrObjectInitializers (ArrayList initializers, Location loc)
+               public CollectionOrObjectInitializers (IList<Expression> initializers, Location loc)
                {
                        this.initializers = initializers;
                        this.loc = loc;
@@ -9495,42 +9075,39 @@ namespace Mono.CSharp {
                {
                        CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target;
 
-                       t.initializers = new ArrayList (initializers.Count);
-                       foreach (Expression e in initializers)
+                       t.initializers = new List<Expression> (initializers.Count);
+                       foreach (var e in initializers)
                                t.initializers.Add (e.Clone (clonectx));
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
-                       ArrayList expr_initializers = new ArrayList (initializers.Count);
+                       var expr_initializers = new ArrayInitializer (initializers.Count, loc);
                        foreach (Expression e in initializers) {
                                Expression expr = e.CreateExpressionTree (ec);
                                if (expr != null)
                                        expr_initializers.Add (expr);
                        }
 
-                       return new ImplicitlyTypedArrayCreation ("[]", expr_initializers, loc);
+                       return new ImplicitlyTypedArrayCreation (expr_initializers, loc);
                }
                
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-
-                       ArrayList element_names = null;
+                       List<string> element_names = null;
                        for (int i = 0; i < initializers.Count; ++i) {
-                               Expression initializer = (Expression) initializers [i];
+                               Expression initializer = initializers [i];
                                ElementInitializer element_initializer = initializer as ElementInitializer;
 
                                if (i == 0) {
                                        if (element_initializer != null) {
-                                               element_names = new ArrayList (initializers.Count);
+                                               element_names = new List<string> (initializers.Count);
                                                element_names.Add (element_initializer.Name);
                                        } else if (initializer is CompletingExpression){
                                                initializer.Resolve (ec);
                                                throw new InternalErrorException ("This line should never be reached");
                                        } else {
-                                               if (!TypeManager.ImplementsInterface (ec.CurrentInitializerVariable.Type, TypeManager.ienumerable_type)) {
+                                               if (!ec.CurrentInitializerVariable.Type.ImplementsInterface (TypeManager.ienumerable_type)) {
                                                        ec.Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " +
                                                                "object initializer because type `{1}' does not implement `{2}' interface",
                                                                ec.CurrentInitializerVariable.GetSignatureForError (),
@@ -9587,12 +9164,6 @@ namespace Mono.CSharp {
                        foreach (ExpressionStatement e in initializers)
                                e.EmitStatement (ec);
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       foreach (Expression e in initializers)
-                               e.MutateHoistedGenericType (storey);
-               }
        }
        
        //
@@ -9623,7 +9194,7 @@ namespace Mono.CSharp {
                                throw new NotSupportedException ("ET");
                        }
 
-                       public override Expression DoResolve (ResolveContext ec)
+                       protected override Expression DoResolve (ResolveContext ec)
                        {
                                return this;
                        }
@@ -9652,7 +9223,7 @@ namespace Mono.CSharp {
                CollectionOrObjectInitializers initializers;
                IMemoryLocation instance;
 
-               public NewInitialize (Expression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l)
+               public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l)
                        : base (requested_type, arguments, l)
                {
                        this.initializers = initializers;
@@ -9688,11 +9259,8 @@ namespace Mono.CSharp {
                                args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       if (eclass != ExprClass.Invalid)
-                               return this;
-                       
                        Expression e = base.DoResolve (ec);
                        if (type == null)
                                return null;
@@ -9746,25 +9314,21 @@ namespace Mono.CSharp {
                                return !initializers.IsEmpty;
                        }
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       base.MutateHoistedGenericType (storey);
-                       initializers.MutateHoistedGenericType (storey);
-               }
        }
 
-       public class AnonymousTypeDeclaration : Expression
+       public class NewAnonymousType : New
        {
-               ArrayList parameters;
+               static readonly AnonymousTypeParameter[] EmptyParameters = new AnonymousTypeParameter[0];
+
+               List<AnonymousTypeParameter> parameters;
                readonly TypeContainer parent;
-               static readonly ArrayList EmptyParameters = new ArrayList (0);
+               AnonymousTypeClass anonymous_type;
 
-               public AnonymousTypeDeclaration (ArrayList parameters, TypeContainer parent, Location loc)
+               public NewAnonymousType (List<AnonymousTypeParameter> parameters, TypeContainer parent, Location loc)
+                        : base (null, null, loc)
                {
                        this.parameters = parameters;
                        this.parent = parent;
-                       this.loc = loc;
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression target)
@@ -9772,13 +9336,13 @@ namespace Mono.CSharp {
                        if (parameters == null)
                                return;
 
-                       AnonymousTypeDeclaration t = (AnonymousTypeDeclaration) target;
-                       t.parameters = new ArrayList (parameters.Count);
+                       NewAnonymousType t = (NewAnonymousType) target;
+                       t.parameters = new List<AnonymousTypeParameter> (parameters.Count);
                        foreach (AnonymousTypeParameter atp in parameters)
-                               t.parameters.Add (atp.Clone (clonectx));
+                               t.parameters.Add ((AnonymousTypeParameter) atp.Clone (clonectx));
                }
 
-               AnonymousTypeClass CreateAnonymousType (ResolveContext ec, ArrayList parameters)
+               AnonymousTypeClass CreateAnonymousType (ResolveContext ec, IList<AnonymousTypeParameter> parameters)
                {
                        AnonymousTypeClass type = parent.Module.Compiled.GetAnonymousType (parameters);
                        if (type != null)
@@ -9788,7 +9352,9 @@ namespace Mono.CSharp {
                        if (type == null)
                                return null;
 
+                       type.CreateType ();
                        type.DefineType ();
+                       type.ResolveTypeParameters ();
                        type.Define ();
                        type.EmitType ();
                        if (ec.Report.Errors == 0)
@@ -9800,13 +9366,27 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
-                       throw new NotSupportedException ("ET");
+                       if (parameters == null)
+                               return base.CreateExpressionTree (ec);
+
+                       var init = new ArrayInitializer (parameters.Count, loc);
+                       foreach (Property p in anonymous_type.Properties)
+                               init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc));
+
+                       var ctor_args = new ArrayInitializer (Arguments.Count, loc);
+                       foreach (Argument a in Arguments)
+                               ctor_args.Add (a.CreateExpressionTree (ec));
+
+                       Arguments args = new Arguments (3);
+                       args.Add (new Argument (method.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new ArrayCreation (TypeManager.expression_type_expr, ctor_args, loc)));
+                       args.Add (new Argument (new ImplicitlyTypedArrayCreation (init, loc)));
+
+                       return CreateExpressionFactoryCall (ec, "New", args);
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       AnonymousTypeClass anonymous_type;
-
                        if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
                                ec.Report.Error (836, loc, "Anonymous types cannot be used in this expression");
                                return null;
@@ -9814,12 +9394,12 @@ namespace Mono.CSharp {
 
                        if (parameters == null) {
                                anonymous_type = CreateAnonymousType (ec, EmptyParameters);
-                               return new New (new TypeExpression (anonymous_type.TypeBuilder, loc),
-                                       null, loc).Resolve (ec);
+                               RequestedType = new TypeExpression (anonymous_type.Definition, loc);
+                               return base.DoResolve (ec);
                        }
 
                        bool error = false;
-                       Arguments arguments = new Arguments (parameters.Count);
+                       Arguments = new Arguments (parameters.Count);
                        TypeExpression [] t_args = new TypeExpression [parameters.Count];
                        for (int i = 0; i < parameters.Count; ++i) {
                                Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec);
@@ -9828,7 +9408,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               arguments.Add (new Argument (e));
+                               Arguments.Add (new Argument (e));
                                t_args [i] = new TypeExpression (e.Type, e.Location);
                        }
 
@@ -9839,15 +9419,8 @@ namespace Mono.CSharp {
                        if (anonymous_type == null)
                                return null;
 
-                       GenericTypeExpr te = new GenericTypeExpr (anonymous_type.TypeBuilder,
-                               new TypeArguments (t_args), loc);
-
-                       return new New (te, arguments, loc).Resolve (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new InternalErrorException ("Should not be reached");
+                       RequestedType = new GenericTypeExpr (anonymous_type.Definition, new TypeArguments (t_args), loc);
+                       return base.DoResolve (ec);
                }
        }
 
@@ -9880,7 +9453,7 @@ namespace Mono.CSharp {
                        return Name.GetHashCode ();
                }
 
-               public override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        Expression e = expr.Resolve (ec);
                        if (e == null)