2009-10-23 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / expression.cs
index ef8c431c18da45c2ad0446b4423b29b59c9b0dc8..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
 
@@ -726,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;
 
@@ -922,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)
                {
@@ -939,85 +938,6 @@ namespace Mono.CSharp {
                        expr = e;
                }
 
-               string OperName ()
-               {
-                       return IsDecrement ?
-                               Operator.GetName (Operator.OpType.Decrement) :
-                               Operator.GetName (Operator.OpType.Increment);
-               }
-
-               /// <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 (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;
-
-                               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 () + "' 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;
                        }
@@ -1150,27 +1007,25 @@ namespace Mono.CSharp {
                        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;
+               }
+
 #if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       if (method != null)
-                               return method.MakeExpression (ctx);
-
-                       bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
-                       var one = SLE.Expression.Constant (1);
-                       var left = expr.MakeExpression (ctx);
-
-                       SLE.Expression binary;
-                       if (IsDecrement) {
-                               binary = is_checked ? SLE.Expression.SubtractChecked (left, one) : SLE.Expression.Subtract (left, one);
-                       } else {
-                               binary = is_checked ? SLE.Expression.AddChecked (left, one) : SLE.Expression.Add (left, one);
-                       }
-
                        var target = ((RuntimeValueExpression) expr).MetaObject.Expression;
-                       binary = SLE.Expression.Convert (binary, target.Type);
-
-                       return SLE.Expression.Assign (target, binary);
+                       var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type);
+                       return SLE.Expression.Assign (target, source);
                }
 #endif
 
@@ -1180,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>
@@ -1445,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)
@@ -1585,7 +1512,7 @@ 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);
@@ -1603,17 +1530,25 @@ namespace Mono.CSharp {
 
        public class ImplicitCast : ShimExpression
        {
-               public ImplicitCast (Expression expr, Type target)
+               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)
+                       if (expr == null)
+                               return null;
+
+                       if (arrayAccess)
+                               expr = ConvertExpressionToArrayIndex (ec, expr);
+                       else
                                expr = Convert.ImplicitConversionRequired (ec, expr, type, loc);
 
                        return expr;
@@ -3090,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)) {
@@ -3100,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)) {
@@ -3203,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;
@@ -3668,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)
@@ -4107,27 +4048,19 @@ namespace Mono.CSharp {
        // A boolean-expression is an expression that yields a result
        // of type bool
        //
-       public class BooleanExpression : Expression
+       public class BooleanExpression : ShimExpression
        {
-               Expression expr;
-
                public BooleanExpression (Expression expr)
+                       : base (expr)
                {
-                       this.expr = expr;
                        this.loc = expr.Location;
                }
 
-               protected override void CloneTo (CloneContext clonectx, Expression t)
-               {
-                       BooleanExpression target = (BooleanExpression) t;
-                       target.expr = expr.Clone (clonectx);
-               }
-
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        // TODO: We should emit IsTrue (v4) instead of direct user operator
                        // call but that would break csc compatibility
-                       throw new NotSupportedException ();
+                       return base.CreateExpressionTree (ec);
                }
 
                public override Expression DoResolve (ResolveContext ec)
@@ -4142,7 +4075,7 @@ namespace Mono.CSharp {
 
                        Assign ass = expr as Assign;
                        if (ass != null && ass.Source is Constant) {
-                               ec.Report.Warning (665, 3, expr.Location,
+                               ec.Report.Warning (665, 3, loc,
                                        "Assignment in conditional expression is always constant. Did you mean to use `==' instead ?");
                        }
 
@@ -4171,11 +4104,6 @@ namespace Mono.CSharp {
 
                        return converted;
                }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new InternalErrorException ("Should not be reached");
-               }
        }
        
        /// <summary>
@@ -4258,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;
                                }
                        }                       
@@ -4361,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);
@@ -5048,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.
                        //
@@ -5117,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 ();
@@ -5248,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) {
@@ -5298,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);
-                       }
-
-                       //
-                       // 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;
-                       }                       
+                       var instance_expr = instance == null ? null : instance.MakeExpression (ctx);
+                       SLE.Expression expr = SLE.Expression.Call (instance_expr, mi,
+                               Arguments.MakeExpression (args, ctx));
 
-                       //
-                       // 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 
@@ -5643,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 });
@@ -5681,9 +5518,6 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Call, ci);
                        ig.MarkLabel (label_end);
                        return true;
-#else
-                       throw new InternalErrorException ();
-#endif
                }
 
                //
@@ -5878,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;
 
@@ -6012,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);
 
@@ -6043,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);
@@ -6076,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)
@@ -6190,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;
@@ -6213,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;
                                                
@@ -6222,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;
 
@@ -6231,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);
                                                        
@@ -6240,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);
 
@@ -6251,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;
                                        
@@ -6281,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;
                                        
@@ -6290,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;
@@ -6324,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);
@@ -6487,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)
@@ -7354,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)
@@ -7734,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;
                        }
 
@@ -8033,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
                //
@@ -8143,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
@@ -8190,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
@@ -8388,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);
@@ -8398,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
                {
@@ -8679,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)
                {
@@ -8738,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)
                {
@@ -9239,29 +9112,30 @@ namespace Mono.CSharp {
        public class ArrayIndexCast : TypeCast
        {
                public ArrayIndexCast (Expression expr)
-                       : base (expr, expr.Type)
+                       : base (expr, TypeManager.int32_type)
                {
-                       if (type == TypeManager.int32_type)
-                               throw new ArgumentException ("unnecessary conversion");
+                       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.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);
@@ -9308,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)) {
@@ -9846,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;
 
@@ -9860,7 +9733,7 @@ namespace Mono.CSharp {
                        if (ec.Report.Errors == 0)
                                type.CloseType ();
 
-                       parent.Module.AddAnonymousType (type);
+                       parent.Module.Compiled.AddAnonymousType (type);
                        return type;
                }