2004-04-05 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index f384ab46612781e8d1492713b5025535b9ef7f43..06fff718a381f2fa058c1a9ee8692aae8fe60e83 100755 (executable)
@@ -4,8 +4,8 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //
-// (C) 2001 Ximian, Inc.
-//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 #define USE_OLD
 
@@ -81,6 +81,28 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Pop);
                }
        }
+
+       public class ParenthesizedExpression : Expression
+       {
+               public Expression Expr;
+
+               public ParenthesizedExpression (Expression expr, Location loc)
+               {
+                       this.Expr = expr;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expr = Expr.Resolve (ec);
+                       return Expr;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should not happen");
+               }
+       }
        
        /// <summary>
        ///   Unary expressions.  
@@ -232,16 +254,16 @@ namespace Mono.CSharp {
 
                                        result = null;
                                        if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.int32_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.uint32_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.int64_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.uint64_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        }
 
@@ -400,6 +422,23 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               IVariable variable = Expr as IVariable;
+                               if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+                                       Error (212, "You can only take the address of an unfixed expression inside " +
+                                              "of a fixed statement initializer");
+                                       return null;
+                               }
+                               
+                               if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+                                       Error (213, "You can not fix an already fixed expression");
+                                       return null;
+                               }
+
+                               // According to the specs, a variable is considered definitely assigned if you take
+                               // its address.
+                               if ((variable != null) && (variable.VariableInfo != null))
+                                       variable.VariableInfo.SetAssigned (ec);
+
                                type = TypeManager.GetPointerType (Expr.Type);
                                return this;
 
@@ -531,15 +570,23 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       Type expr_type = Expr.Type;
                        
                        switch (Oper) {
                        case Operator.UnaryPlus:
                                throw new Exception ("This should be caught by Resolve");
                                
                        case Operator.UnaryNegation:
-                               Expr.Emit (ec);
-                               ig.Emit (OpCodes.Neg);
+                               if (ec.CheckState) {
+                                       ig.Emit (OpCodes.Ldc_I4_0);
+                                       if (type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_U8);
+                                       Expr.Emit (ec);
+                                       ig.Emit (OpCodes.Sub_Ovf);
+                               } else {
+                                       Expr.Emit (ec);
+                                       ig.Emit (OpCodes.Neg);
+                               }
+                               
                                break;
                                
                        case Operator.LogicalNot:
@@ -563,16 +610,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   This will emit the child expression for `ec' avoiding the logical
-               ///   not.  The parent will take care of changing brfalse/brtrue
-               /// </summary>
-               public void EmitLogicalNot (EmitContext ec)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (Oper != Operator.LogicalNot)
-                               throw new Exception ("EmitLogicalNot can only be called with !expr");
-
-                       Expr.Emit (ec);
+                       if (Oper == Operator.LogicalNot)
+                               Expr.EmitBranchable (ec, target, !onTrue);
+                       else
+                               base.EmitBranchable (ec, target, onTrue);
                }
 
                public override string ToString ()
@@ -595,7 +638,7 @@ namespace Mono.CSharp {
                public Indirection (Expression expr, Location l)
                {
                        this.expr = expr;
-                       this.type = TypeManager.TypeToCoreType (expr.Type.GetElementType ());
+                       this.type = TypeManager.GetElementType (expr.Type);
                        eclass = ExprClass.Variable;
                        loc = l;
                }
@@ -609,14 +652,14 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
 
                        if (temporary != null){
-                               if (have_temporary){
+                               if (have_temporary) {
                                        temporary.Emit (ec);
-                                       return;
+                               } else {
+                                       expr.Emit (ec);
+                                       ec.ig.Emit (OpCodes.Dup);
+                                       temporary.Store (ec);
+                                       have_temporary = true;
                                }
-                               expr.Emit (ec);
-                               ec.ig.Emit (OpCodes.Dup);
-                               temporary.Store (ec);
-                               have_temporary = true;
                        } else
                                expr.Emit (ec);
                        
@@ -666,7 +709,7 @@ namespace Mono.CSharp {
 
                public new void CacheTemporaries (EmitContext ec)
                {
-                       temporary = new LocalTemporary (ec, type);
+                       temporary = new LocalTemporary (ec, expr.Type);
                }
 
                public override string ToString ()
@@ -792,6 +835,9 @@ namespace Mono.CSharp {
                        //
                        type = expr_type;
                        if (expr.eclass == ExprClass.Variable){
+                               LocalVariableReference var = expr as LocalVariableReference;
+                               if ((var != null) && var.IsReadOnly)
+                                       Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
                                if (IsIncrementableNumber (expr_type) ||
                                    expr_type == TypeManager.decimal_type){
                                        return this;
@@ -836,7 +882,7 @@ namespace Mono.CSharp {
 
                static int PtrTypeSize (Type t)
                {
-                       return GetTypeSize (t.GetElementType ());
+                       return GetTypeSize (TypeManager.GetElementType (t));
                }
 
                //
@@ -930,6 +976,13 @@ namespace Mono.CSharp {
 
                        ia.CacheTemporaries (ec);
 
+                       //
+                       // NOTE: We should probably handle three cases:
+                       //
+                       //     * method invocation required.
+                       //     * direct stack manipulation possible
+                       //     * the object requires an "instance" field
+                       //
                        if (temp_storage == null){
                                //
                                // Temporary improvement: if we are dealing with something that does
@@ -938,9 +991,8 @@ namespace Mono.CSharp {
                                // For now: only localvariables when not remapped
                                //
 
-                               if (method == null && 
-                                   (expr is LocalVariableReference && ec.RemapToProxy == false) ||
-                                   (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
+                               if (method == null &&
+                                   ((expr is LocalVariableReference) ||(expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic))){
                                        if (empty_expr == null)
                                                empty_expr = new EmptyExpression ();
                                        
@@ -1006,6 +1058,8 @@ namespace Mono.CSharp {
                                ia.EmitAssign (ec, temp_storage);
                                break;
                        }
+
+                       temp_storage.Release (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -1055,6 +1109,8 @@ namespace Mono.CSharp {
                                return null;
 
                        expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
                        
                        return this;
                }
@@ -1105,6 +1161,35 @@ namespace Mono.CSharp {
                        }
                        throw new Exception ("never reached");
                }
+               
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       switch (action){
+                       case Action.AlwaysFalse:
+                               if (! onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.AlwaysTrue:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.LeaveOnStack:
+                               // the `e != null' rule.
+                               expr.Emit (ec);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       case Action.Probe:
+                               expr.Emit (ec);
+                               ig.Emit (OpCodes.Isinst, probe_type);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       }
+                       throw new Exception ("never reached");
+               }
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -1204,7 +1289,7 @@ namespace Mono.CSharp {
 
                        if (TypeManager.IsValueType (probe_type)){
                                Report.Error (77, loc, "The as operator should be used with a reference type only (" +
-                                             TypeManager.CSharpName (probe_type) + " is a value type");
+                                             TypeManager.CSharpName (probe_type) + " is a value type)");
                                return null;
                        
                        }
