2009-10-23 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / expression.cs
index 97d7b8f6e60d4a6c08998b49a722540053d8c013..d77b452517a2481af459d26d6ccb9dd08c5d6b5c 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
 
@@ -91,42 +93,22 @@ namespace Mono.CSharp {
                }
        }
 
-       public class ParenthesizedExpression : Expression
+       public class ParenthesizedExpression : ShimExpression
        {
-               public Expression Expr;
-
                public ParenthesizedExpression (Expression expr)
+                       : base (expr)
                {
-                       Expr = expr;
                        loc = expr.Location;
                }
 
-               public override Expression CreateExpressionTree (ResolveContext ec)
-               {
-                       throw new NotSupportedException ("ET");
-               }
-
                public override Expression DoResolve (ResolveContext ec)
                {
-                       Expr = Expr.Resolve (ec);
-                       return Expr;
+                       return expr.Resolve (ec);
                }
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
-                       return Expr.DoResolveLValue (ec, right_side);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Should not happen");
-               }
-
-               protected override void CloneTo (CloneContext clonectx, Expression t)
-               {
-                       ParenthesizedExpression target = (ParenthesizedExpression) t;
-
-                       target.Expr = Expr.Clone (clonectx);
+                       return expr.DoResolveLValue (ec, right_side);
                }
        }
        
@@ -614,6 +596,25 @@ namespace Mono.CSharp {
                        throw new NotImplementedException (oper.ToString ());
                }
 
+#if NET_4_0
+               public override SLE.Expression MakeExpression (BuilderContext ctx)
+               {
+                       var expr = Expr.MakeExpression (ctx);
+                       bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
+
+                       switch (Oper) {
+                       case Operator.UnaryNegation:
+                               return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr);
+                       case Operator.LogicalNot:
+                               return SLE.Expression.Not (expr);
+                       case Operator.OnesComplement:
+                               return SLE.Expression.OnesComplement (expr);
+                       default:
+                               throw new NotImplementedException (Oper.ToString ());
+                       }
+               }
+#endif
+
                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
                        type = storey.MutateType (type);
@@ -727,7 +728,7 @@ namespace Mono.CSharp {
 
                        Type[] predefined = predefined_operators [(int) Oper];
                        foreach (Type t in predefined) {
-                               Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false);
+                               Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false, false);
                                if (oper_expr == null)
                                        continue;
 
@@ -923,15 +924,12 @@ namespace Mono.CSharp {
                }
 
                Mode mode;
-               bool is_expr = false;
-               bool recurse = false;
+               bool is_expr, recurse;
 
                Expression expr;
 
-               //
-               // This is expensive for the simplest case.
-               //
-               UserOperatorCall method;
+               // Holds the real operation
+               Expression operation;
 
                public UnaryMutator (Mode m, Expression e)
                {
@@ -940,84 +938,6 @@ namespace Mono.CSharp {
                        expr = e;
                }
 
-               static string OperName (Mode mode)
-               {
-                       return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
-                               "++" : "--";
-               }
-
-               /// <summary>
-               ///   Returns whether an object of type `t' can be incremented
-               ///   or decremented with add/sub (ie, basically whether we can
-               ///   use pre-post incr-decr operations on it, but it is not a
-               ///   System.Decimal, which we require operator overloading to catch)
-               /// </summary>
-               static bool IsIncrementableNumber (Type t)
-               {
-                       return (t == TypeManager.sbyte_type) ||
-                               (t == TypeManager.byte_type) ||
-                               (t == TypeManager.short_type) ||
-                               (t == TypeManager.ushort_type) ||
-                               (t == TypeManager.int32_type) ||
-                               (t == TypeManager.uint32_type) ||
-                               (t == TypeManager.int64_type) ||
-                               (t == TypeManager.uint64_type) ||
-                               (t == TypeManager.char_type) ||
-                               (TypeManager.IsSubclassOf (t, TypeManager.enum_type)) ||
-                               (t == TypeManager.float_type) ||
-                               (t == TypeManager.double_type) ||
-                               (t.IsPointer && t != TypeManager.void_ptr_type);
-               }
-
-               Expression ResolveOperator (ResolveContext ec)
-               {
-                       type = expr.Type;
-                       
-                       //
-                       // The operand of the prefix/postfix increment decrement operators
-                       // should be an expression that is classified as a variable,
-                       // a property access or an indexer access
-                       //
-                       if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
-                               expr = expr.ResolveLValue (ec, expr);
-                       } else {
-                               ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
-                       }
-
-                       //
-                       // Step 1: Perform Operator Overload location
-                       //
-                       MethodGroupExpr mg;
-                       string op_name;
-                       
-                       if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
-                               op_name = Operator.GetMetadataName (Operator.OpType.Increment);
-                       else
-                               op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
-
-                       mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
-
-                       if (mg != null) {
-                               Arguments args = new Arguments (1);
-                               args.Add (new Argument (expr));
-                               mg = mg.OverloadResolve (ec, ref args, false, loc);
-                               if (mg == null)
-                                       return null;
-
-                               method = new UserOperatorCall (mg, args, null, loc);
-                               Convert.ImplicitConversionRequired (ec, method, type, loc);
-                               return this;
-                       }
-
-                       if (!IsIncrementableNumber (type)) {
-                               ec.Report.Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
-                                          TypeManager.CSharpName (type) + "'");
-                               return null;
-                       }
-
-                       return this;
-               }
-
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        return new SimpleAssign (this, this).CreateExpressionTree (ec);
@@ -1044,68 +964,6 @@ namespace Mono.CSharp {
                        return ResolveOperator (ec);
                }
 