@@ -1311,7 +1396,7 @@ namespace Mono.CSharp {
                        Expression real_expr = expr;
                        if (real_expr is EnumConstant)
                                real_expr = ((EnumConstant) real_expr).Child;
-                               
+
                        if (real_expr is ByteConstant){
                                byte v = ((ByteConstant) real_expr).Value;
        
@@ -1682,9 +1767,9 @@ namespace Mono.CSharp {
                        if (real_expr is DoubleConstant){
                                double v = ((DoubleConstant) real_expr).Value;
        
-                               if (target_type == TypeManager.byte_type)
+                               if (target_type == TypeManager.byte_type){
                                        return new ByteConstant ((byte) v);
-                               if (target_type == TypeManager.sbyte_type)
+                               if (target_type == TypeManager.sbyte_type)
                                        return new SByteConstant ((sbyte) v);
                                if (target_type == TypeManager.short_type)
                                        return new ShortConstant ((short) v);
@@ -1754,8 +1839,6 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       int errors = Report.Errors;
-
                        type = ec.DeclSpace.ResolveType (target_type, false, Location);
                        
                        if (type == null)
@@ -1804,15 +1887,6 @@ namespace Mono.CSharp {
                Operator oper;
                Expression left, right;
 
-               //
-               // After resolution, method might contain the operator overload
-               // method.
-               //
-               protected MethodBase method;
-               ArrayList  Arguments;
-
-               bool DelegateOperation;
-
                // This must be kept in sync with Operator!!!
                public static readonly string [] oper_names;
                
@@ -2062,7 +2136,7 @@ namespace Mono.CSharp {
                                //
                                // If either operand is of type uint, and the other
                                // operand is of type sbyte, short or int, othe operands are
-                               // converted to type long.
+                               // converted to type long (unless we have an int constant).
                                //
                                Type other = null;
                                
@@ -2071,24 +2145,24 @@ namespace Mono.CSharp {
                                                IntConstant ic = (IntConstant) right;
                                                int val = ic.Value;
                                                
-                                               if (val >= 0)
+                                               if (val >= 0){
                                                        right = new UIntConstant ((uint) val);
-
-                                               type = l;
-                                               return true;
+                                                       type = l;
+                                                       
+                                                       return true;
+                                               }
                                        }
                                        other = r;
-                               } 
-                               else if (r == TypeManager.uint32_type){
+                               } else if (r == TypeManager.uint32_type){
                                        if (left is IntConstant){
                                                IntConstant ic = (IntConstant) left;
                                                int val = ic.Value;
                                                
-                                               if (val >= 0)
+                                               if (val >= 0){
                                                        left = new UIntConstant ((uint) val);
-
-                                               type = r;
-                                               return true;
+                                                       type = r;
+                                                       return true;
+                                               }
                                        }
                                        
                                        other = l;
@@ -2139,12 +2213,6 @@ namespace Mono.CSharp {
                        Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
                }
 
-               static bool is_32_or_64 (Type t)
-               {
-                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
-                               t == TypeManager.int64_type || t == TypeManager.uint64_type);
-               }
-
                static bool is_unsigned (Type t)
                {
                        return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
@@ -2159,12 +2227,32 @@ namespace Mono.CSharp {
                        else
                                return false;
                }
+
+               Expression Make32or64 (EmitContext ec, Expression e)
+               {
+                       Type t= e.Type;
+                       
+                       if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+                           t == TypeManager.int64_type || t == TypeManager.uint64_type)
+                               return e;
+                       Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);
+                       if (ee != null)
+                               return ee;
+                       return null;
+               }
                                        
                Expression CheckShiftArguments (EmitContext ec)
                {
                        Expression e;
-                       Type l = left.Type;
-                       Type r = right.Type;
 
                        e = ForceConversion (ec, right, TypeManager.int32_type);
                        if (e == null){
@@ -2180,6 +2268,14 @@ namespace Mono.CSharp {
                                left = e;
                                type = e.Type;
 
+                               if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
+                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
+                                       right = right.DoResolve (ec);
+                               } else {
+                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
+                                       right = right.DoResolve (ec);
+                               }
+
                                return this;
                        }
                        Error_OperatorCannotBeApplied ();
@@ -2227,26 +2323,21 @@ namespace Mono.CSharp {
                                        union = (MethodGroupExpr) left_expr;
                                
                                if (union != null) {
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       ArrayList args = new ArrayList (2);
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
                                        
-                                       method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
+                                       MethodBase method = Invocation.OverloadResolve (ec, union, args, Location.Null);
                                        if (method != null) {
                                                MethodInfo mi = (MethodInfo) method;
                                                
-                                               type = mi.ReturnType;
-                                               return this;
+                                               return new BinaryMethod (mi.ReturnType, method, args);
                                        } else {
                                                overload_failed = true;
                                        }
                                }
                        }
                        
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
                        //
                        // Step 0: String concatenation (because overloading will get this wrong)
                        //
@@ -2255,94 +2346,25 @@ namespace Mono.CSharp {
                                // If any of the arguments is a string, cast to string
                                //
                                
-                               if (l == TypeManager.string_type){
-                                       
-                                       if (r == TypeManager.void_type) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
-                                       
-                                       if (r == TypeManager.string_type){
-                                               if (left is Constant && right is Constant){
-                                                       StringConstant ls = (StringConstant) left;
-                                                       StringConstant rs = (StringConstant) right;
-                                                       
-                                                       return new StringConstant (
-                                                               ls.Value + rs.Value);
-                                               }
-
-                                               if (left is Binary){
-                                                       Binary b = (Binary) left;
-
-                                                       //
-                                                       // Call String.Concat (string, string, string) or
-                                                       // String.Concat (string, string, string, string)
-                                                       // if possible.
-                                                       //
-                                                       if (b.oper == Operator.Addition &&
-                                                           (b.method == TypeManager.string_concat_string_string_string ||
-                                                            b.method == TypeManager.string_concat_string_string_string_string)){
-                                                               ArrayList bargs = b.Arguments;
-                                                               int count = bargs.Count;
-                                                               
-                                                               if (count == 2){
-                                                                       Arguments = bargs;
-                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                                                       type = TypeManager.string_type;
-                                                                       method = TypeManager.string_concat_string_string_string;
-                                                                       
-                                                                       return this;
-                                                               } else if (count == 3){
-                                                                       Arguments = bargs;
-                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                                                       type = TypeManager.string_type;
-                                                                       method = TypeManager.string_concat_string_string_string_string;                                                                 
-                                                                       return this;
-                                                               }
-                                                       }
-                                               }
-
-                                               // string + string
-                                               method = TypeManager.string_concat_string_string;
-                                       } else {
-                                               // string + object
-                                               method = TypeManager.string_concat_object_object;
-                                               right = Convert.ImplicitConversion (
-                                                       ec, right, TypeManager.object_type, loc);
-                                               if (right == null){
-                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                                       return null;
-                                               }
-                                       }
-                                       type = TypeManager.string_type;
-
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-
-                                       return this;
-                                       
-                               } else if (r == TypeManager.string_type){
-                                       // object + string
+                               // Simple constant folding
+                               if (left is StringConstant && right is StringConstant)
+                                       return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
+                               
+                               if (l == TypeManager.string_type || r == TypeManager.string_type) {
 
-                                       if (l == TypeManager.void_type) {
+                                       if (r == TypeManager.void_type || l == TypeManager.void_type) {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
                                        
-                                       method = TypeManager.string_concat_object_object;
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
-                                       if (left == null){
-                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                               return null;
+                                       // try to fold it in on the left
+                                       if (left is StringConcat) {
+                                               ((StringConcat) left).Append (ec, right);
+                                               return left.Resolve (ec);
                                        }
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-
-                                       type = TypeManager.string_type;
-
-                                       return this;
+                                       
+                                       // Otherwise, start a new concat expression
+                                       return new StringConcat (ec, loc, left, right).Resolve (ec);
                                }
 
                                //
@@ -2424,28 +2446,37 @@ namespace Mono.CSharp {
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
-                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
-                                   r.IsSubclassOf (TypeManager.delegate_type)) {
-                                       
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                       
-                                       if (oper == Operator.Addition)
-                                               method = TypeManager.delegate_combine_delegate_delegate;
-                                       else
-                                               method = TypeManager.delegate_remove_delegate_delegate;
-
-                                       if (l != r) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
+                               if (l.IsSubclassOf (TypeManager.delegate_type)){
+                                       if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
+                                               Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+                                               if (tmp == null)
+                                                       return null;
+                                               right = tmp;
+                                               r = right.Type;
+                                       }
+                               
+                                       if (r.IsSubclassOf (TypeManager.delegate_type)){
+                                               MethodInfo method;
+                                               ArrayList args = new ArrayList (2);
+                                               
+                                               args = new ArrayList (2);
+                                               args.Add (new Argument (left, Argument.AType.Expression));
+                                               args.Add (new Argument (right, Argument.AType.Expression));
+                                               
+                                               if (oper == Operator.Addition)
+                                                       method = TypeManager.delegate_combine_delegate_delegate;
+                                               else
+                                                       method = TypeManager.delegate_remove_delegate_delegate;
+                                               
+                                               if (l != r) {
+                                                       Error_OperatorCannotBeApplied ();
+                                                       return null;
+                                               }
+                                               
+                                               return new BinaryDelegate (l, method, args);
                                        }
-
-                                       DelegateOperation = true;
-                                       type = l;
-                                       return this;
                                }
-
+                               
                                //
                                // Pointer arithmetic:
                                //
@@ -2472,12 +2503,16 @@ namespace Mono.CSharp {
                                                        return new PointerArithmetic (
                                                                false, left, right, TypeManager.int64_type,
                                                                loc);
-                                       } else if (is_32_or_64 (r))
-                                               return new PointerArithmetic (
-                                                       oper == Operator.Addition, left, right, l, loc);
-                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
-                                       return new PointerArithmetic (
-                                               true, right, left, r, loc);
+                                       } else {
+                                               Expression t = Make32or64 (ec, right);
+                                               if (t != null)
+                                                       return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc);
+                                       }
+                               } else if (r.IsPointer && oper == Operator.Addition){
+                                       Expression t = Make32or64 (ec, left);
+                                       if (t != null)
+                                               return new PointerArithmetic (true, right, t, r, loc);
+                               }
                        }
                        
                        //
@@ -2489,13 +2524,15 @@ namespace Mono.CSharp {
                                Expression temp;
 
                                // U operator - (E e, E f)
-                               if (lie && rie && oper == Operator.Subtraction){
-                                       if (l == r){
-                                               type = TypeManager.EnumToUnderlying (l);
-                                               return this;
-                                       } 
-                                       Error_OperatorCannotBeApplied ();
-                                       return null;
+                               if (lie && rie){
+                                       if (oper == Operator.Subtraction){
+                                               if (l == r){
+                                                       type = TypeManager.EnumToUnderlying (l);
+                                                       return this;
+                                               }
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
                                }
                                        
                                //
@@ -2506,9 +2543,18 @@ namespace Mono.CSharp {
                                        Type enum_type = lie ? l : r;
                                        Type other_type = lie ? r : l;
                                        Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
-;
                                        
                                        if (underlying_type != other_type){
+                                               temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
+                                               if (temp != null){
+                                                       if (lie)
+                                                               right = temp;
+                                                       else
+                                                               left = temp;
+                                                       type = enum_type;
+                                                       return this;
+                                               }
+                                                       
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
@@ -2561,13 +2607,19 @@ namespace Mono.CSharp {
                                return CheckShiftArguments (ec);
 
                        if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
-                               if (l != TypeManager.bool_type || r != TypeManager.bool_type){
+                               if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (l != r) {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
                                }
 
-                               type = TypeManager.bool_type;
-                               return this;
+                               Expression e = new ConditionalLogicalOperator (
+                                       oper == Operator.LogicalAnd, left, right, l, loc);
+                               return e.Resolve (ec);
                        } 
 
                        //
@@ -2626,9 +2678,12 @@ namespace Mono.CSharp {
                                if (l == r){
                                        if (!((l == TypeManager.int32_type) ||
                                              (l == TypeManager.uint32_type) ||
+                                             (l == TypeManager.short_type) ||
+                                             (l == TypeManager.ushort_type) ||
                                              (l == TypeManager.int64_type) ||
-                                             (l == TypeManager.uint64_type)))
+                                             (l == TypeManager.uint64_type))){
                                                type = l;
+                                       }
                                } else {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
@@ -2649,7 +2704,18 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       left = left.Resolve (ec);
+                       if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
+                               left = ((ParenthesizedExpression) left).Expr;
+                               left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
+                               if (left == null)
+                                       return null;
+
+                               if (left.eclass == ExprClass.Type) {
+                                       Error (75, "Casting a negative value needs to have the value in parentheses.");
+                                       return null;
+                               }
+                       } else
+                               left = left.Resolve (ec);
                        right = right.Resolve (ec);
 
                        if (left == null || right == null)
@@ -2678,11 +2744,8 @@ namespace Mono.CSharp {
                ///   The expression's code is generated, and we will generate a branch to `target'
                ///   if the resulting expression value is equal to isTrue
                /// </remarks>
-               public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (method != null)
-                               return false;
-
                        ILGenerator ig = ec.ig;
 
                        //
@@ -2691,136 +2754,78 @@ namespace Mono.CSharp {
                        // but on top of that we want for == and != to use a special path
                        // if we are comparing against null
                        //
-                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                       if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
                                bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
-
-                               if (left is NullLiteral){
-                                       right.Emit (ec);
-                                       if (my_on_true)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (right is NullLiteral){
+                               
+                               //
+                               // put the constant on the rhs, for simplicity
+                               //
+                               if (left is Constant) {
+                                       Expression swap = right;
+                                       right = left;
+                                       left = swap;
+                               }
+                               
+                               if (((Constant) right).IsZeroInteger) {
                                        left.Emit (ec);
                                        if (my_on_true)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (left is BoolConstant){
-                                       right.Emit (ec);
-                                       if (my_on_true != ((BoolConstant) left).Value)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (right is BoolConstant){
+                                       
+                                       return;
+                               } else if (right is BoolConstant) {
                                        left.Emit (ec);
                                        if (my_on_true != ((BoolConstant) right).Value)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
+                                       
+                                       return;
                                }
 
-                       } else if (oper == Operator.LogicalAnd){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
+                       } else if (oper == Operator.LogicalAnd) {
 
-                                       if (onTrue){
-                                               Label tests_end = ig.DefineLabel ();
-                                               
-                                               if (left_binary.EmitBranchable (ec, tests_end, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, true)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
-                                                       ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
-                                       } else {
-                                               if (left_binary.EmitBranchable (ec, target, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-                                                               
-                                                               if (right_binary.EmitBranchable (ec, target, false))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       if (onTrue)
-                                                               ig.Emit (OpCodes.Brtrue, target);
-                                                       else
-                                                               ig.Emit (OpCodes.Brfalse, target);
-                                                       return true;
-                                               }
-                                       }
-                                       //
-                                       // Give up, and let the regular Emit work, but we could
-                                       // also optimize the left-non-Branchable, but-right-Branchable
-                                       //
+                               if (onTrue) {
+                                       Label tests_end = ig.DefineLabel ();
+                                       
+                                       left.EmitBranchable (ec, tests_end, false);
+                                       right.EmitBranchable (ec, target, true);
+                                       ig.MarkLabel (tests_end);                                       
+                               } else {
+                                       left.EmitBranchable (ec, target, false);
+                                       right.EmitBranchable (ec, target, false);
                                }
-                               return false;
+                               
+                               return;
+                               
                        } else if (oper == Operator.LogicalOr){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (onTrue){
-                                               if (left_binary.EmitBranchable (ec, target, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-                                                               
-                                                               if (right_binary.EmitBranchable (ec, target, true))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
-                                                       return true;
-                                               }
-                                               
-                                               //
-                                               // Give up, and let the regular Emit work, but we could
-                                               // also optimize the left-non-Branchable, but-right-Branchable
-                                               //
-                                       } else {
-                                               Label tests_end = ig.DefineLabel ();
-                                               
-                                               if (left_binary.EmitBranchable (ec, tests_end, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, false)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brfalse, target);
-                                                       ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
-                                       }
+                               if (onTrue) {
+                                       left.EmitBranchable (ec, target, true);
+                                       right.EmitBranchable (ec, target, true);
+                                       
+                               } else {
+                                       Label tests_end = ig.DefineLabel ();
+                                       left.EmitBranchable (ec, tests_end, true);
+                                       right.EmitBranchable (ec, target, false);
+                                       ig.MarkLabel (tests_end);
                                }
                                
-                               return false;
-                       } else if (!(oper == Operator.LessThan ||
-                               oper == Operator.GreaterThan ||
-                               oper == Operator.LessThanOrEqual ||
-                               oper == Operator.GreaterThanOrEqual))
-                               return false;
-                       
-                       left.Emit (ec);
+                               return;
+                               
+                       } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
+                                    oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
+                                    oper == Operator.Equality        || oper == Operator.Inequality)) {
+                               base.EmitBranchable (ec, target, onTrue);
+                               return;
+                       }
+                       
+                       left.Emit (ec);
                        right.Emit (ec);
 
                        Type t = left.Type;
-                       bool isUnsigned = is_unsigned (t);
-
+                       bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
+                       
                        switch (oper){
                        case Operator.Equality:
                                if (onTrue)
@@ -2863,9 +2868,6 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.LessThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
-
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Ble_Un, target);
@@ -2880,8 +2882,6 @@ namespace Mono.CSharp {
 
 
                        case Operator.GreaterThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Bge_Un, target);
@@ -2893,89 +2893,42 @@ namespace Mono.CSharp {
                                        else
                                                ig.Emit (OpCodes.Blt, target);
                                break;
-
                        default:
-                               return false;
+                               Console.WriteLine (oper);
+                               throw new Exception ("what is THAT");
                        }
-                       
-                       return true;
                }
                
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        Type l = left.Type;
-                       Type r = right.Type;
                        OpCode opcode;
 
-                       if (method != null) {
-
-                               // Note that operators are static anyway
-                               
-                               if (Arguments != null) 
-                                       Invocation.EmitArguments (ec, method, Arguments);
-                               
-                               if (method is MethodInfo)
-                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
-                               else
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-
-                               if (DelegateOperation)
-                                       ig.Emit (OpCodes.Castclass, type);
-                                       
-                               return;
-                       }
-
                        //
                        // Handle short-circuit operators differently
                        // than the rest
                        //
-                       if (oper == Operator.LogicalAnd){
+                       if (oper == Operator.LogicalAnd) {
                                Label load_zero = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
-
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (left_binary.EmitBranchable (ec, load_zero, false)){
-                                               right.Emit (ec);
-                                               ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       }
-                               }
-
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brfalse, load_zero);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
+                                                               
+                               left.EmitBranchable (ec, load_zero, false);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Br, end);
+                               
                                ig.MarkLabel (load_zero);
                                ig.Emit (OpCodes.Ldc_I4_0);
                                ig.MarkLabel (end);
                                return;
-                       } else if (oper == Operator.LogicalOr){
+                       } else if (oper == Operator.LogicalOr) {
                                Label load_one = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
-                               
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
 
-                                       if (left_binary.EmitBranchable (ec, load_one, true)){
-                                               right.Emit (ec);
-                                               ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       } 
-                               }
-
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brtrue, load_one);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
+                               left.EmitBranchable (ec, load_one, true);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Br, end);
+                               
                                ig.MarkLabel (load_one);
                                ig.Emit (OpCodes.Ldc_I4_1);
                                ig.MarkLabel (end);
@@ -2986,7 +2939,7 @@ namespace Mono.CSharp {
                        right.Emit (ec);
 
                        bool isUnsigned = is_unsigned (left.Type);
-
+                       
                        switch (oper){
                        case Operator.Multiply:
                                if (ec.CheckState){
@@ -3095,9 +3048,9 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (OpCodes.Clt);
                                
-                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.Emit (OpCodes.Ldc_I4_0);
                                
-                               opcode = OpCodes.Sub;
+                               opcode = OpCodes.Ceq;
                                break;
 
                        case Operator.BitwiseOr:
@@ -3119,13 +3072,297 @@ namespace Mono.CSharp {
 
                        ig.Emit (opcode);
                }
+       }
+
+       //
+       // Object created by Binary when the binary operator uses an method instead of being
+       // a binary operation that maps to a CIL binary operation.
+       //
+       public class BinaryMethod : Expression {
+               public MethodBase method;
+               public ArrayList  Arguments;
+               
+               public BinaryMethod (Type t, MethodBase m, ArrayList args)
+               {
+                       method = m;
+                       Arguments = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (Arguments != null) 
+                               Invocation.EmitArguments (ec, method, Arguments);
+                       
+                       if (method is MethodInfo)
+                               ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       else
+                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+               }
+       }
+       
+       //
+       // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+       // b, c, d... may be strings or objects.
+       //
+       public class StringConcat : Expression {
+               ArrayList operands;
+               bool invalid = false;
+               
+               
+               public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+               {
+                       this.loc = loc;
+                       type = TypeManager.string_type;
+                       eclass = ExprClass.Value;
+               
+                       operands = new ArrayList (2);
+                       Append (ec, left);
+                       Append (ec, right);
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (invalid)
+                               return null;
+                       
+                       return this;
+               }
+               
+               public void Append (EmitContext ec, Expression operand)
+               {
+                       //
+                       // Constant folding
+                       //
+                       if (operand is StringConstant && operands.Count != 0) {
+                               StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+                               if (last_operand != null) {
+                                       operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+                                       return;
+                               }
+                       }
+                       
+                       //
+                       // Conversion to object
+                       //
+                       if (operand.Type != TypeManager.string_type) {
+                               Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+                               
+                               if (no == null) {
+                                       Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+                                       invalid = true;
+                               }
+                               operand = no;
+                       }
+                       
+                       operands.Add (operand);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       MethodInfo concat_method = null;
+                       
+                       //
+                       // Are we also concating objects?
+                       //
+                       bool is_strings_only = true;
+                       
+                       //
+                       // Do conversion to arguments; check for strings only
+                       //
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               is_strings_only &= e.Type == TypeManager.string_type;
+                       }
+                       
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               
+                               if (! is_strings_only && e.Type == TypeManager.string_type) {
+                                       // need to make sure this is an object, because the EmitParams
+                                       // method might look at the type of this expression, see it is a
+                                       // string and emit a string [] when we want an object [];
+                                       
+                                       e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+                               }
+                               operands [i] = new Argument (e, Argument.AType.Expression);
+                       }
+                       
+                       //
+                       // Find the right method
+                       //
+                       switch (operands.Count) {
+                       case 1:
+                               //
+                               // This should not be possible, because simple constant folding
+                               // is taken care of in the Binary code.
+                               //
+                               throw new Exception ("how did you get here?");
+                       
+                       case 2:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string :
+                                       TypeManager.string_concat_object_object ;
+                               break;
+                       case 3:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string_string :
+                                       TypeManager.string_concat_object_object_object ;
+                               break;
+                       case 4:
+                               //
+                               // There is not a 4 param overlaod for object (the one that there is
+                               // is actually a varargs methods, and is only in corlib because it was
+                               // introduced there before.).
+                               //
+                               if (!is_strings_only)
+                                       goto default;
+                               
+                               concat_method = TypeManager.string_concat_string_string_string_string;
+                               break;
+                       default:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_dot_dot_dot :
+                                       TypeManager.string_concat_object_dot_dot_dot ;
+                               break;
+                       }
+                       
+                       Invocation.EmitArguments (ec, concat_method, operands);
+                       ec.ig.Emit (OpCodes.Call, concat_method);
+               }
+       }
 
-               public bool IsBuiltinOperator {
+       //
+       // Object created with +/= on delegates
+       //
+       public class BinaryDelegate : Expression {
+               MethodInfo method;
+               ArrayList  args;
+
+               public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+               {
+                       method = mi;
+                       this.args = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       Invocation.EmitArguments (ec, method, args);
+                       
+                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       ig.Emit (OpCodes.Castclass, type);
+               }
+
+               public Expression Right {
                        get {
-                               return method == null;
+                               Argument arg = (Argument) args [1];
+                               return arg.Expr;
+                       }
+               }
+
+               public bool IsAddition {
+                       get {
+                               return method == TypeManager.delegate_combine_delegate_delegate;
                        }
                }
        }
+       
+       //
+       // User-defined conditional logical operator
+       public class ConditionalLogicalOperator : Expression {
+               Expression left, right;
+               bool is_and;
+
+               public ConditionalLogicalOperator (bool is_and, Expression left, Expression right, Type t, Location loc)
+               {
+                       type = t;
+                       eclass = ExprClass.Value;
+                       this.loc = loc;
+                       this.left = left;
+                       this.right = right;
+                       this.is_and = is_and;
+               }
+
+               protected void Error19 ()
+               {
+                       Binary.Error_OperatorCannotBeApplied (loc, is_and ? "&&" : "||", type, type);
+               }
+
+               protected void Error218 ()
+               {
+                       Error (218, "The type ('" + TypeManager.CSharpName (type) + "') must contain " +
+                              "declarations of operator true and operator false");
+               }
+
+               Expression op_true, op_false, op;
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       MethodInfo method;
+                       Expression operator_group;
+
+                       operator_group = MethodLookup (ec, type, is_and ? "op_BitwiseAnd" : "op_BitwiseOr", loc);
+                       if (operator_group == null) {
+                               Error19 ();
+                               return null;
+                       }
+
+                       ArrayList arguments = new ArrayList ();
+                       arguments.Add (new Argument (left, Argument.AType.Expression));
+                       arguments.Add (new Argument (right, Argument.AType.Expression));
+                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc) as MethodInfo;
+                       if ((method == null) || (method.ReturnType != type)) {
+                               Error19 ();
+                               return null;
+                       }
+
+                       op = new StaticCallExpr (method, arguments, loc);
+
+                       op_true = GetOperatorTrue (ec, left, loc);
+                       op_false = GetOperatorFalse (ec, left, loc);
+                       if ((op_true == null) || (op_false == null)) {
+                               Error218 ();
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label false_target = ig.DefineLabel ();
+                       Label end_target = ig.DefineLabel ();
+
+                       ig.Emit (OpCodes.Nop);
+
+                       (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
+                       left.Emit (ec);
+                       ig.Emit (OpCodes.Br, end_target);
+                       ig.MarkLabel (false_target);
+                       op.Emit (ec);
+                       ig.MarkLabel (end_target);
+
+                       ig.Emit (OpCodes.Nop);
+               }
+       }
 
        public class PointerArithmetic : Expression {
                Expression left, right;
@@ -3156,7 +3393,7 @@ namespace Mono.CSharp {
                {
                        Type op_type = left.Type;
                        ILGenerator ig = ec.ig;
-                       int size = GetTypeSize (op_type.GetElementType ());
+                       int size = GetTypeSize (TypeManager.GetElementType (op_type));
                        Type rtype = right.Type;
                        
                        if (rtype.IsPointer){
@@ -3320,7 +3557,7 @@ namespace Mono.CSharp {
                        Label false_target = ig.DefineLabel ();
                        Label end_target = ig.DefineLabel ();
 
-                       Statement.EmitBoolExpression (ec, expr, false_target, false);
+                       expr.EmitBranchable (ec, false_target, false);
                        trueExpr.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -3337,7 +3574,6 @@ namespace Mono.CSharp {
                public readonly string Name;
                public readonly Block Block;
                LocalInfo local_info;
-               VariableInfo variable_info;
                bool is_readonly;
                
                public LocalVariableReference (Block block, string name, Location l)
@@ -3359,7 +3595,7 @@ namespace Mono.CSharp {
                }
 
                public VariableInfo VariableInfo {
-                       get { return variable_info; }
+                       get { return local_info.VariableInfo; }
                }
 
                public bool IsReadOnly {
@@ -3375,14 +3611,15 @@ namespace Mono.CSharp {
                                is_readonly = local_info.ReadOnly;
                        }
 
-                       variable_info = Block.GetVariableInfo (local_info);
                        type = local_info.VariableType;
+#if false
+                       if (ec.InAnonymousMethod)
+                               Block.LiftVariable (local_info);
+#endif
                }
-               
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       DoResolveBase (ec);
 
+               protected Expression DoResolve (EmitContext ec, bool is_lvalue)
+               {
                        Expression e = Block.GetConstantExpression (Name);
                        if (e != null) {
                                local_info.Used = true;
@@ -3390,20 +3627,35 @@ namespace Mono.CSharp {
                                return e;
                        }
 
+                       VariableInfo variable_info = local_info.VariableInfo; 
                        if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
                                return null;
 
+                       if (!is_lvalue)
+                               local_info.Used = true;
+
+                       if (local_info.LocalBuilder == null)
+                               return ec.RemapLocal (local_info);
+                       
                        return this;
                }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       DoResolveBase (ec);
+
+                       return DoResolve (ec, false);
+               }
 
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        DoResolveBase (ec);
 
+                       VariableInfo variable_info = local_info.VariableInfo; 
                        if (variable_info != null)
                                variable_info.SetAssigned (ec);
 
-                       Expression e = DoResolve (ec);
+                       Expression e = DoResolve (ec, true);
 
                        if (e == null)
                                return null;
@@ -3412,46 +3664,43 @@ namespace Mono.CSharp {
                                Error (1604, "cannot assign to `" + Name + "' because it is readonly");
                                return null;
                        }
+
+                       if (local_info.LocalBuilder == null)
+                               return ec.RemapLocalLValue (local_info, right_side);
                        
                        return this;
                }
 
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return !is_expression || local_info.IsFixed;
+               }
+
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
 
-                       if (local_info.LocalBuilder == null){
-                               ec.EmitThis ();
-                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
-                       } else 
-                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
-                       
-                       local_info.Used = true;
+                       ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
                }
                
                public void EmitAssign (EmitContext ec, Expression source)
                {
                        ILGenerator ig = ec.ig;
 
-                       local_info.Assigned = true;
-
-                       if (local_info.LocalBuilder == null){
-                               ec.EmitThis ();
-                               source.Emit (ec);
-                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
-                       } else {
-                               source.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
-                       }
+                       source.Emit (ec);
+                       ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
                }
                
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       if (local_info.LocalBuilder == null){
-                               ec.EmitThis ();
-                               ec.ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
-                       } else
-                               ec.ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+                       ILGenerator ig = ec.ig;
+                       
+                       ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
                }
        }
 
@@ -3482,6 +3731,11 @@ namespace Mono.CSharp {
                        get { return vi; }
                }
 
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return !is_expression || TypeManager.IsValueType (type);
+               }
+
                public bool IsAssigned (EmitContext ec, Location loc)
                {
                        if (!ec.DoFlowAnalysis || !is_out ||
@@ -3546,6 +3800,9 @@ namespace Mono.CSharp {
                        if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
                                return null;
 
+                       if (ec.RemapToProxy)
+                               return ec.RemapParameter (idx);
+                       
                        return this;
                }
 
@@ -3555,6 +3812,9 @@ namespace Mono.CSharp {
 
                        SetAssigned (ec);
 
+                       if (ec.RemapToProxy)
+                               return ec.RemapParameterLValue (idx, right_side);
+                       
                        return this;
                }
 
@@ -3593,12 +3853,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (ec.RemapToProxy){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ec.EmitArgument (idx);
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3620,13 +3874,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (ec.RemapToProxy){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               source.Emit (ec);
-                               ec.EmitStoreArgument (idx);
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3649,11 +3896,6 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       if (ec.RemapToProxy){
-                               Report.Error (-1, "Report this: Taking the address of a remapped parameter not supported");
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3869,9 +4111,10 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///  Determines "better conversion" as specified in 7.4.2.3
-               ///  Returns : 1 if a->p is better
-               ///            0 if a->q or neither is better 
+               ///   Determines "better conversion" as specified in 7.4.2.3
+               ///
+                ///    Returns : 1 if a->p is better
+               ///              0 if a->q or neither is better 
                /// </summary>
                static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
                {
@@ -3879,17 +4122,40 @@ namespace Mono.CSharp {
                        Expression argument_expr = a.Expr;
 
                        if (argument_type == null)
-                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+                               throw new Exception ("Expression of type " + a.Expr +
+                                                     " does not resolve its type");
 
                        //
-                       // This is a special case since csc behaves this way. I can't find
-                       // it anywhere in the spec but oh well ...
+                       // This is a special case since csc behaves this way.
                        //
-                       if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+                       if (argument_expr is NullLiteral &&
+                            p == TypeManager.string_type &&
+                            q == TypeManager.object_type)
                                return 1;
-                       else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+                       else if (argument_expr is NullLiteral &&
+                                 p == TypeManager.object_type &&
+                                 q == TypeManager.string_type)
                                return 0;
                        
+                        //
+                        // csc behaves this way so we emulate it. Basically, if the argument
+                        // is null and one of the types to compare is 'object' and the other
+                        // is a reference type, we prefer the other.
+                        //
+                        // I can't find this anywhere in the spec but we can interpret this
+                        // to mean that null can be of any type you wish in such a context
+                        //
+                        if (p != null && q != null) {
+                                if (argument_expr is NullLiteral &&
+                                    !p.IsValueType &&
+                                    q == TypeManager.object_type)
+                                        return 1;
+                                else if (argument_expr is NullLiteral &&
+                                         !q.IsValueType &&
+                                         p == TypeManager.object_type)
+                                        return 0;
+                        }
+                                
                        if (p == q)
                                return 0;
                        
@@ -3954,6 +4220,14 @@ namespace Mono.CSharp {
                                        // we can optimize this case: a positive int32
                                        // always fits on a uint64
                                        //
+
+                                        //
+                                        // This special case is needed because csc behaves like this.
+                                        // int -> uint is better than int -> ulong!
+                                        //
+                                        if (q == TypeManager.uint32_type)
+                                                return 0;
+                                        
                                        if (q == TypeManager.int64_type)
                                                return 0;
                                        else if (value >= 0)
@@ -4008,16 +4282,18 @@ namespace Mono.CSharp {
                }
                
                /// <summary>
-               ///  Determines "Better function"
+               ///   Determines "Better function" between candidate
+                ///   and the current best match
                /// </summary>
                /// <remarks>
-               ///    and returns an integer indicating :
-               ///    0 if candidate ain't better
-               ///    1 if candidate is better than the current best match
+               ///    Returns an integer indicating :
+               ///     0 if candidate ain't better
+               ///     1 if candidate is better than the current best match
                /// </remarks>
                static int BetterFunction (EmitContext ec, ArrayList args,
-                                          MethodBase candidate, MethodBase best,
-                                          bool expanded_form, Location loc)
+                                          MethodBase candidate, bool candidate_params,
+                                           MethodBase best, bool best_params,
+                                          Location loc)
                {
                        ParameterData candidate_pd = GetParameterData (candidate);
                        ParameterData best_pd;
@@ -4029,14 +4305,35 @@ namespace Mono.CSharp {
                                argument_count = args.Count;
 
                        int cand_count = candidate_pd.Count;
-
+                       
+                       //
+                       // If there is no best method, than this one
+                       // is better, however, if we already found a
+                       // best method, we cant tell. This happens
+                       // if we have:
+                       // 
+                       //      interface IFoo {
+                       //              void DoIt ();
+                       //      }
+                       //      
+                       //      interface IBar {
+                       //              void DoIt ();
+                       //      }
+                       //      
+                       //      interface IFooBar : IFoo, IBar {}
+                       //
+                       // We cant tell if IFoo.DoIt is better than IBar.DoIt
+                       //
+                       // However, we have to consider that
+                       // Trim (); is better than Trim (params char[] chars);
+                        //
                        if (cand_count == 0 && argument_count == 0)
-                               return 1;
+                               return best == null || best_params ? 1 : 0;
 
                        if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
                                if (cand_count != argument_count)
                                        return 0;
-                       
+
                        if (best == null) {
                                int x = 0;
 
@@ -4044,15 +4341,14 @@ namespace Mono.CSharp {
                                    candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
                                        return 1;
                                
-                               for (int j = argument_count; j > 0;) {
-                                       j--;
+                               for (int j = 0; j < argument_count; ++j) {
 
                                        Argument a = (Argument) args [j];
                                        Type t = candidate_pd.ParameterType (j);
 
                                        if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                               if (expanded_form)
-                                                       t = t.GetElementType ();
+                                               if (candidate_params)
+                                                       t = TypeManager.GetElementType (t);
 
                                        x = BetterConversion (ec, a, t, null, loc);
                                        
@@ -4079,13 +4375,13 @@ namespace Mono.CSharp {
                                Type bt = best_pd.ParameterType (j);
 
                                if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                       if (expanded_form)
-                                               ct = ct.GetElementType ();
+                                       if (candidate_params)
+                                               ct = TypeManager.GetElementType (ct);
 
                                if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                       if (expanded_form)
-                                               bt = bt.GetElementType ();
-                               
+                                       if (best_params)
+                                               bt = TypeManager.GetElementType (bt);
+
                                x = BetterConversion (ec, a, ct, bt, loc);
                                y = BetterConversion (ec, a, bt, ct, loc);
 
@@ -4096,6 +4392,16 @@ namespace Mono.CSharp {
                                rating2 += y;
                        }
 
+                        //
+                        // If a method (in the normal form) with the
+                        // same signature as the expanded form of the
+                        // current best params method already exists,
+                        // the expanded form is not applicable so we
+                        // force it to select the candidate
+                        //
+                        if (!candidate_params && best_params && cand_count == argument_count)
+                                return 1;
+
                        if (rating1 > rating2)
                                return 1;
                        else
@@ -4106,6 +4412,9 @@ namespace Mono.CSharp {
                {
                        string ret_type = "";
 
+                        if (mb == null)
+                                return "";
+
                        if (mb is MethodInfo)
                                ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
                        
@@ -4137,7 +4446,7 @@ namespace Mono.CSharp {
                        MemberInfo [] miset;
                        MethodGroupExpr union;
 
-                       if (mg1 == null){
+                       if (mg1 == null) {
                                if (mg2 == null)
                                        return null;
                                return (MethodGroupExpr) mg2;
@@ -4157,33 +4466,29 @@ namespace Mono.CSharp {
                        
                        ArrayList common = new ArrayList ();
 
-                       foreach (MethodBase l in left_set.Methods){
-                               foreach (MethodBase r in right_set.Methods){
-                                       if (l != r)
-                                               continue;
+                       foreach (MethodBase r in right_set.Methods){
+                               if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
                                        common.Add (r);
-                                       break;
-                               }
                        }
-                       
+
                        miset = new MemberInfo [length1 + length2 - common.Count];
                        left_set.Methods.CopyTo (miset, 0);
                        
                        int k = length1;
 
-                       foreach (MemberInfo mi in right_set.Methods){
-                               if (!common.Contains (mi))
-                                       miset [k++] = mi;
+                       foreach (MethodBase r in right_set.Methods) {
+                               if (!common.Contains (r))
+                                       miset [k++] = r;
                        }
-                       
+
                        union = new MethodGroupExpr (miset, loc);
                        
                        return union;
                }
 
                /// <summary>
-               ///  Determines is the candidate method, if a params method, is applicable
-               ///  in its expanded form to the given set of arguments
+               ///   Determines if the candidate method, if a params method, is applicable
+               ///   in its expanded form to the given set of arguments
                /// </summary>
                static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
                {
@@ -4211,8 +4516,9 @@ namespace Mono.CSharp {
                                return true;
 
                        //
-                       // If we have come this far, the case which remains is when the number of parameters
-                       // is less than or equal to the argument count.
+                       // If we have come this far, the case which
+                       // remains is when the number of parameters is
+                       // less than or equal to the argument count.
                        //
                        for (int i = 0; i < pd_count - 1; ++i) {
 
@@ -4226,7 +4532,9 @@ namespace Mono.CSharp {
                                if (a_mod == p_mod) {
 
                                        if (a_mod == Parameter.Modifier.NONE)
-                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+                                               if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr,
+                                                                                       pd.ParameterType (i)))
                                                        return false;
                                                                                
                                        if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
@@ -4243,12 +4551,12 @@ namespace Mono.CSharp {
                                
                        }
 
-                       Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
+                       Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
 
                        for (int i = pd_count - 1; i < arg_count; i++) {
                                Argument a = (Argument) arguments [i];
                                
-                               if (!Convert.ImplicitStandardConversionExists (a.Expr, element_type))
+                               if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
                                        return false;
                        }
                        
@@ -4256,8 +4564,8 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///  Determines if the candidate method is applicable (section 14.4.2.1)
-               ///  to the given set of arguments
+               ///   Determines if the candidate method is applicable (section 14.4.2.1)
+               ///   to the given set of arguments
                /// </summary>
                static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
                {
@@ -4268,13 +4576,12 @@ namespace Mono.CSharp {
                        else
                                arg_count = arguments.Count;
 
-                       ParameterData pd = GetParameterData (candidate);
 
-                       int pd_count = pd.Count;
+                       ParameterData pd = GetParameterData (candidate);
 
                        if (arg_count != pd.Count)
                                return false;
-                       
+
                        for (int i = arg_count; i > 0; ) {
                                i--;
 
@@ -4285,18 +4592,22 @@ namespace Mono.CSharp {
                                Parameter.Modifier p_mod = pd.ParameterModifier (i) &
                                        ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
 
+
                                if (a_mod == p_mod ||
                                    (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
-                                       if (a_mod == Parameter.Modifier.NONE)
-                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+                                       if (a_mod == Parameter.Modifier.NONE) {
+                                                if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr,
+                                                                                       pd.ParameterType (i)))
                                                        return false;
+                                        }
                                        
                                        if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
                                                Type pt = pd.ParameterType (i);
 
                                                if (!pt.IsByRef)
                                                        pt = TypeManager.GetReferenceType (pt);
-
+                                                
                                                if (pt != a.Type)
                                                        return false;
                                        }
@@ -4307,8 +4618,6 @@ namespace Mono.CSharp {
                        return true;
                }
                
-               
-
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -4329,63 +4638,95 @@ namespace Mono.CSharp {
                                                          ArrayList Arguments, Location loc)
                {
                        MethodBase method = null;
-                       Type current_type = null;
+                       Type applicable_type = null;
                        int argument_count;
                        ArrayList candidates = new ArrayList ();
-                       
 
-                       foreach (MethodBase candidate in me.Methods){
-                               int x;
+                        //
+                        // Used to keep a map between the candidate
+                        // and whether it is being considered in its
+                        // normal or expanded form
+                        //
+                        // false is normal form, true is expanded form
+                        //
+                        Hashtable candidate_to_form = new PtrHashtable ();
+
+
+                        //
+                        // First we construct the set of applicable methods
+                        //
+                        // We start at the top of the type hierarchy and
+                        // go down to find applicable methods
+                        //
+                        applicable_type = me.DeclaringType;
+                        
+                        if (me.Name == "Invoke" && TypeManager.IsDelegateType (applicable_type)) {
+                                Error_InvokeOnDelegate (loc);
+                                return null;
+                        }
 
-                               // If we're going one level higher in the class hierarchy, abort if
-                               // we already found an applicable method.
-                               if (candidate.DeclaringType != current_type) {
-                                       current_type = candidate.DeclaringType;
-                                       if (method != null)
-                                               break;
-                               }
+                        bool found_applicable = false;
 
-                               // Check if candidate is applicable (section 14.4.2.1)
-                               if (!IsApplicable (ec, Arguments, candidate))
-                                       continue;
+                       foreach (MethodBase candidate in me.Methods){
+                                Type decl_type = candidate.DeclaringType;
 
-                               candidates.Add (candidate);
-                               x = BetterFunction (ec, Arguments, candidate, method, false, loc);
-                               
-                               if (x == 0)
-                                       continue;
+                                //
+                                // If we have already found an applicable method
+                                // we eliminate all base types (Section 14.5.5.1)
+                                //
+                                if (decl_type != applicable_type &&
+                                    (applicable_type.IsSubclassOf (decl_type) ||
+                                     TypeManager.ImplementsInterface (applicable_type, decl_type)) &&
+                                    found_applicable)
+                                                continue;
 
-                               method = candidate;
-                       }
+
+                               // Check if candidate is applicable (section 14.4.2.1)
+                               if (IsApplicable (ec, Arguments, candidate)) {
+                                        // Candidate is applicable in normal form
+                                        candidates.Add (candidate);
+                                        applicable_type = candidate.DeclaringType;
+                                        found_applicable = true;
+                                        candidate_to_form [candidate] = false;
+                                } else if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
+                                                // Candidate is applicable in expanded form
+                                                candidates.Add (candidate);
+                                                applicable_type = candidate.DeclaringType;
+                                                found_applicable = true; 
+                                                candidate_to_form [candidate] = true;
+                                        }
+                                }
+                        
+
+                        //
+                        // Now we actually find the best method
+                        //
+                       int candidate_top = candidates.Count;
+                       for (int ix = 0; ix < candidate_top; ix++){
+                               MethodBase candidate = (MethodBase) candidates [ix];
+
+                                bool cand_params = (bool) candidate_to_form [candidate];
+                                bool method_params = false;
+
+                                if (method != null)
+                                        method_params = (bool) candidate_to_form [method];
+                                
+                                int x = BetterFunction (ec, Arguments,
+                                                        candidate, cand_params,
+                                                        method, method_params,
+                                                        loc);
+                                
+                                if (x == 0)
+                                        continue;
+                                
+                                method = candidate;
+                        }
 
                        if (Arguments == null)
                                argument_count = 0;
                        else
                                argument_count = Arguments.Count;
                        
-                       //
-                       // Now we see if we can find params functions, applicable in their expanded form
-                       // since if they were applicable in their normal form, they would have been selected
-                       // above anyways
-                       //
-                       bool chose_params_expanded = false;
-                       
-                       if (method == null) {
-                               candidates = new ArrayList ();
-                               foreach (MethodBase candidate in me.Methods){
-                                       if (!IsParamsMethodApplicable (ec, Arguments, candidate))
-                                               continue;
-
-                                       candidates.Add (candidate);
-
-                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
-                                       if (x == 0)
-                                               continue;
-
-                                       method = candidate; 
-                                       chose_params_expanded = true;
-                               }
-                       }
 
                        if (method == null) {
                                //
@@ -4402,8 +4743,17 @@ namespace Mono.CSharp {
 
                                        VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
                                                               null, loc);
+                                        break;
                                }
-                               
+
+                                if (!Location.IsNull (loc)) {
+                                        string report_name = me.Name;
+                                        if (report_name == ".ctor")
+                                                report_name = me.DeclaringType.ToString ();
+                                        
+                                        Error_WrongNumArguments (loc, report_name, argument_count);
+                                }
+                                
                                return null;
                        }
 
@@ -4411,22 +4761,31 @@ namespace Mono.CSharp {
                        // Now check that there are no ambiguities i.e the selected method
                        // should be better than all the others
                        //
+                        bool best_params = (bool) candidate_to_form [method];
 
-                       foreach (MethodBase candidate in candidates){
-                               if (candidate == method)
-                                       continue;
+                       for (int ix = 0; ix < candidate_top; ix++){
+                               MethodBase candidate = (MethodBase) candidates [ix];
 
+                                if (candidate == method)
+                                        continue;
+                                               
                                //
-                               // If a normal method is applicable in the sense that it has the same
-                               // number of arguments, then the expanded params method is never applicable
-                               // so we debar the params method.
+                               // If a normal method is applicable in
+                               // the sense that it has the same
+                               // number of arguments, then the
+                               // expanded params method is never
+                               // applicable so we debar the params
+                               // method.
                                //
-                               if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                   IsApplicable (ec, Arguments, method))
-                                       continue;
-                                       
-                               int x = BetterFunction (ec, Arguments, method, candidate,
-                                                       chose_params_expanded, loc);
+                                // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+//                                      IsApplicable (ec, Arguments, method)))
+//                                         continue;
+                                
+                                bool cand_params = (bool) candidate_to_form [candidate];
+                               int x = BetterFunction (ec, Arguments,
+                                                        method, best_params,
+                                                        candidate, cand_params,
+                                                       loc);
 
                                if (x != 1) {
                                        Report.Error (
@@ -4437,17 +4796,31 @@ namespace Mono.CSharp {
                        }
 
                        //
-                       // And now check if the arguments are all compatible, perform conversions
-                       // if necessary etc. and return if everything is all right
+                       // And now check if the arguments are all
+                       // compatible, perform conversions if
+                       // necessary etc. and return if everything is
+                       // all right
                        //
-
-                       if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
-                                                  chose_params_expanded, null, loc))
+                        if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+                                                    best_params, null, loc))
                                return null;
 
                        return method;
                }
 
+                static void Error_WrongNumArguments (Location loc, String name, int arg_count)
+                {
+                        Report.Error (1501, loc,
+                                      "No overload for method `" + name + "' takes `" +
+                                      arg_count + "' arguments");
+                }
+
+                static void Error_InvokeOnDelegate (Location loc)
+                {
+                        Report.Error (1533, loc,
+                                      "Invoke cannot be called directly on a delegate");
+                }
+                        
                static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
                                                     Type delegate_type, string arg_sig, string par_desc)
                {
@@ -4482,8 +4855,16 @@ namespace Mono.CSharp {
                                Parameter.Modifier pm = pd.ParameterModifier (j);
                                
                                if (pm == Parameter.Modifier.PARAMS){
+                                       if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
+                                               if (!Location.IsNull (loc))
+                                                       Error_InvalidArguments (
+                                                               loc, j, method, delegate_type,
+                                                               Argument.FullDesc (a), pd.ParameterDesc (j));
+                                               return false;
+                                       }
+
                                        if (chose_params_expanded)
-                                               parameter_type = TypeManager.TypeToCoreType (parameter_type.GetElementType ());
+                                               parameter_type = TypeManager.GetElementType (parameter_type);
                                } else {
                                        //
                                        // Check modifiers
@@ -4524,14 +4905,10 @@ namespace Mono.CSharp {
                                        ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
                                Parameter.Modifier p_mod = pd.ParameterModifier (j) &
                                        ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
-
                                
                                if (a_mod != p_mod &&
                                    pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
                                        if (!Location.IsNull (loc)) {
-                                               Console.WriteLine ("A:P: " + a.GetParameterModifier ());
-                                               Console.WriteLine ("PP:: " + pd.ParameterModifier (j));
-                                               Console.WriteLine ("PT:  " + parameter_type.IsByRef);
                                                Report.Error (1502, loc,
                                                       "The best overloaded match for method '" + FullMethodDesc (method)+
                                                       "' has some invalid arguments");
@@ -4557,8 +4934,6 @@ namespace Mono.CSharp {
                        if (expr is BaseAccess)
                                is_base = true;
 
-                       Expression old = expr;
-                       
                        expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
                        if (expr == null)
                                return null;
@@ -4639,19 +5014,15 @@ namespace Mono.CSharp {
                        int count = arguments.Count - idx;
                        Argument a = (Argument) arguments [idx];
                        Type t = a.Expr.Type;
-                       string array_type = t.FullName + "[]";
-                       LocalBuilder array;
-
-                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
+                       
                        IntConstant.EmitInt (ig, count);
                        ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
-                       ig.Emit (OpCodes.Stloc, array);
 
                        int top = arguments.Count;
                        for (int j = idx; j < top; j++){
                                a = (Argument) arguments [j];
                                
-                               ig.Emit (OpCodes.Ldloc, array);
+                               ig.Emit (OpCodes.Dup);
                                IntConstant.EmitInt (ig, j - idx);
 
                                bool is_stobj;
@@ -4666,7 +5037,6 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (op);
                        }
-                       ig.Emit (OpCodes.Ldloc, array);
                }
                
                /// <summary>
@@ -4695,7 +5065,7 @@ namespace Mono.CSharp {
                                        ILGenerator ig = ec.ig;
 
                                        IntConstant.EmitInt (ig, 0);
-                                       ig.Emit (OpCodes.Newarr, pd.ParameterType (0).GetElementType ());
+                                       ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0)));
                                }
 
                                return;
@@ -4728,7 +5098,7 @@ namespace Mono.CSharp {
                                ILGenerator ig = ec.ig;
 
                                IntConstant.EmitInt (ig, 0);
-                               ig.Emit (OpCodes.Newarr, pd.ParameterType (top).GetElementType ());
+                               ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
                        }
                }
 
@@ -4753,6 +5123,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        bool struct_call = false;
+                       bool this_call = false;
 
                        Type decl_type = method.DeclaringType;
 
@@ -4791,7 +5162,8 @@ namespace Mono.CSharp {
                                //
                                // If this is ourselves, push "this"
                                //
-                               if (instance_expr == null){
+                               if (instance_expr == null) {
+                                       this_call = true;
                                        ig.Emit (OpCodes.Ldarg_0);
                                } else {
                                        //
@@ -4834,8 +5206,13 @@ namespace Mono.CSharp {
                        }
 
                        EmitArguments (ec, method, Arguments);
-
-                       if (is_static || struct_call || is_base){
+                       //
+                       // If you have:
+                       // this.DoFoo ();
+                       // and DoFoo is not virtual, you can omit the callvirt,
+                       // because you don't need the null checking behavior.
+                       //
+                       if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
                                if (method is MethodInfo) {
                                        ig.Emit (OpCodes.Call, (MethodInfo) method);
                                } else
@@ -4870,6 +5247,111 @@ namespace Mono.CSharp {
                }
        }
 
+       public class InvocationOrCast : ExpressionStatement
+       {
+               Expression expr;
+               Expression argument;
+
+               public InvocationOrCast (Expression expr, Expression argument, Location loc)
+               {
+                       this.expr = expr;
+                       this.argument = argument;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // First try to resolve it as a cast.
+                       //
+                       type = ec.DeclSpace.ResolveType (expr, true, loc);
+                       if (type != null) {
+                               Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
+                               return cast.Resolve (ec);
+                       }
+
+                       //
+                       // 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) {
+                               Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
+                               return cast.Resolve (ec);
+                       }
+
+                       //
+                       // It's a delegate invocation.
+                       //
+                       if (!TypeManager.IsDelegateType (expr.Type)) {
+                               Error (149, "Method name expected");
+                               return null;
+                       }
+
+                       ArrayList args = new ArrayList ();
+                       args.Add (new Argument (argument, Argument.AType.Expression));
+                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+                       return invocation.Resolve (ec);
+               }
+
+               void error201 ()
+               {
+                       Error (201, "Only assignment, call, increment, decrement and new object " +
+                              "expressions can be used as a statement");
+               }
+
+               public override ExpressionStatement ResolveStatement (EmitContext ec)
+               {
+                       //
+                       // First try to resolve it as a cast.
+                       //
+                       type = ec.DeclSpace.ResolveType (expr, true, loc);
+                       if (type != null) {
+                               error201 ();
+                               return null;
+                       }
+
+                       //
+                       // 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) || (expr.eclass == ExprClass.Type)) {
+                               error201 ();
+                               return null;
+                       }
+
+                       //
+                       // It's a delegate invocation.
+                       //
+                       if (!TypeManager.IsDelegateType (expr.Type)) {
+                               Error (149, "Method name expected");
+                               return null;
+                       }
+
+                       ArrayList args = new ArrayList ();
+                       args.Add (new Argument (argument, Argument.AType.Expression));
+                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+                       return invocation.ResolveStatement (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Cannot happen");
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       throw new Exception ("Cannot happen");
+               }
+       }
+
        //
        // This class is used to "disable" the code generation for the
        // temporary variable when initializing value types.
@@ -4886,7 +5368,13 @@ namespace Mono.CSharp {
        /// </summary>
        public class New : ExpressionStatement, IMemoryLocation {
                public readonly ArrayList Arguments;
-               public readonly Expression RequestedType;
+
+               //
+               // During bootstrap, it contains the RequestedType,
+               // but if `type' is not null, it *might* contain a NewDelegate
+               // (because of field multi-initialization)
+               //
+               public Expression RequestedType;
 
                MethodBase method = null;
 
@@ -4904,15 +5392,15 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public Expression ValueTypeVariable {
-                       get {
-                               return value_target;
-                       }
-
-                       set {
-                               value_target = value;
-                               value_target_set = true;
+               public bool SetValueTypeVariable (Expression value)
+               {
+                       value_target = value;
+                       value_target_set = true;
+                       if (!(value_target is IMemoryLocation)){
+                               Error_UnexpectedKind ("variable");
+                               return false;
                        }
+                       return true;
                }
 
                //
@@ -4952,8 +5440,11 @@ namespace Mono.CSharp {
                        //
                        // This leads to bugs (#37014)
                        //
-                       if (type != null)
+                       if (type != null){
+                               if (RequestedType is NewDelegate)
+                                       return RequestedType;
                                return this;
+                       }
                        
                        type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
                        
@@ -4962,16 +5453,20 @@ namespace Mono.CSharp {
                        
                        bool IsDelegate = TypeManager.IsDelegateType (type);
                        
-                       if (IsDelegate)
-                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                       if (IsDelegate){
+                               RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                               if (RequestedType != null)
+                                       if (!(RequestedType is NewDelegate))
+                                               throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
+                               return RequestedType;
+                       }
 
                        if (type.IsInterface || type.IsAbstract){
                                Error (144, "It is not possible to create instances of interfaces or abstract classes");
                                return null;
                        }
                        
-                       bool is_struct = false;
-                       is_struct = type.IsValueType;
+                       bool is_struct = type.IsValueType;
                        eclass = ExprClass.Value;
 
                        //
@@ -5004,8 +5499,7 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
-                                                                    Arguments, loc);
+                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
                                
                        }
 
@@ -5017,6 +5511,7 @@ namespace Mono.CSharp {
                                        return null;
                                 }
                        }
+
                        return this;
                }
 
@@ -5057,7 +5552,7 @@ namespace Mono.CSharp {
                                // you can't share LocalBuilders among ILGeneators.
                                if (!value_target_set)
                                        value_target = new LocalTemporary (ec, type);
-                                       
+
                                ml = (IMemoryLocation) value_target;
                                ml.AddressOf (ec, AddressOp.Store);
                        }
@@ -5189,9 +5684,9 @@ namespace Mono.CSharp {
                        this.rank = rank;
                        loc = l;
 
-                       //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+                       //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
                        //
-                       //string tmp = rank.Substring (rank.LastIndexOf ("["));
+                       //string tmp = rank.Substring (rank.LastIndexOf ('['));
                        //
                        //dimensions = tmp.Length - 1;
                        expect_initializers = true;
@@ -5277,10 +5772,15 @@ namespace Mono.CSharp {
                                        
                                        if (conv == null) 
                                                return false;
-
-                                       if (conv is StringConstant)
+                                       
+                                       if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
+                                               // These are subclasses of Constant that can appear as elements of an
+                                               // array that cannot be statically initialized (with num_automatic_initializers
+                                               // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
                                                array_data.Add (conv);
-                                       else if (conv is Constant) {
+                                       } else if (conv is Constant) {
+                                               // These are the types of Constant that can appear in arrays that can be
+                                               // statically allocated.
                                                array_data.Add (conv);
                                                num_automatic_initializers++;
                                        } else
@@ -5439,7 +5939,7 @@ namespace Mono.CSharp {
 
                        underlying_type = type;
                        if (underlying_type.IsArray)
-                               underlying_type = TypeManager.TypeToCoreType (underlying_type.GetElementType ());
+                               underlying_type = TypeManager.GetElementType (underlying_type);
                        dimensions = type.GetArrayRank ();
 
                        return true;
@@ -5475,7 +5975,7 @@ namespace Mono.CSharp {
                                }
                        }
                        
-                       array_element_type = TypeManager.TypeToCoreType (type.GetElementType ());
+                       array_element_type = TypeManager.GetElementType (type);
 
                        if (arg_count == 1) {
                                is_one_dimensional = true;
@@ -5513,7 +6013,7 @@ namespace Mono.CSharp {
                                eclass = ExprClass.Value;
                                return this;
                        } else {
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                ArrayList args = new ArrayList ();
                                
                                if (arguments != null) {
@@ -5662,12 +6162,19 @@ namespace Mono.CSharp {
                                        if (!(v is Expression)){
                                                int [] bits = Decimal.GetBits ((decimal) v);
                                                int p = idx;
+
+                                               // FIXME: For some reason, this doesn't work on the MS runtime.
+                                               int [] nbits = new int [4];
+                                               nbits [0] = bits [3];
+                                               nbits [1] = bits [2];
+                                               nbits [2] = bits [0];
+                                               nbits [3] = bits [1];
                                                
                                                for (int j = 0; j < 4; j++){
-                                                       data [p++] = (byte) (bits [j] & 0xff);
-                                                       data [p++] = (byte) ((bits [j] >> 8) & 0xff);
-                                                       data [p++] = (byte) ((bits [j] >> 16) & 0xff);
-                                                       data [p++] = (byte) (bits [j] >> 24);
+                                                       data [p++] = (byte) (nbits [j] & 0xff);
+                                                       data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
+                                                       data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
+                                                       data [p++] = (byte) (nbits [j] >> 24);
                                                }
                                        }
                                } else
@@ -5700,7 +6207,7 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Call,
                                 TypeManager.void_initializearray_array_fieldhandle);
                }
-               
+
                //
                // Emits pieces of the array that can not be computed at compile
                // time (variables and string locations).
@@ -5713,16 +6220,13 @@ namespace Mono.CSharp {
                        int dims = bounds.Count;
                        int [] current_pos = new int [dims];
                        int top = array_data.Count;
-                       LocalBuilder temp = ig.DeclareLocal (type);
-
-                       ig.Emit (OpCodes.Stloc, temp);
 
                        MethodInfo set = null;
 
                        if (dims != 1){
                                Type [] args;
                                ModuleBuilder mb = null;
-                               mb = CodeGen.ModuleBuilder;
+                               mb = CodeGen.Module.Builder;
                                args = new Type [dims + 1];
 
                                int j;
@@ -5753,11 +6257,12 @@ namespace Mono.CSharp {
                                                e = ((EnumConstant) e).Child;
                                        }
                                        
-                                       if (e is StringConstant || !(e is Constant) ||
+                                       if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
                                            num_automatic_initializers <= max_automatic_initializers) {
                                                Type etype = e.Type;
                                                
-                                               ig.Emit (OpCodes.Ldloc, temp);
+                                               if (is_expression || i != top - 1)
+                                                       ig.Emit (OpCodes.Dup);
 
                                                for (int idx = 0; idx < dims; idx++) 
                                                        IntConstant.EmitInt (ig, current_pos [idx]);
@@ -5766,9 +6271,9 @@ namespace Mono.CSharp {
                                                // If we are dealing with a struct, get the
                                                // address of it, so we can store it.
                                                //
-                                               if ((dims == 1) &&
+                                               if ((dims == 1) && 
                                                    etype.IsSubclassOf (TypeManager.value_type) &&
-                                                   (!TypeManager.IsBuiltinType (etype) ||
+                                                   (!TypeManager.IsBuiltinOrEnum (etype) ||
                                                     etype == TypeManager.decimal_type)) {
                                                        if (e is New){
                                                                New n = (New) e;
@@ -5785,12 +6290,12 @@ namespace Mono.CSharp {
 
                                                e.Emit (ec);
 
-                                                if (dims == 1)
-                                                        ArrayAccess.EmitStoreOpcode (ig, array_element_type);
-                                                else 
-                                                        ig.Emit (OpCodes.Call, set);
-                                                
-                                        }
+                                               if (dims == 1)
+                                                       ArrayAccess.EmitStoreOpcode (ig, array_element_type);
+                                               else 
+                                                       ig.Emit (OpCodes.Call, set);
+
+                                       }
                                }
                                
                                //
@@ -5803,9 +6308,6 @@ namespace Mono.CSharp {
                                        current_pos [j] = 0;
                                }
                        }
-
-                       if (is_expression)
-                               ig.Emit (OpCodes.Ldloc, temp);
                }
 
                void EmitArrayArguments (EmitContext ec)
@@ -5843,11 +6345,11 @@ namespace Mono.CSharp {
                                // 
                                bool dynamic_initializers = true;
 
-                               if (underlying_type != TypeManager.string_type &&
-                                   underlying_type != TypeManager.object_type) {
-                                       if (num_automatic_initializers > max_automatic_initializers)
-                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
-                               }
+                               // This will never be true for array types that cannot be statically
+                               // initialized. num_automatic_initializers will always be zero.  See
+                               // CheckIndices.
+                               if (num_automatic_initializers > max_automatic_initializers)
+                                       EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
                                
                                if (dynamic_initializers)
                                        EmitDynamicInitializers (ec, !is_statement);
@@ -5891,6 +6393,16 @@ namespace Mono.CSharp {
                        }
                        return ret;
                }
+
+               public Expression TurnIntoConstant ()
+               {
+                       //
+                       // Should use something like the above attribute thing.
+                       // It should return a subclass of Constant that just returns
+                       // the computed value of the array
+                       //
+                       throw new Exception ("Does not support yet Turning array into a Constant");
+               }
        }
        
        /// <summary>
@@ -5916,6 +6428,14 @@ namespace Mono.CSharp {
                        get { return variable_info; }
                }
 
+               public bool VerifyFixed (bool is_expression)
+               {
+                       if ((variable_info == null) || (variable_info.LocalInfo == null))
+                               return false;
+                       else
+                               return variable_info.LocalInfo.IsFixed;
+               }
+
                public bool ResolveBase (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
@@ -5927,7 +6447,7 @@ namespace Mono.CSharp {
                        }
 
                        if ((block != null) && (block.ThisVariable != null))
-                               variable_info = block.GetVariableInfo (block.ThisVariable);
+                               variable_info = block.ThisVariable.VariableInfo;
 
                        return true;
                }
@@ -6007,12 +6527,35 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // This produces the value that renders an instance, used by the iterators code
+       //
+       public class ProxyInstance : Expression, IMemoryLocation  {
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = ExprClass.Variable;
+                       type = ec.ContainerType;
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+               }
+       }
+
        /// <summary>
        ///   Implements the typeof operator
        /// </summary>
        public class TypeOf : Expression {
                public readonly Expression QueriedType;
-               Type typearg;
+               protected Type typearg;
                
                public TypeOf (Expression queried_type, Location l)
                {
@@ -6027,6 +6570,12 @@ namespace Mono.CSharp {
                        if (typearg == null)
                                return null;
 
+                       if (typearg == TypeManager.void_type) {
+                               Error (673, "System.Void cannot be used from C# - " +
+                                      "use typeof (void) to get the void type object");
+                               return null;
+                       }
+
                        type = TypeManager.type_type;
                        eclass = ExprClass.Type;
                        return this;
@@ -6043,6 +6592,24 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   Implements the `typeof (void)' operator
+       /// </summary>
+       public class TypeOfVoid : TypeOf {
+               public TypeOfVoid (Location l) : base (null, l)
+               {
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.type_type;
+                       typearg = TypeManager.void_type;
+                       eclass = ExprClass.Type;
+                       return this;
+               }
+       }
+
        /// <summary>
        ///   Implements the sizeof expression
        /// </summary>
@@ -6149,7 +6716,7 @@ namespace Mono.CSharp {
 
                                // Implicitly default to `this' unless we're static.
                                if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
-                                       left = ec.This;
+                                       left = ec.GetThis (loc);
                        } else {
                                left_is_type = left is TypeExpr;
                                left_is_explicit = true;
@@ -6159,7 +6726,7 @@ namespace Mono.CSharp {
                                FieldExpr fe = (FieldExpr) member_lookup;
                                FieldInfo fi = fe.FieldInfo;
                                Type decl_type = fi.DeclaringType;
-                               
+
                                if (fi is FieldBuilder) {
                                        Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
                                        
@@ -6223,7 +6790,6 @@ namespace Mono.CSharp {
                        }
 
                        if (member_lookup is EventExpr) {
-
                                EventExpr ee = (EventExpr) member_lookup;
                                
                                //
@@ -6231,17 +6797,17 @@ namespace Mono.CSharp {
                                // a FieldExpr
                                //
 
-                               if (ee.EventInfo.DeclaringType == ec.ContainerType) {
+                               if (ee.EventInfo.DeclaringType == ec.ContainerType ||
+                                   TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
                                        MemberInfo mi = GetFieldFromEvent (ee);
 
                                        if (mi == null) {
                                                //
                                                // If this happens, then we have an event with its own
                                                // accessors and private field etc so there's no need
-                                               // to transform ourselves : we should instead flag an error
+                                               // to transform ourselves.
                                                //
-                                               Assign.error70 (ee.EventInfo, loc);
-                                               return null;
+                                               return ee;
                                        }
 
                                        Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
@@ -6250,11 +6816,14 @@ namespace Mono.CSharp {
                                                Report.Error (-200, loc, "Internal error!!");
                                                return null;
                                        }
+
+                                       if (!left_is_explicit)
+                                               left = null;
                                        
                                        return ResolveMemberAccess (ec, ml, left, loc, left_original);
                                }
                        }
-                       
+
                        if (member_lookup is IMemberExpr) {
                                IMemberExpr me = (IMemberExpr) member_lookup;
 
@@ -6264,7 +6833,8 @@ namespace Mono.CSharp {
                                                mg.IsExplicitImpl = left_is_explicit;
 
                                        if (!me.IsStatic){
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                               if ((ec.IsFieldInitializer || ec.IsStatic) &&
+                                                   IdenticalNameAndTypeName (ec, left_original, loc))
                                                        return member_lookup;
 
                                                SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
@@ -6349,8 +6919,6 @@ namespace Mono.CSharp {
                        // it will fail to find any members at all
                        //
 
-                       int errors = Report.Errors;
-                       
                        Type expr_type = expr.Type;
                        if (expr is TypeExpr){
                                if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
@@ -6358,10 +6926,10 @@ namespace Mono.CSharp {
                                               "is inaccessible because of its protection level");
                                        return null;
                                }
-                                   
+
                                if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
                                        Enum en = TypeManager.LookupEnum (expr_type);
-                                       
+
                                        if (en != null) {
                                                object value = en.LookupEnumValue (ec, Identifier, loc);
                                                
@@ -6384,8 +6952,15 @@ namespace Mono.CSharp {
                        if (member_lookup == null)
                                return null;
 
-                       if (member_lookup is TypeExpr)
+                       if (member_lookup is TypeExpr) {
+                               if (!(expr is TypeExpr) && !(expr is SimpleName)) {
+                                       Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
+                                              member_lookup.Type + "' instead");
+                                       return null;
+                               }
+
                                return member_lookup;
+                       }
                        
                        member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
                        if (member_lookup == null)
@@ -6416,6 +6991,24 @@ namespace Mono.CSharp {
 
                public override Expression ResolveAsTypeStep (EmitContext ec)
                {
+                       string fname = null;
+                       MemberAccess full_expr = this;
+                       while (full_expr != null) {
+                               if (fname != null)
+                                       fname = String.Concat (full_expr.Identifier, ".", fname);
+                               else
+                                       fname = full_expr.Identifier;
+
+                               if (full_expr.Expr is SimpleName) {
+                                       string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
+                                       Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
+                                       if (fully_qualified != null)
+                                               return new TypeExpression (fully_qualified, loc);
+                               }
+
+                               full_expr = full_expr.Expr as MemberAccess;
+                       }
+
                        Expression new_expr = expr.ResolveAsTypeStep (ec);
 
                        if (new_expr == null)
@@ -6633,6 +7226,11 @@ namespace Mono.CSharp {
                        //
                        Type t = Expr.Type;
 
+                       if (t == TypeManager.array_type){
+                               Report.Error (21, loc, "Cannot use indexer on System.Array");
+                               return null;
+                       }
+                       
                        if (t.IsArray)
                                return (new ArrayAccess (this, loc)).Resolve (ec);
                        else if (t.IsPointer)
@@ -6681,9 +7279,9 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
+#if false
                        ExprClass eclass = ea.Expr.eclass;
 
-#if false
                        // As long as the type is valid
                        if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
                              eclass == ExprClass.Value)) {
@@ -6700,8 +7298,9 @@ namespace Mono.CSharp {
                                          ea.Arguments.Count);
                                return null;
                        }
-                       type = TypeManager.TypeToCoreType (t.GetElementType ());
-                       if (type.IsPointer && !ec.InUnsafe){
+
+                        type = TypeManager.GetElementType (t);
+                        if (type.IsPointer && !ec.InUnsafe){
                                UnsafeError (ea.Location);
                                return null;
                        }
@@ -6817,7 +7416,7 @@ namespace Mono.CSharp {
 
                MethodInfo FetchGetMethod ()
                {
-                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       ModuleBuilder mb = CodeGen.Module.Builder;
                        int arg_count = ea.Arguments.Count;
                        Type [] args = new Type [arg_count];
                        MethodInfo get;
@@ -6838,7 +7437,7 @@ namespace Mono.CSharp {
 
                MethodInfo FetchAddressMethod ()
                {
-                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       ModuleBuilder mb = CodeGen.Module.Builder;
                        int arg_count = ea.Arguments.Count;
                        Type [] args = new Type [arg_count];
                        MethodInfo address;
@@ -6961,7 +7560,7 @@ namespace Mono.CSharp {
                        if (rank == 1)
                                EmitStoreOpcode (ig, t);
                        else {
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                int arg_count = ea.Arguments.Count;
                                Type [] args = new Type [arg_count + 1];
                                MethodInfo set;
@@ -7001,9 +7600,21 @@ namespace Mono.CSharp {
 
        
        class Indexers {
-               public ArrayList properties;
+               public ArrayList Properties;
                static Hashtable map;
 
+               public struct Indexer {
+                       public readonly Type Type;
+                       public readonly MethodInfo Getter, Setter;
+
+                       public Indexer (Type type, MethodInfo get, MethodInfo set)
+                       {
+                               this.Type = type;
+                               this.Getter = get;
+                               this.Setter = set;
+                       }
+               }
+
                static Indexers ()
                {
                        map = new Hashtable ();
@@ -7011,7 +7622,7 @@ namespace Mono.CSharp {
 
                Indexers ()
                {
-                       properties = new ArrayList ();
+                       Properties = new ArrayList ();
                }
                                
                void Append (MemberInfo [] mi)
@@ -7021,7 +7632,7 @@ namespace Mono.CSharp {
                                
                                get = property.GetGetMethod (true);
                                set = property.GetSetMethod (true);
-                               properties.Add (new Pair (get, set));
+                               Properties.Add (new Indexer (property.PropertyType, get, set));
                        }
                }
 
@@ -7043,7 +7654,7 @@ namespace Mono.CSharp {
                static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
                {
                        Indexers ix = (Indexers) map [lookup_type];
-                       
+
                        if (ix != null)
                                return ix;
 
@@ -7061,9 +7672,13 @@ namespace Mono.CSharp {
                                copy = copy.BaseType;
                        }
 
-                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+                       if (!lookup_type.IsInterface)
+                               return ix;
+
+                       TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
                        if (ifaces != null) {
-                               foreach (Type itype in ifaces) {
+                               foreach (TypeExpr iface in ifaces) {
+                                       Type itype = iface.Type;
                                        MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
                                        if (mi != null){
                                                if (ix == null)
@@ -7136,10 +7751,10 @@ namespace Mono.CSharp {
                        ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
                        if (ilist != null) {
                                found_any = true;
-                               if (ilist.properties != null) {
-                                       foreach (Pair o in ilist.properties) {
-                                               if (o.First != null)
-                                                       AllGetters.Add(o.First);
+                               if (ilist.Properties != null) {
+                                       foreach (Indexers.Indexer ix in ilist.Properties) {
+                                               if (ix.Getter != null)
+                                                       AllGetters.Add(ix.Getter);
                                        }
                                }
                        }
@@ -7193,17 +7808,15 @@ namespace Mono.CSharp {
                        if (!CommonResolve (ec))
                                return null;
 
-                       Type right_type = right_side.Type;
-
                        bool found_any = false, found_any_setters = false;
 
                        Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
                        if (ilist != null) {
                                found_any = true;
-                               if (ilist.properties != null) {
-                                       foreach (Pair o in ilist.properties) {
-                                               if (o.Second != null)
-                                                       AllSetters.Add(o.Second);
+                               if (ilist.Properties != null) {
+                                       foreach (Indexers.Indexer ix in ilist.Properties) {
+                                               if (ix.Setter != null)
+                                                       AllSetters.Add(ix.Setter);
                                        }
                                }
                        }
@@ -7247,10 +7860,9 @@ namespace Mono.CSharp {
                        // Now look for the actual match in the list of indexers to set our "return" type
                        //
                        type = TypeManager.void_type;   // default value
-                       foreach (Pair t in ilist.properties){
-                               if (t.Second == set){
-                                       if (t.First != null)
-                                               type = ((MethodInfo) t.First).ReturnType;
+                       foreach (Indexers.Indexer ix in ilist.Properties){
+                               if (ix.Setter == set){
+                                       type = ix.Type;
                                        break;
                                }
                        }
@@ -7340,9 +7952,9 @@ namespace Mono.CSharp {
                        Expression left;
                        
                        if (ec.IsStatic)
-                               left = new TypeExpr (base_type, loc);
+                               left = new TypeExpression (base_type, loc);
                        else
-                               left = ec.This;
+                               left = ec.GetThis (loc);
                        
                        e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
 
@@ -7375,7 +7987,7 @@ namespace Mono.CSharp {
 
                protected override bool CommonResolve (EmitContext ec)
                {
-                       instance_expr = ec.This;
+                       instance_expr = ec.GetThis (loc);
 
                        current_type = ec.ContainerType.BaseType;
                        indexer_type = current_type;
@@ -7476,7 +8088,7 @@ namespace Mono.CSharp {
        //   the type specification, we just use this to construct the type
        //   one bit at a time.
        // </summary>
-       public class ComposedCast : Expression {
+       public class ComposedCast : TypeExpr {
                Expression left;
                string dim;
                
@@ -7487,7 +8099,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
                        Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
                        if (ltype == null)
@@ -7528,19 +8140,10 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       return ResolveAsTypeStep (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("This should never be called");
-               }
-
-               public override string ToString ()
-               {
-                       return left + dim;
+               public override string Name {
+                       get {
+                               return left + dim;
+                       }
                }
        }
 
@@ -7553,7 +8156,7 @@ namespace Mono.CSharp {
                
                public ArrayPtr (Expression array, Location l)
                {
-                       Type array_type = array.Type.GetElementType ();
+                       Type array_type = TypeManager.GetElementType (array.Type);
 
                        this.array = array;
 
@@ -7568,7 +8171,7 @@ namespace Mono.CSharp {
                        
                        array.Emit (ec);
                        IntLiteral.EmitInt (ig, 0);
-                       ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());
+                       ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -7640,9 +8243,10 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
-                       if (ec.InCatch || ec.InFinally){
+                       if (ec.CurrentBranching.InCatch () ||
+                           ec.CurrentBranching.InFinally (true)) {
                                Error (255,
-                                             "stackalloc can not be used in a catch or finally block");
+                                      "stackalloc can not be used in a catch or finally block");
                                return null;
                        }