-               //
-               // Loads the proper "1" into the stack based on the type, then it emits the
-               // opcode for the operation requested
-               //
-               void LoadOneAndEmitOp (EmitContext ec, Type t)
-               {
-                       //
-                       // Measure if getting the typecode and using that is more/less efficient
-                       // that comparing types.  t.GetTypeCode() is an internal call.
-                       //
-                       ILGenerator ig = ec.ig;
-                                                    
-                       if (t == TypeManager.uint64_type || t == TypeManager.int64_type)
-                               LongConstant.EmitLong (ig, 1);
-                       else if (t == TypeManager.double_type)
-                               ig.Emit (OpCodes.Ldc_R8, 1.0);
-                       else if (t == TypeManager.float_type)
-                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
-                       else if (t.IsPointer){
-                               Type et = TypeManager.GetElementType (t);
-                               int n = GetTypeSize (et);
-                               
-                               if (n == 0)
-                                       ig.Emit (OpCodes.Sizeof, et);
-                               else {
-                                       IntConstant.EmitInt (ig, n);
-                                       ig.Emit (OpCodes.Conv_I);
-                               }
-                       } else 
-                               ig.Emit (OpCodes.Ldc_I4_1);
-
-                       //
-                       // Now emit the operation
-                       //
-
-                       Binary.Operator op = (mode & Mode.IsDecrement) != 0 ? Binary.Operator.Subtraction : Binary.Operator.Addition;
-                       Binary.EmitOperatorOpcode (ec, op, t);
-
-                       if (t == TypeManager.sbyte_type){
-                               if (ec.HasSet (EmitContext.Options.CheckedScope))
-                                       ig.Emit (OpCodes.Conv_Ovf_I1);
-                               else
-                                       ig.Emit (OpCodes.Conv_I1);
-                       } else if (t == TypeManager.byte_type){
-                               if (ec.HasSet (EmitContext.Options.CheckedScope))
-                                       ig.Emit (OpCodes.Conv_Ovf_U1);
-                               else
-                                       ig.Emit (OpCodes.Conv_U1);
-                       } else if (t == TypeManager.short_type){
-                               if (ec.HasSet (EmitContext.Options.CheckedScope))
-                                       ig.Emit (OpCodes.Conv_Ovf_I2);
-                               else
-                                       ig.Emit (OpCodes.Conv_I2);
-                       } else if (t == TypeManager.ushort_type || t == TypeManager.char_type){
-                               if (ec.HasSet (EmitContext.Options.CheckedScope))
-                                       ig.Emit (OpCodes.Conv_Ovf_U2);
-                               else
-                                       ig.Emit (OpCodes.Conv_U2);
-                       }
-                       
-               }
-
                void EmitCode (EmitContext ec, bool is_expr)
                {
                        recurse = true;
@@ -1122,10 +980,9 @@ namespace Mono.CSharp {
                        //
                        if (recurse) {
                                ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement));
-                               if (method == null)
-                                       LoadOneAndEmitOp (ec, expr.Type);
-                               else
-                                       ec.ig.Emit (OpCodes.Call, (MethodInfo)method.Method);
+
+                               operation.Emit (ec);
+
                                recurse = false;
                                return;
                        }
@@ -1143,11 +1000,34 @@ namespace Mono.CSharp {
                //
                string GetOperatorExpressionTypeName ()
                {
-                       if ((mode & Mode.IsDecrement) != 0)
-                               return "Decrement";
+                       return IsDecrement ? "Decrement" : "Increment";
+               }
+
+               bool IsDecrement {
+                       get { return (mode & Mode.IsDecrement) != 0; }
+               }
+
+               //
+               //   Returns whether an object of type `t' can be incremented
+               //   or decremented with add/sub (ie, basically whether we can
+               //   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)
+               {
+                       return (TypeManager.IsPrimitiveType (t) && t != TypeManager.bool_type) ||
+                               TypeManager.IsEnumType (t) ||
+                               t.IsPointer && t != TypeManager.void_ptr_type;
+               }
 
-                       return "Increment";
+#if NET_4_0
+               public override SLE.Expression MakeExpression (BuilderContext ctx)
+               {
+                       var target = ((RuntimeValueExpression) expr).MetaObject.Expression;
+                       var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type);
+                       return SLE.Expression.Assign (target, source);
                }
+#endif
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
@@ -1155,6 +1035,80 @@ namespace Mono.CSharp {
 
                        target.expr = expr.Clone (clonectx);
                }
+
+               Expression ResolveOperator (ResolveContext ec)
+               {
+                       type = expr.Type;
+
+                       if (expr is RuntimeValueExpression) {
+                               operation = expr;
+                       } else {
+                               // Use itself at the top of the stack
+                               operation = new EmptyExpression (type);
+                       }
+
+                       //
+                       // The operand of the prefix/postfix increment decrement operators
+                       // should be an expression that is classified as a variable,
+                       // a property access or an indexer access
+                       //
+                       if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
+                               expr = expr.ResolveLValue (ec, expr);
+                       } else {
+                               ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
+                       }
+
+                       //
+                       // 1. Check predefined types
+                       //
+                       if (IsPredefinedOperator (type)) {
+                               // TODO: Move to IntConstant once I get rid of int32_type
+                               var one = new IntConstant (1, loc);
+
+                               // 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 = operation.Resolve (ec);
+                               if (operation.Type != type)
+                                       operation = Convert.ExplicitNumericConversion (operation, type);
+
+                               return this;
+                       }
+
+                       //
+                       // Step 2: Perform Operator Overload location
+                       //
+                       MethodGroupExpr mg;
+                       string op_name;
+
+                       if (IsDecrement)
+                               op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
+                       else
+                               op_name = Operator.GetMetadataName (Operator.OpType.Increment);
+
+                       mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+
+                       if (mg != null) {
+                               Arguments args = new Arguments (1);
+                               args.Add (new Argument (expr));
+                               mg = mg.OverloadResolve (ec, ref args, false, loc);
+                               if (mg == null)
+                                       return null;
+
+                               args[0].Expr = operation;
+                               operation = new UserOperatorCall (mg, args, null, loc);
+                               operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
+                               return this;
+                       }
+
+                       string name = IsDecrement ?
+                               Operator.GetName (Operator.OpType.Decrement) :
+                               Operator.GetName (Operator.OpType.Increment);
+
+                       Unary.Error_OperatorCannotBeApplied (ec, loc, name, type);
+                       return null;
+               }
        }
 
        /// <summary>
@@ -1420,10 +1374,8 @@ namespace Mono.CSharp {
                        if (do_isinst)
                                ig.Emit (OpCodes.Isinst, type);
 
-#if GMCS_SOURCE
                        if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type))
                                ig.Emit (OpCodes.Unbox_Any, type);
-#endif
                }
 
                public override Expression DoResolve (ResolveContext ec)
@@ -1510,9 +1462,8 @@ namespace Mono.CSharp {
        ///   FIXME: Cast expressions have an unusual set of parsing
        ///   rules, we need to figure those out.
        /// </summary>
-       public class Cast : Expression {
+       public class Cast : ShimExpression {
                Expression target_type;
-               Expression expr;
                        
                public Cast (Expression cast_type, Expression expr)
                        : this (cast_type, expr, cast_type.Location)
@@ -1520,9 +1471,9 @@ namespace Mono.CSharp {
                }
 
                public Cast (Expression cast_type, Expression expr, Location loc)
+                       : base (expr)
                {
                        this.target_type = cast_type;
-                       this.expr = expr;
                        this.loc = loc;
                }
 
@@ -1530,15 +1481,6 @@ namespace Mono.CSharp {
                        get { return target_type; }
                }
 
-               public Expression Expr {
-                       get { return expr; }
-               }
-
-               public override Expression CreateExpressionTree (ResolveContext ec)
-               {
-                       throw new NotSupportedException ("ET");
-               }
-
                public override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
@@ -1570,18 +1512,13 @@ namespace Mono.CSharp {
                        } else if (TypeManager.IsDynamicType (expr.Type)) {
                                Arguments arg = new Arguments (1);
                                arg.Add (new Argument (expr));
-                               return new DynamicConversion (type, true, arg, loc).Resolve (ec);
+                               return new DynamicConversion (type, CSharpBinderFlags.ConvertExplicit, arg, loc).Resolve (ec);
                        }
 
                        expr = Convert.ExplicitConversion (ec, expr, type, loc);
                        return expr;
                }
                
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Should not happen");
-               }
-
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Cast target = (Cast) t;
@@ -1590,6 +1527,33 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                }
        }
+
+       public class ImplicitCast : ShimExpression
+       {
+               bool arrayAccess;
+
+               public ImplicitCast (Expression expr, Type target, bool arrayAccess)
+                       : base (expr)
+               {
+                       this.loc = expr.Location;
+                       this.type = target;
+                       this.arrayAccess = arrayAccess;
+               }
+
+               public override Expression DoResolve (ResolveContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       if (arrayAccess)
+                               expr = ConvertExpressionToArrayIndex (ec, expr);
+                       else
+                               expr = Convert.ImplicitConversionRequired (ec, expr, type, loc);
+
+                       return expr;
+               }
+       }
        
        //
        // C# 2.0 Default value expression
@@ -1815,7 +1779,7 @@ namespace Mono.CSharp {
                        {
                                b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
 
-                               Expression expr_tree_expr = EmptyCast.Create (b.right, TypeManager.int32_type);
+                               Expression expr_tree_expr = Convert.ImplicitConversion (ec, b.right, TypeManager.int32_type, b.right.Location);
 
                                int right_mask = left == TypeManager.int32_type || left == TypeManager.uint32_type ? 0x1f : 0x3f;
 
@@ -2650,7 +2614,7 @@ namespace Mono.CSharp {
                                if (e != null || ec.Report.Errors != prev_e)
                                        return e;
                        } else if ((oper == Operator.BitwiseAnd || oper == Operator.LogicalAnd) && !TypeManager.IsDynamicType (left.Type) &&
-                                       ((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue))) {
+                                       ((lc != null && lc.IsDefaultValue && !(lc is NullLiteral)) || (rc != null && rc.IsDefaultValue && !(rc is NullLiteral)))) {
 
                                if ((ResolveOperator (ec)) == null) {
                                        Error_OperatorCannotBeApplied (ec, left, right);
@@ -2718,6 +2682,40 @@ namespace Mono.CSharp {
                        switch (oper) {
                        case Operator.Addition:
                                return is_checked ? SLE.Expression.AddChecked (le, re) : SLE.Expression.Add (le, re);
+                       case Operator.BitwiseAnd:
+                               return SLE.Expression.And (le, re);
+                       case Operator.BitwiseOr:
+                               return SLE.Expression.Or (le, re);
+                       case Operator.Division:
+                               return SLE.Expression.Divide (le, re);
+                       case Operator.Equality:
+                               return SLE.Expression.Equal (le, re);
+                       case Operator.ExclusiveOr:
+                               return SLE.Expression.ExclusiveOr (le, re);
+                       case Operator.GreaterThan:
+                               return SLE.Expression.GreaterThan (le, re);
+                       case Operator.GreaterThanOrEqual:
+                               return SLE.Expression.GreaterThanOrEqual (le, re);
+                       case Operator.Inequality:
+                               return SLE.Expression.NotEqual (le, re);
+                       case Operator.LeftShift:
+                               return SLE.Expression.LeftShift (le, re);
+                       case Operator.LessThan:
+                               return SLE.Expression.LessThan (le, re);
+                       case Operator.LessThanOrEqual:
+                               return SLE.Expression.LessThanOrEqual (le, re);
+                       case Operator.LogicalAnd:
+                               return SLE.Expression.AndAlso (le, re);
+                       case Operator.LogicalOr:
+                               return SLE.Expression.OrElse (le, re);
+                       case Operator.Modulus:
+                               return SLE.Expression.Modulo (le, re);
+                       case Operator.Multiply:
+                               return is_checked ? SLE.Expression.MultiplyChecked (le, re) : SLE.Expression.Multiply (le, re);
+                       case Operator.RightShift:
+                               return SLE.Expression.RightShift (le, re);
+                       case Operator.Subtraction:
+                               return is_checked ? SLE.Expression.SubtractChecked (le, re) : SLE.Expression.Subtract (le, re);
                        default:
                                throw new NotImplementedException (oper.ToString ());
                        }
@@ -2923,17 +2921,29 @@ namespace Mono.CSharp {
                                return expr;
 
                        //
-                       // TODO: Need to corectly implemented Coumpound Assigment for all operators
                        // Section: 7.16.2
                        //
-                       if (Convert.ImplicitConversionExists (ec, left, rtype))
+
+                       //
+                       // If the return type of the selected operator is implicitly convertible to the type of x
+                       //
+                       if (Convert.ImplicitConversionExists (ec, expr, ltype))
                                return expr;
 
-                       if (!Convert.ImplicitConversionExists (ec, ltemp, rtype))
+                       //
+                       // Otherwise, if the selected operator is a predefined operator, if the return type of the
+                       // selected operator is explicitly convertible to the type of x, and if y is implicitly
+                       // convertible to the type of x or the operator is a shift operator, then the operation
+                       // is evaluated as x = (T)(x op y), where T is the type of x
+                       //
+                       expr = Convert.ExplicitConversion (ec, expr, ltype, loc);
+                       if (expr == null)
                                return null;
 
-                       expr = Convert.ExplicitConversion (ec, expr, rtype, loc);
-                       return expr;
+                       if (Convert.ImplicitConversionExists (ec, ltemp, ltype))
+                               return expr;
+
+                       return null;
                }
 
                //
@@ -3015,7 +3025,9 @@ namespace Mono.CSharp {
                        if (lgen) {
                                if (!TypeManager.IsReferenceType (l))
                                        return null;
-                               left = new BoxedCast (left, TypeManager.object_type);
+
+                               l = TypeManager.object_type;
+                               left = new BoxedCast (left, l);
                        } else if (l.IsInterface) {
                                l = TypeManager.object_type;
                        } else if (TypeManager.IsStruct (l)) {
@@ -3025,7 +3037,9 @@ namespace Mono.CSharp {
                        if (rgen) {
                                if (!TypeManager.IsReferenceType (r))
                                        return null;
-                               right = new BoxedCast (right, TypeManager.object_type);
+
+                               r = TypeManager.object_type;
+                               right = new BoxedCast (right, r);
                        } else if (r.IsInterface) {
                                r = TypeManager.object_type;
                        } else if (TypeManager.IsStruct (r)) {
@@ -3128,7 +3142,7 @@ namespace Mono.CSharp {
 
                                if (best_operator == null) {
                                        ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
-                                               OperName (oper), left.GetSignatureForError (), right.GetSignatureForError ());
+                                               OperName (oper), TypeManager.CSharpName (l), TypeManager.CSharpName (r));
 
                                        best_operator = po;
                                        break;
@@ -3593,21 +3607,23 @@ namespace Mono.CSharp {
 
                public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
                {
-                       Arguments binder_args = new Arguments (4);
+                       Arguments binder_args = new Arguments (3);
 
                        MemberAccess sle = new MemberAccess (new MemberAccess (
                                new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);
 
-                       MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc);
+                       CSharpBinderFlags flags = 0;
+                       if (ec.HasSet (ResolveContext.Options.CheckedScope))
+                               flags = CSharpBinderFlags.CheckedContext;
 
-                       binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
-                       binder_args.Add (new Argument (new BoolLiteral (ec.HasSet (ResolveContext.Options.CheckedScope), loc)));
+                       if ((oper & Operator.LogicalMask) != 0)
+                               flags |= CSharpBinderFlags.BinaryOperationLogical;
 
-                       bool member_access = left is DynamicMemberBinder || right is DynamicMemberBinder;
-                       binder_args.Add (new Argument (new BoolLiteral (member_access, loc)));
+                       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 (), loc)));
 
-                       return new New (new MemberAccess (binder, "CSharpBinaryOperationBinder", loc), binder_args, loc);
+                       return new Invocation (DynamicExpressionStatement.GetBinder ("BinaryOperation", loc), binder_args);
                }
                
                public override Expression CreateExpressionTree (ResolveContext ec)
@@ -4027,14 +4043,76 @@ namespace Mono.CSharp {
                        }
                }
        }
+
+       //
+       // A boolean-expression is an expression that yields a result
+       // of type bool
+       //
+       public class BooleanExpression : ShimExpression
+       {
+               public BooleanExpression (Expression expr)
+                       : base (expr)
+               {
+                       this.loc = expr.Location;
+               }
+
+               public override Expression CreateExpressionTree (ResolveContext ec)
+               {
+                       // TODO: We should emit IsTrue (v4) instead of direct user operator
+                       // call but that would break csc compatibility
+                       return base.CreateExpressionTree (ec);
+               }
+
+               public override Expression DoResolve (ResolveContext ec)
+               {
+                       // A boolean-expression is required to be of a type
+                       // that can be implicitly converted to bool or of
+                       // a type that implements operator true
+
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       Assign ass = expr as Assign;
+                       if (ass != null && ass.Source is Constant) {
+                               ec.Report.Warning (665, 3, loc,
+                                       "Assignment in conditional expression is always constant. Did you mean to use `==' instead ?");
+                       }
+
+                       if (expr.Type == TypeManager.bool_type)
+                               return expr;
+
+                       if (TypeManager.IsDynamicType (expr.Type)) {
+                               Arguments args = new Arguments (1);
+                               args.Add (new Argument (expr));
+                               return new DynamicUnaryConversion ("IsTrue", args, loc).Resolve (ec);
+                       }
+
+                       type = TypeManager.bool_type;
+                       Expression converted = Convert.ImplicitConversion (ec, expr, type, loc);
+                       if (converted != null)
+                               return converted;
+
+                       //
+                       // If no implicit conversion to bool exists, try using `operator true'
+                       //
+                       converted = GetOperatorTrue (ec, expr, loc);
+                       if (converted == null) {
+                               expr.Error_ValueCannotBeConverted (ec, loc, type, false);
+                               return null;
+                       }
+
+                       return converted;
+               }
+       }
        
        /// <summary>
        ///   Implements the ternary conditional operator (?:)
        /// </summary>
        public class Conditional : Expression {
                Expression expr, true_expr, false_expr;
-               
-               public Conditional (Expression expr, Expression true_expr, Expression false_expr)
+
+               public Conditional (BooleanExpression expr, Expression true_expr, Expression false_expr)
                {
                        this.expr = expr;
                        this.true_expr = true_expr;
@@ -4071,13 +4149,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (ResolveContext ec)
                {
-                       expr = Expression.ResolveBoolean (ec, expr, loc);
-                       
-                       Assign ass = expr as Assign;
-                       if (ass != null && ass.Source is Constant) {
-                               ec.Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
-                       }
-
+                       expr = expr.Resolve (ec);
                        true_expr = true_expr.Resolve (ec);
                        false_expr = false_expr.Resolve (ec);
 
@@ -4114,7 +4186,7 @@ namespace Mono.CSharp {
                                } else {
                                        ec.Report.Error (173, loc,
                                                "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
-                                               true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
+                                               TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type));
                                        return null;
                                }
                        }                       
@@ -4217,6 +4289,11 @@ namespace Mono.CSharp {
                        return GetHoistedVariable (ec.CurrentAnonymousMethod);
                }
 
+               public override string GetSignatureForError ()
+               {
+                       return Name;
+               }
+
                public override void Emit (EmitContext ec)
                {
                        Emit (ec, false);
@@ -4904,14 +4981,7 @@ namespace Mono.CSharp {
                                        }
                                }
                        }
-
-                       if (type.IsPointer){
-                               if (!ec.IsUnsafe){
-                                       UnsafeError (ec, loc);
-                                       return null;
-                               }
-                       }
-                       
+               
                        //
                        // Only base will allow this invocation to happen.
                        //
@@ -4973,7 +5043,7 @@ namespace Mono.CSharp {
                                return false;
 
                        method = TypeManager.DropGenericMethodArguments (method);
-                       if (method.DeclaringType.Module == RootContext.ToplevelTypes.Builder) {
+                       if (TypeManager.IsBeingCompiled (method)) {
                                IMethodData md = TypeManager.GetMethod (method);
                                if (md != null)
                                        return md.IsExcluded ();
@@ -5104,10 +5174,8 @@ namespace Mono.CSharp {
                        } else {
                                call_op = OpCodes.Callvirt;
                                
-#if GMCS_SOURCE
                                if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
                                        ig.Emit (OpCodes.Constrained, instance_expr.Type);
-#endif
                        }
 
                        if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
@@ -5154,122 +5222,37 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       mg.MutateHoistedGenericType (storey);
-                       type = storey.MutateType (type);
-                       if (arguments != null) {
-                               arguments.MutateHoistedGenericType (storey);
-                       }
-               }
-       }
-/*
-       //
-       // It's either a cast or delegate invocation
-       //
-       public class InvocationOrCast : ExpressionStatement
-       {
-               Expression expr;
-               Expression argument;
-
-               public InvocationOrCast (Expression expr, Expression argument)
-               {
-                       this.expr = expr;
-                       this.argument = argument;
-                       this.loc = expr.Location;
-               }
-
-               public override Expression CreateExpressionTree (ResolveContext ec)
-               {
-                       throw new NotSupportedException ("ET");
-               }
-
-               public override Expression DoResolve (ResolveContext ec)
+#if NET_4_0
+               public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       Expression e = ResolveCore (ec);
-                       if (e == null)
-                               return null;
-
-                       return e.Resolve (ec);
+                       return MakeExpression (ctx, mg.InstanceExpression, (MethodInfo) mg, arguments);
                }
 
-               Expression ResolveCore (EmitContext ec)
+               public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodInfo mi, Arguments args)
                {
-                       //
-                       // First try to resolve it as a cast.
-                       //
-                       TypeExpr te = expr.ResolveAsBaseTerminal (ec, true);
-                       if (te != null) {
-                               return new Cast (te, argument, loc);
-                       }
+                       var instance_expr = instance == null ? null : instance.MakeExpression (ctx);
+                       SLE.Expression expr = SLE.Expression.Call (instance_expr, mi,
+                               Arguments.MakeExpression (args, ctx));
 
-                       //
-                       // This can either be a type or a delegate invocation.
-                       // Let's just resolve it and see what we'll get.
-                       //
-                       expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
-                       if (expr == null)
-                               return null;
-
-                       //
-                       // Ok, so it's a Cast.
-                       //
-                       if (expr.eclass == ExprClass.Type || expr.eclass == ExprClass.TypeParameter) {
-                               return new Cast (expr, argument, loc);
-                       }
-
-                       if (expr.eclass == ExprClass.Namespace) {
-                               expr.Error_UnexpectedKind (null, "type", loc);
-                               return null;
-                       }                       
-
-                       //
-                       // It's a delegate invocation.
-                       //
-                       if (!TypeManager.IsDelegateType (expr.Type)) {
-                               Error (149, "Method name expected");
-                               return null;
+                       if (mi.ReturnType == typeof (void)) {
+                               expr = SLE.Expression.Block (
+                                       expr,
+                                       SLE.Expression.Default (typeof (object)));
                        }
 
-                       ArrayList args = new ArrayList (1);
-                       args.Add (new Argument (argument, Argument.AType.Expression));
-                       return new DelegateInvocation (expr, args, loc);
+                       return expr;
                }
+#endif
 
-               public override ExpressionStatement ResolveStatement (EmitContext ec)
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
-                       Expression e = ResolveCore (ec);
-                       if (e == null)
-                               return null;
-
-                       ExpressionStatement s = e as ExpressionStatement;
-                       if (s == null) {
-                               Error_InvalidExpressionStatement ();
-                               return null;
+                       mg.MutateHoistedGenericType (storey);
+                       type = storey.MutateType (type);
+                       if (arguments != null) {
+                               arguments.MutateHoistedGenericType (storey);
                        }
-
-                       return s.ResolveStatement (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Cannot happen");
-               }
-
-               public override void EmitStatement (EmitContext ec)
-               {
-                       throw new Exception ("Cannot happen");
-               }
-
-               protected override void CloneTo (CloneContext clonectx, Expression t)
-               {
-                       InvocationOrCast target = (InvocationOrCast) t;
-
-                       target.expr = expr.Clone (clonectx);
-                       target.argument = argument.Clone (clonectx);
                }
        }
-*/
 
        /// <summary>
        ///    Implements the new expression 
@@ -5499,9 +5482,7 @@ namespace Mono.CSharp {
 
                bool DoEmitTypeParameter (EmitContext ec)
                {
-#if GMCS_SOURCE
                        ILGenerator ig = ec.ig;
-//                     IMemoryLocation ml;
 
                        MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod (
                                new Type [] { type });
@@ -5537,9 +5518,6 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Call, ci);
                        ig.MarkLabel (label_end);
                        return true;
-#else
-                       throw new InternalErrorException ();
-#endif
                }
 
                //
@@ -5734,8 +5712,10 @@ namespace Mono.CSharp {
                int num_arguments = 0;
                protected int dimensions;
                protected readonly string rank;
+               Expression first_emit;
+               LocalTemporary first_emit_temp;
 
-               protected ArrayList array_data;
+               protected List<Expression> array_data;
 
                IDictionary bounds;
 
@@ -5853,14 +5833,8 @@ namespace Mono.CSharp {
                        if (array_data == null) {
                                args = new Arguments (arguments.Count + 1);
                                args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
-                               foreach (Expression a in arguments) {
-                                       if (arguments.Count == 1) {
-                                               Constant c = a as Constant;
-                                               if (c.IsDefaultValue)
-                                                       return CreateExpressionFactoryCall (ec, "NewArrayInit", args);
-                                       }
+                               foreach (Expression a in arguments)
                                        args.Add (new Argument (a.CreateExpressionTree (ec)));
-                               }
 
                                return CreateExpressionFactoryCall (ec, "NewArrayBounds", args);
                        }
@@ -5874,7 +5848,7 @@ namespace Mono.CSharp {
                        args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
                        if (array_data != null) {
                                for (int i = 0; i < array_data.Count; ++i) {
-                                       Expression e = (Expression) array_data [i];
+                                       Expression e = array_data [i];
                                        if (e == null)
                                                e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc);
 
@@ -5905,12 +5879,8 @@ namespace Mono.CSharp {
                                        return;
                                }
                        }
-
                }
 
-               Expression first_emit;
-               LocalTemporary first_emit_temp;
-
                protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element)
                {
                        element = element.Resolve (ec);
@@ -5938,7 +5908,7 @@ namespace Mono.CSharp {
                        // 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 ArrayList ();
+                       array_data = new List<Expression> ();
                        bounds = new System.Collections.Specialized.HybridDictionary ();
                        
                        if (arguments != null)
@@ -6052,12 +6022,13 @@ namespace Mono.CSharp {
                        byte [] element;
                        int count = array_data.Count;
 
-                       if (TypeManager.IsEnumType (array_element_type))
-                               array_element_type = TypeManager.GetEnumUnderlyingType (array_element_type);
-                       
-                       factor = GetTypeSize (array_element_type);
+                       Type element_type = array_element_type;
+                       if (TypeManager.IsEnumType (element_type))
+                               element_type = TypeManager.GetEnumUnderlyingType (element_type);
+
+                       factor = GetTypeSize (element_type);
                        if (factor == 0)
-                               throw new Exception ("unrecognized type in MakeByteBlob: " + array_element_type);
+                               throw new Exception ("unrecognized type in MakeByteBlob: " + element_type);
 
                        data = new byte [(count * factor + 3) & ~3];
                        int idx = 0;
@@ -6075,7 +6046,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
                                
-                               if (array_element_type == TypeManager.int64_type){
+                               if (element_type == TypeManager.int64_type){
                                        if (!(v is Expression)){
                                                long val = (long) v;
                                                
@@ -6084,7 +6055,7 @@ namespace Mono.CSharp {
                                                        val = (val >> 8);
                                                }
                                        }
-                               } else if (array_element_type == TypeManager.uint64_type){
+                               } else if (element_type == TypeManager.uint64_type){
                                        if (!(v is Expression)){
                                                ulong val = (ulong) v;
 
@@ -6093,7 +6064,7 @@ namespace Mono.CSharp {
                                                        val = (val >> 8);
                                                }
                                        }
-                               } else if (array_element_type == TypeManager.float_type) {
+                               } else if (element_type == TypeManager.float_type) {
                                        if (!(v is Expression)){
                                                element = BitConverter.GetBytes ((float) v);
                                                        
@@ -6102,7 +6073,7 @@ namespace Mono.CSharp {
                                                if (!BitConverter.IsLittleEndian)
                                                        System.Array.Reverse (data, idx, 4);
                                        }
-                               } else if (array_element_type == TypeManager.double_type) {
+                               } else if (element_type == TypeManager.double_type) {
                                        if (!(v is Expression)){
                                                element = BitConverter.GetBytes ((double) v);
 
@@ -6113,28 +6084,28 @@ namespace Mono.CSharp {
                                                if (!BitConverter.IsLittleEndian)
                                                        System.Array.Reverse (data, idx, 8);
                                        }
-                               } else if (array_element_type == TypeManager.char_type){
+                               } else if (element_type == TypeManager.char_type){
                                        if (!(v is Expression)){
                                                int val = (int) ((char) v);
                                                
                                                data [idx] = (byte) (val & 0xff);
                                                data [idx+1] = (byte) (val >> 8);
                                        }
-                               } else if (array_element_type == TypeManager.short_type){
+                               } else if (element_type == TypeManager.short_type){
                                        if (!(v is Expression)){
                                                int val = (int) ((short) v);
                                        
                                                data [idx] = (byte) (val & 0xff);
                                                data [idx+1] = (byte) (val >> 8);
                                        }
-                               } else if (array_element_type == TypeManager.ushort_type){
+                               } else if (element_type == TypeManager.ushort_type){
                                        if (!(v is Expression)){
                                                int val = (int) ((ushort) v);
                                        
                                                data [idx] = (byte) (val & 0xff);
                                                data [idx+1] = (byte) (val >> 8);
                                        }
-                               } else if (array_element_type == TypeManager.int32_type) {
+                               } else if (element_type == TypeManager.int32_type) {
                                        if (!(v is Expression)){
                                                int val = (int) v;
                                        
@@ -6143,7 +6114,7 @@ namespace Mono.CSharp {
                                                data [idx+2] = (byte) ((val >> 16) & 0xff);
                                                data [idx+3] = (byte) (val >> 24);
                                        }
-                               } else if (array_element_type == TypeManager.uint32_type) {
+                               } else if (element_type == TypeManager.uint32_type) {
                                        if (!(v is Expression)){
                                                uint val = (uint) v;
                                        
@@ -6152,22 +6123,22 @@ namespace Mono.CSharp {
                                                data [idx+2] = (byte) ((val >> 16) & 0xff);
                                                data [idx+3] = (byte) (val >> 24);
                                        }
-                               } else if (array_element_type == TypeManager.sbyte_type) {
+                               } else if (element_type == TypeManager.sbyte_type) {
                                        if (!(v is Expression)){
                                                sbyte val = (sbyte) v;
                                                data [idx] = (byte) val;
                                        }
-                               } else if (array_element_type == TypeManager.byte_type) {
+                               } else if (element_type == TypeManager.byte_type) {
                                        if (!(v is Expression)){
                                                byte val = (byte) v;
                                                data [idx] = (byte) val;
                                        }
-                               } else if (array_element_type == TypeManager.bool_type) {
+                               } else if (element_type == TypeManager.bool_type) {
                                        if (!(v is Expression)){
                                                bool val = (bool) v;
                                                data [idx] = (byte) (val ? 1 : 0);
                                        }
-                               } else if (array_element_type == TypeManager.decimal_type){
+                               } else if (element_type == TypeManager.decimal_type){
                                        if (!(v is Expression)){
                                                int [] bits = Decimal.GetBits ((decimal) v);
                                                int p = idx;
@@ -6186,15 +6157,31 @@ namespace Mono.CSharp {
                                                        data [p++] = (byte) (nbits [j] >> 24);
                                                }
                                        }
-                               } else
-                                       throw new Exception ("Unrecognized type in MakeByteBlob: " + array_element_type);
+                               } else {
+                                       throw new Exception ("Unrecognized type in MakeByteBlob: " + element_type);
+                               }
 
-                                idx += factor;
+                               idx += factor;
                        }
 
                        return data;
                }
 
+#if NET_4_0
+               public override SLE.Expression MakeExpression (BuilderContext ctx)
+               {
+                       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);
+                               else
+                                       initializers [i] = array_data [i].MakeExpression (ctx);
+                       }
+
+                       return SLE.Expression.NewArrayInit (array_element_type, initializers);
+               }
+#endif
+
                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
                        array_element_type = storey.MutateType (array_element_type);
@@ -6337,7 +6324,7 @@ namespace Mono.CSharp {
                                e.Emit (ec);
 
                        if (arguments.Count == 1)
-                               ig.Emit (OpCodes.Newarr, array_element_type);
+                               ig.Emit (OpCodes.Newarr, TypeManager.TypeToReflectionType (array_element_type));
                        else {
                                ig.Emit (OpCodes.Newobj, GetArrayMethod (arguments.Count));
                        }
@@ -6349,7 +6336,7 @@ namespace Mono.CSharp {
                        // 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) &&
-                               TypeManager.IsPrimitiveType (array_element_type)) {
+                               (TypeManager.IsPrimitiveType (array_element_type) || TypeManager.IsEnumType (array_element_type))) {
                                EmitStaticInitializers (ec);
 
                                if (!only_constant_initializers)
@@ -6370,11 +6357,13 @@ namespace Mono.CSharp {
                        }
 
                        if (array_data == null) {
-                               Constant c = (Constant) arguments [0];
-                               if (c.IsDefaultValue) {
+                               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;
                                }
+
                                // ec.Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
                                return base.GetAttributableValue (ec, null, out value);
                        }
@@ -7214,12 +7203,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       int size = GetTypeSize (type_queried);
-
-                       if (size == 0)
-                               ec.ig.Emit (OpCodes.Sizeof, type_queried);
-                       else
-                               IntConstant.EmitInt (ec.ig, size);
+                       ec.ig.Emit (OpCodes.Sizeof, type_queried);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -7594,7 +7578,7 @@ namespace Mono.CSharp {
                                if (expr_type == null)
                                        return;
 
-                               Namespace.Error_TypeArgumentsCannotBeUsed (expr_type, loc);
+                               expr_type.Error_TypeArgumentsCannotBeUsed (rc.Compiler.Report, loc);
                                return;
                        }
 
@@ -7893,7 +7877,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements array access 
        /// </summary>
-       public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
+       public class ArrayAccess : Expression, IDynamicAssign, IMemoryLocation {
                //
                // Points to our "data" repository
                //
@@ -8003,10 +7987,8 @@ namespace Mono.CSharp {
                        } else if (TypeManager.IsStruct (type)){
                                ig.Emit (OpCodes.Ldelema, type);
                                ig.Emit (OpCodes.Ldobj, type);
-#if GMCS_SOURCE
                        } else if (type.IsGenericParameter) {
                                ig.Emit (OpCodes.Ldelem, type);
-#endif
                        } else if (type.IsPointer)
                                ig.Emit (OpCodes.Ldelem_I);
                        else
@@ -8050,12 +8032,9 @@ namespace Mono.CSharp {
                                has_type_arg = true;
                                is_stobj = true;
                                return OpCodes.Stobj;
-#if GMCS_SOURCE
                        } else if (t.IsGenericParameter) {
                                has_type_arg = true;
                                return OpCodes.Stelem;
-#endif
-
                        } else if (t.IsPointer)
                                return OpCodes.Stelem_I;
                        else
@@ -8248,6 +8227,22 @@ namespace Mono.CSharp {
                        }
                }
 
+#if NET_4_0
+               public SLE.Expression MakeAssignExpression (BuilderContext ctx)
+               {
+                       return SLE.Expression.ArrayAccess (
+                               ea.Expr.MakeExpression (ctx),
+                               Arguments.MakeExpression (ea.Arguments, ctx));
+               }
+
+               public override SLE.Expression MakeExpression (BuilderContext ctx)
+               {
+                       return SLE.Expression.ArrayIndex (
+                               ea.Expr.MakeExpression (ctx),
+                               Arguments.MakeExpression (ea.Arguments, ctx));
+               }
+#endif
+
                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
                        type = storey.MutateType (type);
@@ -8258,7 +8253,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Expressions that represent an indexer call.
        /// </summary>
-       public class IndexerAccess : Expression, IAssignMethod
+       public class IndexerAccess : Expression, IDynamicAssign
        {
                class IndexerMethodGroupExpr : MethodGroupExpr
                {
@@ -8539,6 +8534,11 @@ namespace Mono.CSharp {
                        eclass = ExprClass.IndexerAccess;
                        return this;
                }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
                
                public void Emit (EmitContext ec, bool leave_copy)
                {
@@ -8598,15 +8598,28 @@ namespace Mono.CSharp {
                        }
                }
                
-               public override void Emit (EmitContext ec)
+               public override string GetSignatureForError ()
                {
-                       Emit (ec, false);
+                       return TypeManager.CSharpSignature (get != null ? get : set, false);
                }
 
-               public override string GetSignatureForError ()
+#if NET_4_0
+               public SLE.Expression MakeAssignExpression (BuilderContext ctx)
                {
-                       return TypeManager.CSharpSignature (get != null ? get : set, false);
+                       var value = new[] { set_expr.MakeExpression (ctx) };
+                       var args = Arguments.MakeExpression (arguments, ctx).Concat (value);
+
+                       return SLE.Expression.Block (
+                                       SLE.Expression.Call (instance_expr.MakeExpression (ctx), set, args),
+                                       value [0]);
+               }
+
+               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)
                {
@@ -8719,7 +8732,19 @@ namespace Mono.CSharp {
                        else
                                left = ec.GetThis (loc);
 
-                       MemberExpr me = (MemberExpr) member_lookup;
+                       MemberExpr me = member_lookup as MemberExpr;
+                       if (me == null){
+                               if (member_lookup is TypeExpression){
+                                       ec.Report.Error (582, loc, "{0}: Can not reference a type through an expression, try `{1}' instead",
+                                                        Identifier, member_lookup.GetSignatureForError ());
+                               } else {
+                                       ec.Report.Error (582, loc, "{0}: Can not reference a {1} through an expression", 
+                                                        Identifier, member_lookup.ExprClassName);
+                               }
+                               
+                               return null;
+                       }
+                       
                        me = me.ResolveMemberAccess (ec, left, loc, null);
                        if (me == null)
                                return null;
@@ -9087,34 +9112,39 @@ namespace Mono.CSharp {
        public class ArrayIndexCast : TypeCast
        {
                public ArrayIndexCast (Expression expr)
-                       : base (expr, expr.Type)
+                       : base (expr, TypeManager.int32_type)
                {
+                       if (expr.Type == TypeManager.int32_type)
+                               throw new ArgumentException ("unnecessary array index conversion");
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
-                       Arguments args = new Arguments (2);
-                       args.Add (new Argument (child.CreateExpressionTree (ec)));
-                       args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc)));
-                       return CreateExpressionFactoryCall (ec, "ConvertChecked", args);
+                       using (ec.Set (ResolveContext.Options.CheckedScope)) {
+                               return base.CreateExpressionTree (ec);
+                       }
                }
 
                public override void Emit (EmitContext ec)
                {
                        child.Emit (ec);
-                               
-                       if (type == TypeManager.int32_type)
-                               return;
 
-                       if (type == TypeManager.uint32_type)
+                       var expr_type = child.Type;
+
+                       if (expr_type == TypeManager.uint32_type)
                                ec.ig.Emit (OpCodes.Conv_U);
-                       else if (type == TypeManager.int64_type)
+                       else if (expr_type == TypeManager.int64_type)
                                ec.ig.Emit (OpCodes.Conv_Ovf_I);
-                       else if (type == TypeManager.uint64_type)
+                       else if (expr_type == TypeManager.uint64_type)
                                ec.ig.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);
+               }
        }
 
        //
@@ -9152,7 +9182,6 @@ namespace Mono.CSharp {
                        Constant c = count as Constant;
                        if (c != null && c.IsNegative) {
                                ec.Report.Error (247, loc, "Cannot use a negative size with stackalloc");
-                               return null;
                        }
 
                        if (ec.HasAny (ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) {
@@ -9690,7 +9719,7 @@ namespace Mono.CSharp {
 
                AnonymousTypeClass CreateAnonymousType (ResolveContext ec, ArrayList parameters)
                {
-                       AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters);
+                       AnonymousTypeClass type = parent.Module.Compiled.GetAnonymousType (parameters);
                        if (type != null)
                                return type;
 
@@ -9704,7 +9733,7 @@ namespace Mono.CSharp {
                        if (ec.Report.Errors == 0)
                                type.CloseType ();
 
-                       parent.Module.AddAnonymousType (type);
+                       parent.Module.Compiled.AddAnonymousType (type);
                        return type;
                }
 
@@ -9761,36 +9790,24 @@ namespace Mono.CSharp {
                }
        }
 
-       public class AnonymousTypeParameter : Expression
+       public class AnonymousTypeParameter : ShimExpression
        {
                public readonly string Name;
-               Expression initializer;
 
                public AnonymousTypeParameter (Expression initializer, string name, Location loc)
+                       : base (initializer)
                {
                        this.Name = name;
                        this.loc = loc;
-                       this.initializer = initializer;
                }
                
                public AnonymousTypeParameter (Parameter parameter)
+                       : base (new SimpleName (parameter.Name, parameter.Location))
                {
                        this.Name = parameter.Name;
                        this.loc = parameter.Location;
-                       this.initializer = new SimpleName (Name, loc);
                }               
 
-               protected override void CloneTo (CloneContext clonectx, Expression target)
-               {
-                       AnonymousTypeParameter t = (AnonymousTypeParameter) target;
-                       t.initializer = initializer.Clone (clonectx);
-               }
-
-               public override Expression CreateExpressionTree (ResolveContext ec)
-               {
-                       throw new NotSupportedException ("ET");
-               }
-
                public override bool Equals (object o)
                {
                        AnonymousTypeParameter other = o as AnonymousTypeParameter;
@@ -9804,7 +9821,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (ResolveContext ec)
                {
-                       Expression e = initializer.Resolve (ec);
+                       Expression e = expr.Resolve (ec);
                        if (e == null)
                                return null;
 
@@ -9828,10 +9845,5 @@ namespace Mono.CSharp {
                        ec.Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
                                Name, initializer);
                }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new InternalErrorException ("Should not be reached");
-               }
        }
 }