Bug fixes and a couple of optimizations (used a nice profiler to find
[mono.git] / mcs / mcs / expression.cs
index 13067a7ab111e0707cb082a54501e11052785b32..bcb07955575522d34ff9611621962558a55ed8f6 100755 (executable)
@@ -125,7 +125,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Returns a stringified representation of the Operator
                /// </summary>
-               string OperName ()
+               static public string OperName (Operator oper)
                {
                        switch (oper){
                        case Operator.UnaryPlus:
@@ -159,10 +159,10 @@ namespace Mono.CSharp {
                        oper_names [(int) Operator.AddressOf] = "op_AddressOf";
                }
 
-               void error23 (Type t)
+               void Error23 (Type t)
                {
                        Report.Error (
-                               23, loc, "Operator " + OperName () +
+                               23, loc, "Operator " + OperName (oper) +
                                " cannot be applied to operand of type `" +
                                TypeManager.CSharpName (t) + "'");
                }
@@ -210,7 +210,7 @@ namespace Mono.CSharp {
                                
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
                                
@@ -223,7 +223,7 @@ namespace Mono.CSharp {
                                      (expr_type == TypeManager.int64_type) ||
                                      (expr_type == TypeManager.uint64_type) ||
                                      (expr_type.IsSubclassOf (TypeManager.enum_type)))){
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
 
@@ -244,9 +244,8 @@ namespace Mono.CSharp {
                                if (expr_type == TypeManager.uint64_type)
                                        return new ULongConstant (~ ((ULongConstant) e).Value);
 
-                               throw new Exception (
-                                       "FIXME: Implement constant OnesComplement of:" +
-                                       expr_type);
+                               Error23 (expr_type);
+                               return null;
                        }
                        throw new Exception ("Can not constant fold");
                }
@@ -263,17 +262,14 @@ namespace Mono.CSharp {
                        
                        op_name = oper_names [(int) oper];
 
-                       mg = MemberLookup (ec, expr_type, op_name, false, loc);
-                       
-                       if (mg == null && expr_type.BaseType != null)
-                               mg = MemberLookup (ec, expr_type.BaseType, op_name, false, loc);
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
                        
                        if (mg != null) {
                                Expression e = StaticCallExpr.MakeSimpleCall (
                                        ec, (MethodGroupExpr) mg, expr, loc);
 
                                if (e == null){
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
                                
@@ -294,7 +290,7 @@ namespace Mono.CSharp {
 
                        if (oper == Operator.LogicalNot){
                                if (expr_type != TypeManager.bool_type) {
-                                       error23 (expr.Type);
+                                       Error23 (expr.Type);
                                        return null;
                                }
                                
@@ -308,7 +304,7 @@ namespace Mono.CSharp {
                                      (expr_type == TypeManager.int64_type) ||
                                      (expr_type == TypeManager.uint64_type) ||
                                      (expr_type.IsSubclassOf (TypeManager.enum_type)))){
-                                       error23 (expr.Type);
+                                       Error23 (expr.Type);
                                        return null;
                                }
                                type = expr_type;
@@ -361,7 +357,7 @@ namespace Mono.CSharp {
                                        // -92233720368547758087 (-2^63) to be wrote as
                                        // decimal integer literal.
                                        //
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
 
@@ -391,7 +387,7 @@ namespace Mono.CSharp {
                                        return this;
                                }
 
-                               error23 (expr_type);
+                               Error23 (expr_type);
                                return null;
                        }
 
@@ -400,12 +396,50 @@ namespace Mono.CSharp {
                                        Error (211, loc, "Cannot take the address of non-variables");
                                        return null;
                                }
-                               type = Type.GetType (expr.Type.ToString () + "*");
 
+                               if (!ec.InUnsafe) {
+                                       UnsafeError (loc); 
+                                       return null;
+                               }
+
+                               if (!TypeManager.VerifyUnManaged (expr.Type, loc)){
+                                       return null;
+                               }
+                               
+                               //
+                               // This construct is needed because dynamic types
+                               // are not known by Type.GetType, so we have to try then to use
+                               // ModuleBuilder.GetType.
+                               //
+                               string ptr_type_name = expr.Type.FullName + "*";
+                               type = Type.GetType (ptr_type_name);
+                               if (type == null)
+                                       type = RootContext.ModuleBuilder.GetType (ptr_type_name);
+                               
                                return this;
                        }
+
+                       if (oper == Operator.Indirection){
+                               if (!ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+
+                               if (!expr_type.IsPointer){
+                                       Report.Error (
+                                               193, loc,
+                                               "The * or -> operator can only be applied to pointers");
+                                       return null;
+                               }
+
+                               //
+                               // We create an Indirection expression, because
+                               // it can implement the IMemoryLocation.
+                               // 
+                               return new Indirection (expr);
+                       }
                        
-                       Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+                       Error (187, loc, "No such operator '" + OperName (oper) + "' defined for type '" +
                               TypeManager.CSharpName (expr_type) + "'");
                        return null;
                }
@@ -447,12 +481,9 @@ namespace Mono.CSharp {
                                break;
                                
                        case Operator.AddressOf:
-                               ((IMemoryLocation)expr).AddressOf (ec);
+                               ((IMemoryLocation)expr).AddressOf (ec, AddressOp.LoadStore);
                                break;
                                
-                       case Operator.Indirection:
-                               throw new Exception ("Not implemented yet");
-                               
                        default:
                                throw new Exception ("This should not happen: Operator = "
                                                     + oper.ToString ());
@@ -470,9 +501,56 @@ namespace Mono.CSharp {
 
                        expr.Emit (ec);
                }
+
+               public override string ToString ()
+               {
+                       return "Unary (" + oper + ", " + expr + ")";
+               }
                
        }
 
+       //
+       // Unary operators are turned into Indirection expressions
+       // after semantic analysis (this is so we can take the address
+       // of an indirection).
+       //
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+               Expression expr;
+               
+               public Indirection (Expression expr)
+               {
+                       this.expr = expr;
+                       this.type = expr.Type.GetElementType ();
+                       eclass = ExprClass.Variable;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       expr.Emit (ec);
+                       LoadFromPtr (ec.ig, Type, false);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       expr.Emit (ec);
+                       source.Emit (ec);
+                       StoreFromPtr (ec.ig, type);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       expr.Emit (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // Born fully resolved
+                       //
+                       return this;
+               }
+       }
+       
        /// <summary>
        ///   Unary Mutator expressions (pre and post ++ and --)
        /// </summary>
@@ -511,16 +589,16 @@ namespace Mono.CSharp {
                        expr = e;
                }
 
-               string OperName ()
+               static string OperName (Mode mode)
                {
                        return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
                                "++" : "--";
                }
                
-               void error23 (Type t)
+               void Error23 (Type t)
                {
                        Report.Error (
-                               23, loc, "Operator " + OperName () + 
+                               23, loc, "Operator " + OperName (mode) + 
                                " cannot be applied to operand of type `" +
                                TypeManager.CSharpName (t) + "'");
                }
@@ -544,7 +622,8 @@ namespace Mono.CSharp {
                                (t == TypeManager.char_type) ||
                                (t.IsSubclassOf (TypeManager.enum_type)) ||
                                (t == TypeManager.float_type) ||
-                               (t == TypeManager.double_type);
+                               (t == TypeManager.double_type) ||
+                               (t.IsPointer && t != TypeManager.void_ptr_type);
                }
 
                Expression ResolveOperator (EmitContext ec)
@@ -562,10 +641,11 @@ namespace Mono.CSharp {
                        else 
                                op_name = "op_Decrement";
 
-                       mg = MemberLookup (ec, expr_type, op_name, false, loc);
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
 
                        if (mg == null && expr_type.BaseType != null)
-                               mg = MemberLookup (ec, expr_type.BaseType, op_name, false, loc);
+                               mg = MemberLookup (ec, expr_type.BaseType, op_name,
+                                                  MemberTypes.Method, AllBindingFlags, loc);
                        
                        if (mg != null) {
                                method = StaticCallExpr.MakeSimpleCall (
@@ -608,7 +688,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+                       Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
                               TypeManager.CSharpName (expr_type) + "'");
                        return null;
                }
@@ -623,8 +703,13 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                        return ResolveOperator (ec);
                }
-               
 
+               static int PtrTypeSize (Type t)
+               {
+                       return GetTypeSize (t.GetElementType ());
+               }
+               
+               
                //
                // FIXME: We need some way of avoiding the use of temp_storage
                // for some types of storage (parameters, local variables,
@@ -634,17 +719,33 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        IAssignMethod ia = (IAssignMethod) expr;
-
-                       if (temp_storage == null)
-                               temp_storage = new LocalTemporary (ec, expr.Type);
+                       Type expr_type = expr.Type;
                        
+                       if (temp_storage == null)
+                               temp_storage = new LocalTemporary (ec, expr_type);
+
                        switch (mode){
                        case Mode.PreIncrement:
                        case Mode.PreDecrement:
                                if (method == null){
                                        expr.Emit (ec);
 
-                                       ig.Emit (OpCodes.Ldc_I4_1);
+                                       if (expr_type == TypeManager.uint64_type ||
+                                           expr_type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Ldc_I8, 1L);
+                                       else if (expr_type == TypeManager.double_type)
+                                               ig.Emit (OpCodes.Ldc_R8, 1.0);
+                                       else if (expr_type == TypeManager.float_type)
+                                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
+                                       else if (expr_type.IsPointer){
+                                               int n = PtrTypeSize (expr_type);
+
+                                               if (n == 0)
+                                                       ig.Emit (OpCodes.Sizeof, expr_type);
+                                               else
+                                                       IntConstant.EmitInt (ig, n);
+                                       } else 
+                                               ig.Emit (OpCodes.Ldc_I4_1);
                                
                                        if (mode == Mode.PreDecrement)
                                                ig.Emit (OpCodes.Sub);
@@ -670,7 +771,22 @@ namespace Mono.CSharp {
                                        else
                                                ig.Emit (OpCodes.Dup);
 
-                                       ig.Emit (OpCodes.Ldc_I4_1);
+                                       if (expr_type == TypeManager.uint64_type ||
+                                           expr_type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Ldc_I8, 1L);
+                                       else if (expr_type == TypeManager.double_type)
+                                               ig.Emit (OpCodes.Ldc_R8, 1.0);
+                                       else if (expr_type == TypeManager.float_type)
+                                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
+                                       else if (expr_type.IsPointer){
+                                               int n = PtrTypeSize (expr_type);
+
+                                               if (n == 0)
+                                                       ig.Emit (OpCodes.Sizeof, expr_type);
+                                               else
+                                                       IntConstant.EmitInt (ig, n);
+                                       } else
+                                               ig.Emit (OpCodes.Ldc_I4_1);
                                
                                        if (mode == Mode.PostDecrement)
                                                ig.Emit (OpCodes.Sub);
@@ -711,7 +827,7 @@ namespace Mono.CSharp {
                public readonly string ProbeType;
                protected Expression expr;
                protected Type probe_type;
-               Location loc;
+               protected Location loc;
                
                public Probe (Expression expr, string probe_type, Location l)
                {
@@ -766,6 +882,23 @@ namespace Mono.CSharp {
                        if (e == null)
                                return null;
 
+                       if (RootContext.WarningLevel >= 1){
+                               if (expr.Type == probe_type || expr.Type.IsSubclassOf (probe_type)){
+                                       Report.Warning (
+                                               183, loc,
+                                               "The expression is always of type `" +
+                                               TypeManager.CSharpName (probe_type) + "'");
+                               }
+
+                               if (expr.Type != probe_type && !probe_type.IsSubclassOf (expr.Type)){
+                                       if (!probe_type.IsInterface)
+                                               Report.Warning (
+                                                       184, loc,
+                                                       "The expression is never of type `" +
+                                                       TypeManager.CSharpName (probe_type) + "'");
+                               }
+                       }
+                       
                        type = TypeManager.bool_type;
                        eclass = ExprClass.Value;
 
@@ -1171,7 +1304,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Returns a stringified representation of the Operator
                /// </summary>
-               string OperName ()
+               static string OperName (Operator oper)
                {
                        switch (oper){
                        case Operator.Multiply:
@@ -1222,7 +1355,17 @@ namespace Mono.CSharp {
 
                        return ConvertImplicit (ec, expr, target_type, new Location (-1));
                }
-               
+
+               public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
+               {
+                       Report.Error (
+                               34, loc, "Operator `" + OperName (oper) 
+                               + "' is ambiguous on operands of type `"
+                               + TypeManager.CSharpName (l) + "' "
+                               + "and `" + TypeManager.CSharpName (r)
+                               + "'");
+               }
+
                //
                // Note that handling the case l == Decimal || r == Decimal
                // is taken care of by the Step 1 Operator Overload resolution.
@@ -1242,8 +1385,8 @@ namespace Mono.CSharp {
                                type = TypeManager.double_type;
                        } else if (l == TypeManager.float_type || r == TypeManager.float_type){
                                //
-                               // if either operand is of type float, th eother operand is
-                               // converd to type float.
+                               // if either operand is of type float, thother operand is
+                               // converted to type float.
                                //
                                if (r != TypeManager.double_type)
                                        right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
@@ -1258,11 +1401,12 @@ namespace Mono.CSharp {
                                // converted to type ulong.  or an error ocurrs if the other
                                // operand is of type sbyte, short, int or long
                                //
-                               
                                if (l == TypeManager.uint64_type){
                                        if (r != TypeManager.uint64_type){
                                                if (right is IntConstant){
-                                                       e = TryImplicitIntConversion(l, (IntConstant) right);
+                                                       IntConstant ic = (IntConstant) right;
+                                                       
+                                                       e = TryImplicitIntConversion (l, ic);
                                                        if (e != null)
                                                                right = e;
                                                } else if (right is LongConstant){
@@ -1270,6 +1414,10 @@ namespace Mono.CSharp {
 
                                                        if (ll > 0)
                                                                right = new ULongConstant ((ulong) ll);
+                                               } else {
+                                                       e = ImplicitNumericConversion (ec, right, l, loc);
+                                                       if (e != null)
+                                                               right = e;
                                                }
                                        }
                                        other = right.Type;
@@ -1280,9 +1428,13 @@ namespace Mono.CSharp {
                                                        left = e;
                                        } else if (left is LongConstant){
                                                long ll = ((LongConstant) left).Value;
-
+                                               
                                                if (ll > 0)
                                                        left = new ULongConstant ((ulong) ll);
+                                       } else {
+                                               e = ImplicitNumericConversion (ec, left, r, loc);
+                                               if (e != null)
+                                                       left = e;
                                        }
                                        other = left.Type;
                                }
@@ -1290,15 +1442,8 @@ namespace Mono.CSharp {
                                if ((other == TypeManager.sbyte_type) ||
                                    (other == TypeManager.short_type) ||
                                    (other == TypeManager.int32_type) ||
-                                   (other == TypeManager.int64_type)){
-                                       string oper = OperName ();
-                                       
-                                       Error (34, loc, "Operator `" + OperName ()
-                                              + "' is ambiguous on operands of type `"
-                                              + TypeManager.CSharpName (l) + "' "
-                                              + "and `" + TypeManager.CSharpName (r)
-                                              + "'");
-                               }
+                                   (other == TypeManager.int64_type))
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
                                type = TypeManager.uint64_type;
                        } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
                                //
@@ -1319,10 +1464,33 @@ namespace Mono.CSharp {
                                //
                                Type other = null;
                                
-                               if (l == TypeManager.uint32_type)
+                               if (l == TypeManager.uint32_type){
+                                       if (right is IntConstant){
+                                               IntConstant ic = (IntConstant) right;
+                                               int val = ic.Value;
+                                               
+                                               if (val >= 0)
+                                                       right = new UIntConstant ((uint) val);
+
+                                               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)
+                                                       left = new UIntConstant ((uint) val);
+
+                                               type = r;
+                                               return true;
+                                       }
+                                       
                                        other = l;
+                               }
 
                                if ((other == TypeManager.sbyte_type) ||
                                    (other == TypeManager.short_type) ||
@@ -1366,15 +1534,25 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               void error19 ()
+               static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
                {
                        Error (19, loc,
-                              "Operator " + OperName () + " cannot be applied to operands of type `" +
-                              TypeManager.CSharpName (left.Type) + "' and `" +
-                              TypeManager.CSharpName (right.Type) + "'");
-                                                    
+                              "Operator " + name + " cannot be applied to operands of type `" +
+                              TypeManager.CSharpName (l) + "' and `" +
+                              TypeManager.CSharpName (r) + "'");
                }
                
+               void error19 ()
+               {
+                       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);
+               }
+                                       
                Expression CheckShiftArguments (EmitContext ec)
                {
                        Expression e;
@@ -1413,15 +1591,14 @@ namespace Mono.CSharp {
                        
                        string op = "op_" + oper;
 
-                       left_expr = MemberLookup (ec, l, op, false, loc);
-                       if (left_expr == null && l.BaseType != null)
-                               left_expr = MemberLookup (ec, l.BaseType, op, false, loc);
-                       
-                       right_expr = MemberLookup (ec, r, op, false, loc);
-                       if (right_expr == null && r.BaseType != null)
-                               right_expr = MemberLookup (ec, r.BaseType, op, false, loc);
-                       
-                       MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
+                       MethodGroupExpr union;
+                       left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
+                       if (r != l){
+                               right_expr = MemberLookup (
+                                       ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
+                               union = Invocation.MakeUnionSet (left_expr, right_expr);
+                       } else
+                               union = (MethodGroupExpr) left_expr;
                        
                        if (union != null) {
                                Arguments = new ArrayList ();
@@ -1431,6 +1608,7 @@ namespace Mono.CSharp {
                                method = Invocation.OverloadResolve (ec, union, Arguments, loc);
                                if (method != null) {
                                        MethodInfo mi = (MethodInfo) method;
+
                                        type = mi.ReturnType;
                                        return this;
                                } else {
@@ -1451,6 +1629,12 @@ namespace Mono.CSharp {
                                // If any of the arguments is a string, cast to string
                                //
                                if (l == TypeManager.string_type){
+                                       
+                                       if (r == TypeManager.void_type) {
+                                               error19 ();
+                                               return null;
+                                       }
+                                       
                                        if (r == TypeManager.string_type){
                                                if (left is Constant && right is Constant){
                                                        StringConstant ls = (StringConstant) left;
@@ -1478,12 +1662,18 @@ namespace Mono.CSharp {
                                        
                                } else if (r == TypeManager.string_type){
                                        // object + string
+
+                                       if (l == TypeManager.void_type) {
+                                               error19 ();
+                                               return null;
+                                       }
+                                       
                                        method = TypeManager.string_concat_object_object;
+                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
                                        Arguments = new ArrayList ();
                                        Arguments.Add (new Argument (left, Argument.AType.Expression));
                                        Arguments.Add (new Argument (right, Argument.AType.Expression));
 
-                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
                                        type = TypeManager.string_type;
 
                                        return this;
@@ -1507,6 +1697,38 @@ namespace Mono.CSharp {
                                        type = l;
                                        return this;
                                }
+
+                               //
+                               // Pointer arithmetic:
+                               //
+                               // T* operator + (T* x, int y);
+                               // T* operator + (T* x, uint y);
+                               // T* operator + (T* x, long y);
+                               // T* operator + (T* x, ulong y);
+                               //
+                               // T* operator + (int y,   T* x);
+                               // T* operator + (uint y,  T *x);
+                               // T* operator + (long y,  T *x);
+                               // T* operator + (ulong y, T *x);
+                               //
+                               // T* operator - (T* x, int y);
+                               // T* operator - (T* x, uint y);
+                               // T* operator - (T* x, long y);
+                               // T* operator - (T* x, ulong y);
+                               //
+                               // long operator - (T* x, T *y)
+                               //
+                               if (l.IsPointer){
+                                       if (r.IsPointer && oper == Operator.Subtraction){
+                                               if (r == l)
+                                                       return new PointerArithmetic (
+                                                               false, left, right, TypeManager.int64_type);
+                                       } else if (is_32_or_64 (r))
+                                               return new PointerArithmetic (
+                                                       oper == Operator.Addition, left, right, l);
+                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
+                                       return new PointerArithmetic (
+                                               true, right, left, r);
                        }
                        
                        //
@@ -1599,6 +1821,18 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       //
+                       // Pointer comparison
+                       //
+                       if (l.IsPointer && r.IsPointer){
+                               if (oper == Operator.Equality || oper == Operator.Inequality ||
+                                   oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
+                                   oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+                       }
+                       
                        //
                        // We are dealing with numbers
                        //
@@ -1644,56 +1878,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               /// <summary>
-               ///   Constant expression reducer for binary operations
-               /// </summary>
-               public Expression ConstantFold (EmitContext ec)
-               {
-                       object l = ((Constant) left).GetValue ();
-                       object r = ((Constant) right).GetValue ();
-                       
-                       if (l is string && r is string)
-                               return new StringConstant ((string) l + (string) r);
-
-                       Type result_type = null;
-
-                       //
-                       // Enumerator folding
-                       //
-                       if (left.Type == right.Type && left is EnumConstant)
-                               result_type = left.Type;
-
-                       switch (oper){
-                       case Operator.BitwiseOr:
-                               if ((l is int) && (r is int)){
-                                       IntConstant v;
-                                       int res = (int)l | (int)r;
-                                       
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               }
-                               break;
-                               
-                       case Operator.BitwiseAnd:
-                               if ((l is int) && (r is int)){
-                                       IntConstant v;
-                                       int res = (int)l & (int)r;
-                                       
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               }
-                               break;
-                       }
-                                       
-                       return null;
-               }
-               
                public override Expression DoResolve (EmitContext ec)
                {
                        left = left.Resolve (ec);
@@ -1714,10 +1898,8 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
 
                        if (left is Constant && right is Constant){
-                               //
-                               // This is temporary until we do the full folding
-                               //
-                               Expression e = ConstantFold (ec);
+                               Expression e = ConstantFold.BinaryFold (
+                                       ec, oper, (Constant) left, (Constant) right, loc);
                                if (e != null)
                                        return e;
                        }
@@ -1998,6 +2180,74 @@ namespace Mono.CSharp {
                }
        }
 
+       public class PointerArithmetic : Expression {
+               Expression left, right;
+               bool is_add;
+
+               //
+               // We assume that `l' is always a pointer
+               //
+               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t)
+               {
+                       type = t;
+                       eclass = ExprClass.Variable;
+                       left = l;
+                       right = r;
+                       is_add = is_addition;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Type op_type = left.Type;
+                       ILGenerator ig = ec.ig;
+                       int size = GetTypeSize (op_type.GetElementType ());
+                       
+                       if (right.Type.IsPointer){
+                               //
+                               // handle (pointer - pointer)
+                               //
+                               left.Emit (ec);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Sub);
+
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Div);
+                               }
+                               ig.Emit (OpCodes.Conv_I8);
+                       } else {
+                               //
+                               // handle + and - on (pointer op int)
+                               //
+                               left.Emit (ec);
+                               ig.Emit (OpCodes.Conv_I);
+                               right.Emit (ec);
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Mul);
+                               }
+                               if (is_add)
+                                       ig.Emit (OpCodes.Add);
+                               else
+                                       ig.Emit (OpCodes.Sub);
+                       }
+               }
+       }
+       
        /// <summary>
        ///   Implements the ternary conditiona operator (?:)
        /// </summary>
@@ -2045,21 +2295,44 @@ namespace Mono.CSharp {
                        if (expr == null || trueExpr == null || falseExpr == null)
                                return null;
 
+                       eclass = ExprClass.Value;
                        if (trueExpr.Type == falseExpr.Type)
                                type = trueExpr.Type;
                        else {
                                Expression conv;
+                               Type true_type = trueExpr.Type;
+                               Type false_type = falseExpr.Type;
 
+                               if (trueExpr is NullLiteral){
+                                       type = false_type;
+                                       return this;
+                               } else if (falseExpr is NullLiteral){
+                                       type = true_type;
+                                       return this;
+                               }
+                               
                                //
                                // First, if an implicit conversion exists from trueExpr
                                // to falseExpr, then the result type is of type falseExpr.Type
                                //
-                               conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
+                               conv = ConvertImplicit (ec, trueExpr, false_type, loc);
                                if (conv != null){
-                                       type = falseExpr.Type;
+                                       //
+                                       // Check if both can convert implicitl to each other's type
+                                       //
+                                       if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){
+                                               Report.Error (
+                                                       172, loc,
+                                                       "Can not compute type of conditional expression " +
+                                                       "as `" + TypeManager.CSharpName (trueExpr.Type) +
+                                                       "' and `" + TypeManager.CSharpName (falseExpr.Type) +
+                                                       "' convert implicitly to each other");
+                                               return null;
+                                       }
+                                       type = false_type;
                                        trueExpr = conv;
-                               } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
-                                       type = trueExpr.Type;
+                               } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){
+                                       type = true_type;
                                        falseExpr = conv;
                                } else {
                                        Error (173, loc, "The type of the conditional expression can " +
@@ -2079,7 +2352,6 @@ namespace Mono.CSharp {
                                        return falseExpr;
                        }
 
-                       eclass = ExprClass.Value;
                        return this;
                }
 
@@ -2132,15 +2404,6 @@ namespace Mono.CSharp {
                        if (Block.IsConstant (Name)) {
                                Expression e = Block.GetConstantExpression (Name);
 
-                               e = e.Resolve (ec);
-                               if (e == null)  
-                                       return null;
-
-                               if (!(e is Constant)) {
-                                       Report.Error (150, loc, "A constant value is expected");
-                                       return null;
-                               }
-
                                vi.Used = true;
                                return e;
                        }
@@ -2248,13 +2511,15 @@ namespace Mono.CSharp {
                        Store (ig, vi.Idx);
                }
                
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        VariableInfo vi = VariableInfo;
                        int idx = vi.Idx;
 
-                       vi.Used = true;
-                       vi.Assigned = true;
+                       if ((mode & AddressOp.Load) != 0)
+                               vi.Used = true;
+                       if ((mode & AddressOp.Store) != 0)
+                               vi.Assigned = true;
                        
                        if (idx <= 255)
                                ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
@@ -2271,7 +2536,7 @@ namespace Mono.CSharp {
                Parameters pars;
                String name;
                int idx;
-               bool is_ref;
+               public bool is_ref;
                
                public ParameterReference (Parameters pars, int idx, string name)
                {
@@ -2297,10 +2562,30 @@ namespace Mono.CSharp {
                {
                        type = pars.GetParameterInfo (ec.TypeContainer, idx, out is_ref);
                        eclass = ExprClass.Variable;
-                       
+
                        return this;
                }
 
+               //
+               // This method is used by parameters that are references, that are
+               // being passed as references:  we only want to pass the pointer (that
+               // is already stored in the parameter, not the address of the pointer,
+               // and not the value of the variable).
+               //
+               public void EmitLoad (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+                       
+                       if (arg_idx <= 255)
+                               ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
+                       else
+                               ig.Emit (OpCodes.Ldarg, arg_idx);
+               }
+               
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
@@ -2321,32 +2606,8 @@ namespace Mono.CSharp {
                        // If we are a reference, we loaded on the stack a pointer
                        // Now lets load the real value
                        //
-
-                       if (type == TypeManager.int32_type)
-                               ig.Emit (OpCodes.Ldind_I4);
-                       else if (type == TypeManager.uint32_type)
-                               ig.Emit (OpCodes.Ldind_U4);
-                       else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
-                               ig.Emit (OpCodes.Ldind_I8);
-                       else if (type == TypeManager.char_type)
-                               ig.Emit (OpCodes.Ldind_U2);
-                       else if (type == TypeManager.short_type)
-                               ig.Emit (OpCodes.Ldind_I2);
-                       else if (type == TypeManager.ushort_type)
-                               ig.Emit (OpCodes.Ldind_U2);
-                       else if (type == TypeManager.float_type)
-                               ig.Emit (OpCodes.Ldind_R4);
-                       else if (type == TypeManager.double_type)
-                               ig.Emit (OpCodes.Ldind_R8);
-                       else if (type == TypeManager.byte_type)
-                               ig.Emit (OpCodes.Ldind_U1);
-                       else if (type == TypeManager.sbyte_type)
-                               ig.Emit (OpCodes.Ldind_I1);
-                       else if (type == TypeManager.intptr_type)
-                               ig.Emit (OpCodes.Ldind_I);
-                       else
-                               ig.Emit (OpCodes.Ldind_Ref);
-               }
+                       LoadFromPtr (ig, type, true);
+               }
 
                public void EmitAssign (EmitContext ec, Expression source)
                {
@@ -2366,25 +2627,9 @@ namespace Mono.CSharp {
                        
                        source.Emit (ec);
 
-                       if (is_ref){
-                               if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
-                                       ig.Emit (OpCodes.Stind_I4);
-                               else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
-                                       ig.Emit (OpCodes.Stind_I8);
-                               else if (type == TypeManager.char_type || type == TypeManager.short_type ||
-                                       type == TypeManager.ushort_type)
-                                       ig.Emit (OpCodes.Stind_I2);
-                               else if (type == TypeManager.float_type)
-                                       ig.Emit (OpCodes.Stind_R4);
-                               else if (type == TypeManager.double_type)
-                                       ig.Emit (OpCodes.Stind_R8);
-                               else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type)
-                                       ig.Emit (OpCodes.Stind_I1);
-                               else if (type == TypeManager.intptr_type)
-                                       ig.Emit (OpCodes.Stind_I);
-                               else
-                                       ig.Emit (OpCodes.Stind_Ref);
-                       } else {
+                       if (is_ref)
+                               StoreFromPtr (ig, type);
+                       else {
                                if (arg_idx <= 255)
                                        ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
                                else
@@ -2393,7 +2638,7 @@ namespace Mono.CSharp {
                        
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        int arg_idx = idx;
 
@@ -2444,10 +2689,7 @@ namespace Mono.CSharp {
 
                public Parameter.Modifier GetParameterModifier ()
                {
-                       if (ArgType == AType.Ref)
-                               return Parameter.Modifier.REF;
-
-                       if (ArgType == AType.Out)
+                       if (ArgType == AType.Ref || ArgType == AType.Out)
                                return Parameter.Modifier.OUT;
 
                        return Parameter.Modifier.NONE;
@@ -2468,9 +2710,20 @@ namespace Mono.CSharp {
                                return expr != null;
 
                        if (expr.eclass != ExprClass.Variable){
-                               Report.Error (206, loc,
-                                             "A property or indexer can not be passed as an out or ref " +
-                                             "parameter");
+                               //
+                               // We just probe to match the CSC output
+                               //
+                               if (expr.eclass == ExprClass.PropertyAccess ||
+                                   expr.eclass == ExprClass.IndexerAccess){
+                                       Report.Error (
+                                               206, loc,
+                                               "A property or indexer can not be passed as an out or ref " +
+                                               "parameter");
+                               } else {
+                                       Report.Error (
+                                               1510, loc,
+                                               "An lvalue is required as an argument to out or ref");
+                               }
                                return false;
                        }
                                
@@ -2479,9 +2732,30 @@ namespace Mono.CSharp {
 
                public void Emit (EmitContext ec)
                {
-                       if (ArgType == AType.Ref || ArgType == AType.Out)
-                               ((IMemoryLocation)expr).AddressOf (ec);
-                       else
+                       //
+                       // Ref and Out parameters need to have their addresses taken.
+                       //
+                       // ParameterReferences might already be references, so we want
+                       // to pass just the value
+                       //
+                       if (ArgType == AType.Ref || ArgType == AType.Out){
+                               AddressOp mode = AddressOp.Store;
+
+                               if (ArgType == AType.Ref)
+                                       mode |= AddressOp.Load;
+                               
+                               if (expr is ParameterReference){
+                                       ParameterReference pr = (ParameterReference) expr;
+
+                                       if (pr.is_ref)
+                                               pr.EmitLoad (ec);
+                                       else {
+                                               
+                                               pr.AddressOf (ec, mode);
+                                       }
+                               } else
+                                       ((IMemoryLocation)expr).AddressOf (ec, mode);
+                       } else
                                expr.Emit (ec);
                }
        }
@@ -2495,7 +2769,8 @@ namespace Mono.CSharp {
 
                Expression expr;
                MethodBase method = null;
-                       
+               bool is_base;
+               
                static Hashtable method_parameter_cache;
 
                static Invocation ()
@@ -2550,51 +2825,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   Tells whether a user defined conversion from Type `from' to
-               ///   Type `to' exists.
-               ///
-               ///   FIXME: we could implement a cache here. 
-               /// </summary>
-               static bool ConversionExists (EmitContext ec, Type from, Type to, Location loc)
-               {
-                       // Locate user-defined implicit operators
-
-                       Expression mg;
-                       
-                       mg = MemberLookup (ec, to, "op_Implicit", false, loc);
-
-                       if (mg != null) {
-                               MethodGroupExpr me = (MethodGroupExpr) mg;
-                               
-                               for (int i = me.Methods.Length; i > 0;) {
-                                       i--;
-                                       MethodBase mb = me.Methods [i];
-                                       ParameterData pd = GetParameterData (mb);
-                                       
-                                       if (from == pd.ParameterType (0))
-                                               return true;
-                               }
-                       }
-
-                       mg = MemberLookup (ec, from, "op_Implicit", false, loc);
-
-                       if (mg != null) {
-                               MethodGroupExpr me = (MethodGroupExpr) mg;
-
-                               for (int i = me.Methods.Length; i > 0;) {
-                                       i--;
-                                       MethodBase mb = me.Methods [i];
-                                       MethodInfo mi = (MethodInfo) mb;
-                                       
-                                       if (mi.ReturnType == to)
-                                               return true;
-                               }
-                       }
-                       
-                       return false;
-               }
-               
                /// <summary>
                ///  Determines "better conversion" as specified in 7.4.2.3
                ///  Returns : 1 if a->p is better
@@ -2676,20 +2906,16 @@ namespace Mono.CSharp {
                        }
 
                        if (q == null) {
-
-                               Expression tmp;
-
-                               tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
+                               Expression tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
                                
                                if (tmp != null)
                                        return 1;
                                else
                                        return 0;
-
                        }
 
-                       if (ConversionExists (ec, p, q, loc) == true &&
-                           ConversionExists (ec, q, p, loc) == false)
+                       if (StandardConversionExists (p, q) == true &&
+                           StandardConversionExists (q, p) == false)
                                return 1;
 
                        if (p == TypeManager.sbyte_type)
@@ -2735,25 +2961,32 @@ namespace Mono.CSharp {
                        else
                                argument_count = args.Count;
 
-                       if (candidate_pd.Count == 0 && argument_count == 0)
+                       int cand_count = candidate_pd.Count;
+
+                       if (cand_count == 0 && argument_count == 0)
                                return 1;
 
-                       if (candidate_pd.ParameterModifier (candidate_pd.Count - 1) != Parameter.Modifier.PARAMS)
-                               if (candidate_pd.Count != argument_count)
+                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+                               if (cand_count != argument_count)
                                        return 0;
                        
                        if (best == null) {
                                int x = 0;
+
+                               if (argument_count == 0 && cand_count == 1 &&
+                                   candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
+                                       return 1;
+                               
                                for (int j = argument_count; j > 0;) {
                                        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 ();
-                                       
+
                                        x = BetterConversion (ec, a, t, null, loc);
                                        
                                        if (x <= 0)
@@ -2788,9 +3021,9 @@ namespace Mono.CSharp {
                                
                                x = BetterConversion (ec, a, ct, bt, loc);
                                y = BetterConversion (ec, a, bt, ct, loc);
-                                                     
+
                                if (x < y)
-                                       break;
+                                       return 0;
                                
                                rating1 += x;
                                rating2 += y;
@@ -2804,7 +3037,12 @@ namespace Mono.CSharp {
 
                public static string FullMethodDesc (MethodBase mb)
                {
-                       StringBuilder sb = new StringBuilder (mb.Name);
+                       string ret_type = "";
+
+                       if (mb is MethodInfo)
+                               ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
+                       
+                       StringBuilder sb = new StringBuilder (ret_type + " " + mb.Name);
                        ParameterData pd = GetParameterData (mb);
 
                        int count = pd.Count;
@@ -2912,16 +3150,39 @@ namespace Mono.CSharp {
                        
                        if (pd_count - 1 > arg_count)
                                return false;
-
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               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. So, we now check if the element type
-                       // of the params array is compatible with each argument type
-                       //
+                       // is less than or equal to the argument count.
+
+                       for (int i = 0; i < pd_count - 1; ++i) {
+
+                               Argument a = (Argument) arguments [i];
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier ();
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i);
+
+                               if (a_mod == p_mod) {
+                                       
+                                       if (a_mod == Parameter.Modifier.NONE)
+                                               if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
+                                                       return false;
+                                                                               
+                                       if (a_mod == Parameter.Modifier.REF ||
+                                           a_mod == Parameter.Modifier.OUT)
+                                               if (pd.ParameterType (i) != a.Type)
+                                                       return false;
+                               } else
+                                       return false;
+                               
+                       }
 
                        Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
 
-                       for (int i = pd_count - 1; i < arg_count - 1; i++) {
+                       for (int i = pd_count - 1; i < arg_count; i++) {
                                Argument a = (Argument) arguments [i];
                                
                                if (!StandardConversionExists (a.Type, element_type))
@@ -2990,9 +3251,6 @@ namespace Mono.CSharp {
                ///   loc: The location if we want an error to be reported, or a Null
                ///        location for "probing" purposes.
                ///
-               ///   use_standard: controls whether OverloadResolve should use the 
-               ///   ConvertImplicit or ConvertImplicitStandard during overload resolution.
-               ///
                ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
                ///            that is the best match of me on Arguments.
                ///
@@ -3016,6 +3274,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                candidates.Add (candidate);
+
                                x = BetterFunction (ec, Arguments, candidate, method, false, loc);
                                
                                if (x == 0)
@@ -3095,19 +3354,29 @@ namespace Mono.CSharp {
 
                        for (int i = 0; i < candidates.Count; ++i) {
                                MethodBase candidate = (MethodBase) candidates [i];
-                               
+
                                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 (IsParamsMethodApplicable (Arguments, candidate) &&
+                                   IsApplicable (Arguments, method))
+                                       continue;
+                                       
                                int x = BetterFunction (ec, Arguments, method, candidate,
                                                        chose_params_expanded, loc);
 
                                if (x != 1) {
-                                       Console.WriteLine (candidate + "  " + method);
+                                       //Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));
+                                       //Console.WriteLine ("Best : " + FullMethodDesc (method));
                                        Report.Error (
                                                121, loc,
                                                "Ambiguous call when selecting function due to implicit casts");
-                                       return null;
+                                       return null;
                                }
                        }
                        
@@ -3157,6 +3426,9 @@ namespace Mono.CSharp {
                                if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
                                    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);
                                                Error (1502, loc,
                                                       "The best overloaded match for method '" + FullMethodDesc (method)+
                                                       "' has some invalid arguments");
@@ -3178,6 +3450,9 @@ namespace Mono.CSharp {
                        // First, resolve the expression that is used to
                        // trigger the invocation
                        //
+                       if (expr is BaseAccess)
+                               is_base = true;
+
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return null;
@@ -3222,6 +3497,13 @@ namespace Mono.CSharp {
                        if (method is MethodInfo)
                                type = ((MethodInfo)method).ReturnType;
 
+                       if (type.IsPointer){
+                               if (!ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+                       }
+                       
                        eclass = ExprClass.Value;
                        return this;
                }
@@ -3292,7 +3574,22 @@ namespace Mono.CSharp {
                        }
                }
 
-               public static void EmitCall (EmitContext ec,
+               /// <remarks>
+               ///   is_base tells whether we want to force the use of the `call'
+               ///   opcode instead of using callvirt.  Call is required to call
+               ///   a specific method, while callvirt will always use the most
+               ///   recent method in the vtable.
+               ///
+               ///   is_static tells whether this is an invocation on a static method
+               ///
+               ///   instance_expr is an expression that represents the instance
+               ///   it must be non-null if is_static is false.
+               ///
+               ///   method is the method to invoke.
+               ///
+               ///   Arguments is the list of arguments to pass to the method or constructor.
+               /// </remarks>
+               public static void EmitCall (EmitContext ec, bool is_base,
                                             bool is_static, Expression instance_expr,
                                             MethodBase method, ArrayList Arguments)
                {
@@ -3300,6 +3597,9 @@ namespace Mono.CSharp {
                        bool struct_call = false;
                                
                        if (!is_static){
+                               
+                               if (method.DeclaringType.IsValueType)
+                                       struct_call = true;
                                //
                                // If this is ourselves, push "this"
                                //
@@ -3315,9 +3615,8 @@ namespace Mono.CSharp {
                                                // reference-type with a value-type argument need
                                                // to have their value boxed.  
 
+                                               struct_call = true;
                                                if (method.DeclaringType.IsValueType){
-                                                       struct_call = true;
-
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -3327,7 +3626,7 @@ namespace Mono.CSharp {
                                                        // it.
                                                        if (instance_expr is IMemoryLocation){
                                                                ((IMemoryLocation)instance_expr).
-                                                                       AddressOf (ec);
+                                                                       AddressOf (ec, AddressOp.LoadStore);
                                                        }
                                                        else {
                                                                Type t = instance_expr.Type;
@@ -3349,7 +3648,7 @@ namespace Mono.CSharp {
                        if (Arguments != null)
                                EmitArguments (ec, method, Arguments);
 
-                       if (is_static || struct_call){
+                       if (is_static || struct_call || is_base){
                                if (method is MethodInfo)
                                        ig.Emit (OpCodes.Call, (MethodInfo) method);
                                else
@@ -3366,7 +3665,7 @@ namespace Mono.CSharp {
                {
                        MethodGroupExpr mg = (MethodGroupExpr) this.expr;
 
-                       EmitCall (ec, method.IsStatic, mg.InstanceExpression, method, Arguments);
+                       EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments);
                }
                
                public override void EmitStatement (EmitContext ec)
@@ -3440,8 +3739,7 @@ namespace Mono.CSharp {
                                return this;
                        
                        Expression ml;
-                       ml = MemberLookup (ec, type, ".ctor", false,
-                                          MemberTypes.Constructor, AllBindingFlags, loc);
+                       ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, AllBindingFlags, loc);
                        
                        if (! (ml is MethodGroupExpr)){
                                if (!is_struct){
@@ -3460,9 +3758,10 @@ namespace Mono.CSharp {
                                                        return null;
                                        }
                                }
-                               
+
                                method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
                                                                     Arguments, loc);
+                               
                        }
                        
                        if (method == null && !is_struct) {
@@ -3500,34 +3799,37 @@ namespace Mono.CSharp {
                //
                bool DoEmit (EmitContext ec, bool need_value_on_stack)
                {
-                       if (method == null){
+                       bool is_value_type = type.IsSubclassOf (TypeManager.value_type);
+                       ILGenerator ig = ec.ig;
+                       
+                       if (is_value_type){
                                IMemoryLocation ml;
 
                                if (value_target == null)
                                        value_target = new LocalTemporary (ec, type);
-                                               
+
                                ml = (IMemoryLocation) value_target;
-                               ml.AddressOf (ec);
-                       } else {
-                               Invocation.EmitArguments (ec, method, Arguments);
-                               ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
-                               return true;
+                               ml.AddressOf (ec, AddressOp.Store);
                        }
 
-                       //
-                       // It must be a value type, sanity check
-                       //
-                       if (value_target != null){
-                               ec.ig.Emit (OpCodes.Initobj, type);
+                       if (method != null)
+                               Invocation.EmitArguments (ec, method, Arguments);
+
+                       if (is_value_type){
+                               if (method == null)
+                                       ig.Emit (OpCodes.Initobj, type);
+                               else
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
 
                                if (need_value_on_stack){
                                        value_target.Emit (ec);
                                        return true;
                                }
                                return false;
+                       } else {
+                               ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+                               return true;
                        }
-
-                       throw new Exception ("No method and no value type");
                }
 
                public override void Emit (EmitContext ec)
@@ -3572,6 +3874,12 @@ namespace Mono.CSharp {
 
                Hashtable Bounds;
 
+               //
+               // The number of array initializers that we can handle
+               // via the InitializeArray method - through EmitStaticInitializers
+               //
+               int num_automatic_initializers;
+               
                public ArrayCreation (string requested_type, ArrayList exprs,
                                      string rank, ArrayList initializers, Location l)
                {
@@ -3584,7 +3892,6 @@ namespace Mono.CSharp {
 
                        foreach (Expression e in exprs)
                                Arguments.Add (new Argument (e, Argument.AType.Expression));
-
                }
 
                public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
@@ -3682,9 +3989,10 @@ namespace Mono.CSharp {
 
                                        if (conv is StringConstant)
                                                ArrayData.Add (conv);
-                                       else if (conv is Constant)
-                                               ArrayData.Add (((Constant) conv).GetValue ());
-                                       else
+                                       else if (conv is Constant) {
+                                               ArrayData.Add (conv);
+                                               num_automatic_initializers++;
+                                       } else
                                                ArrayData.Add (conv);
                                }
                        }
@@ -3763,6 +4071,10 @@ namespace Mono.CSharp {
                {
                        int arg_count;
 
+                       //
+                       // First step is to validate the initializers and fill
+                       // in any missing bits
+                       //
                        if (!ValidateInitializers (ec))
                                return null;
 
@@ -3799,10 +4111,10 @@ namespace Mono.CSharp {
                        IsBuiltinType = TypeManager.IsBuiltinType (type);
                        
                        if (IsBuiltinType) {
-                               
+
                                Expression ml;
                                
-                               ml = MemberLookup (ec, type, ".ctor", false, MemberTypes.Constructor,
+                               ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
                                                   AllBindingFlags, loc);
                                
                                if (!(ml is MethodGroupExpr)){
@@ -3817,7 +4129,7 @@ namespace Mono.CSharp {
                                }
                                
                                method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
-                               
+
                                if (method == null) {
                                        Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
                                                      "this argument list");
@@ -3828,6 +4140,7 @@ namespace Mono.CSharp {
                                return this;
                                
                        } else {
+
                                ModuleBuilder mb = RootContext.ModuleBuilder;
 
                                ArrayList args = new ArrayList ();
@@ -3849,7 +4162,7 @@ namespace Mono.CSharp {
                                
                                method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
                                                            arg_types);
-                               
+
                                if (method == null) {
                                        Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
                                                      "this argument list");
@@ -3866,29 +4179,14 @@ namespace Mono.CSharp {
                {
                        int factor;
                        byte [] data;
-
+                       byte [] element;
                        int count = ArrayData.Count;
 
-                       if (underlying_type == TypeManager.int32_type ||
-                           underlying_type == TypeManager.uint32_type ||
-                           underlying_type == TypeManager.float_type)
-                               factor = 4;
-                       else if (underlying_type == TypeManager.int64_type ||
-                                underlying_type == TypeManager.uint64_type ||
-                                underlying_type == TypeManager.double_type)
-                               factor = 8;
-                       else if (underlying_type == TypeManager.byte_type ||
-                                underlying_type == TypeManager.sbyte_type ||
-                                underlying_type == TypeManager.bool_type)      
-                               factor = 1;
-                       else if (underlying_type == TypeManager.short_type ||
-                                underlying_type == TypeManager.char_type ||
-                                underlying_type == TypeManager.ushort_type)
-                               factor = 2;
-                       else
+                       factor = GetTypeSize (underlying_type);
+                       if (factor == 0)
                                return null;
 
-                       data = new byte [count * factor];
+                       data = new byte [(count * factor + 4) & ~3];
                        int idx = 0;
                        
                        for (int i = 0; i < count; ++i) {
@@ -3896,66 +4194,95 @@ namespace Mono.CSharp {
 
                                if (v is EnumConstant)
                                        v = ((EnumConstant) v).Child;
+                               
+                               if (v is Constant && !(v is StringConstant))
+                                       v = ((Constant) v).GetValue ();
+                               else {
+                                       idx += factor;
+                                       continue;
+                               }
+                               
+                               if (underlying_type == TypeManager.int64_type){
+                                       if (!(v is Expression)){
+                                               long val = (long) v;
+                                               
+                                               for (int j = 0; j < factor; ++j) {
+                                                       data [idx + j] = (byte) (val & 0xFF);
+                                                       val = (val >> 8);
+                                               }
+                                       }
+                               } else if (underlying_type == TypeManager.uint64_type){
+                                       if (!(v is Expression)){
+                                               ulong val = (ulong) v;
 
-                               if (underlying_type == TypeManager.int64_type ||
-                                   underlying_type == TypeManager.uint64_type){
-                                       long val = 0;
-                                       if (!(v is Expression))
-                                               val = (long) v;
-
-                                       for (int j = 0; j < factor; ++j) {
-                                               data [idx + j] = (byte) (val & 0xFF);
-                                               val = (val >> 8);
+                                               for (int j = 0; j < factor; ++j) {
+                                                       data [idx + j] = (byte) (val & 0xFF);
+                                                       val = (val >> 8);
+                                               }
                                        }
                                } else if (underlying_type == TypeManager.float_type) {
-#if __MonoCS__
-#else
-                                       unsafe {
-                                               float val = 0;
-
-                                               if (!(v is Expression))
-                                                       val = (float) v;
-
-                                               byte *ptr = (byte *) &val;
-                                               
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((float) v);
+                                                       
                                                for (int j = 0; j < factor; ++j)
-                                                       data [idx + j] = (byte) ptr [j];
+                                                       data [idx + j] = element [j];
                                        }
-#endif
                                } else if (underlying_type == TypeManager.double_type) {
-#if __MonoCS__
-#else
-                                       unsafe {
-                                               double val = 0;
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((double) v);
 
-                                               if (!(v is Expression))
-                                                       val = (double) v;
-
-                                               byte *ptr = (byte *) &val;
-                                               
                                                for (int j = 0; j < factor; ++j)
-                                                       data [idx + j] = (byte) ptr [j];
+                                                       data [idx + j] = element [j];
                                        }
-#endif
                                } else if (underlying_type == TypeManager.char_type){
-                                       int val = (char) 0;
-
-                                       if (!(v is Expression))
-                                               v = (int) ((char) v);
+                                       if (!(v is Expression)){
+                                               int val = (int) ((char) v);
+                                               
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.short_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((short) v);
                                        
-                                       data [idx] = (byte) (val & 0xff);
-                                       data [idx+1] = (byte) (val >> 8);
-
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.ushort_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((ushort) v);
+                                       
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
                                } else if (underlying_type == TypeManager.int32_type) {
-                                       int val = 0;
+                                       if (!(v is Expression)){
+                                               int val = (int) v;
                                        
-                                       if (!(v is Expression))
-                                               val = (int) v;
+                                               data [idx]   = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) ((val >> 8) & 0xff);
+                                               data [idx+2] = (byte) ((val >> 16) & 0xff);
+                                               data [idx+3] = (byte) (val >> 24);
+                                       }
+                               } else if (underlying_type == TypeManager.uint32_type) {
+                                       if (!(v is Expression)){
+                                               uint val = (uint) v;
                                        
-                                       data [idx]   = (byte) (val & 0xff);
-                                       data [idx+1] = (byte) ((val >> 8) & 0xff);
-                                       data [idx+2] = (byte) ((val >> 16) & 0xff);
-                                       data [idx+3] = (byte) (val >> 24);
+                                               data [idx]   = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) ((val >> 8) & 0xff);
+                                               data [idx+2] = (byte) ((val >> 16) & 0xff);
+                                               data [idx+3] = (byte) (val >> 24);
+                                       }
+                               } else if (underlying_type == TypeManager.sbyte_type) {
+                                       if (!(v is Expression)){
+                                               sbyte val = (sbyte) v;
+                                               data [idx] = (byte) val;
+                                       }
+                               } else if (underlying_type == TypeManager.byte_type) {
+                                       if (!(v is Expression)){
+                                               byte val = (byte) v;
+                                               data [idx] = (byte) val;
+                                       }
                                } else
                                        throw new Exception ("Unrecognized type in MakeByteBlob");
 
@@ -3980,7 +4307,7 @@ namespace Mono.CSharp {
                        
                        if (data != null) {
                                fb = RootContext.MakeStaticData (data);
-                               
+
                                if (is_expression)
                                        ig.Emit (OpCodes.Dup);
                                ig.Emit (OpCodes.Ldtoken, fb);
@@ -4037,7 +4364,7 @@ namespace Mono.CSharp {
                                        // Basically we do this for string literals and
                                        // other non-literal expressions
                                        //
-                                       if (e is StringConstant || !(e is Constant)) {
+                                       if (e is StringConstant || !(e is Constant) || num_automatic_initializers <= 2) {
 
                                                ig.Emit (OpCodes.Ldloc, temp);
 
@@ -4082,12 +4409,12 @@ namespace Mono.CSharp {
                        } else {
                                Invocation.EmitArguments (ec, null, Arguments);
 
-                               if (IsBuiltinType)
+                               if (IsBuiltinType) 
                                        ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
-                               else
+                               else 
                                        ig.Emit (OpCodes.Newobj, (MethodInfo) method);
                        }
-
+                       
                        if (Initializers != null){
                                //
                                // FIXME: Set this variable correctly.
@@ -4095,8 +4422,10 @@ namespace Mono.CSharp {
                                bool dynamic_initializers = true;
 
                                if (underlying_type != TypeManager.string_type &&
-                                   underlying_type != TypeManager.object_type)
-                                       EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+                                   underlying_type != TypeManager.object_type) {
+                                       if (num_automatic_initializers > 2)
+                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+                               }
                                
                                if (dynamic_initializers)
                                        EmitDynamicInitializers (ec, !is_statement);
@@ -4163,7 +4492,7 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Starg, 0);
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ec.ig.Emit (OpCodes.Ldarg_0);
 
@@ -4217,22 +4546,35 @@ namespace Mono.CSharp {
        /// </summary>
        public class SizeOf : Expression {
                public readonly string QueriedType;
+               Type type_queried;
+               Location loc;
                
-               public SizeOf (string queried_type)
+               public SizeOf (string queried_type, Location l)
                {
                        this.QueriedType = queried_type;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       // FIXME: Implement;
-                       throw new Exception ("Unimplemented");
-                       // return this;
+                       type_queried = RootContext.LookupType (
+                               ec.TypeContainer, QueriedType, false, loc);
+                       if (type_queried == null)
+                               return null;
+
+                       type = TypeManager.int32_type;
+                       eclass = ExprClass.Value;
+                       return this;
                }
 
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Implement me");
+                       int size = GetTypeSize (type_queried);
+
+                       if (size == 0)
+                               ec.ig.Emit (OpCodes.Sizeof, type_queried);
+                       else
+                               IntConstant.EmitInt (ec.ig, size);
                }
        }
 
@@ -4266,7 +4608,6 @@ namespace Mono.CSharp {
                                      "type name instead");
                }
 
-#if USE_OLD
                static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
                {
                        if (left_original == null)
@@ -4309,6 +4650,19 @@ namespace Mono.CSharp {
                                //
                                // Instance.MethodGroup
                                //
+                               if (IdenticalNameAndTypeName (ec, left_original, loc)){
+                                       if (mg.RemoveInstanceMethods ())
+                                               return member_lookup;
+                               }
+                               
+                               if (!mg.RemoveStaticMethods ()){
+                                       error176 (loc, mg.Methods [0].Name);
+                                       return null;
+                               } 
+                               
+                               mg.InstanceExpression = left;
+                               return member_lookup;
+#if ORIGINAL
                                if (!mg.RemoveStaticMethods ()){
                                        if (IdenticalNameAndTypeName (ec, left_original, loc)){
                                                if (!mg.RemoveInstanceMethods ()){
@@ -4325,6 +4679,7 @@ namespace Mono.CSharp {
                                mg.InstanceExpression = left;
                                        
                                return member_lookup;
+#endif
                        }
 
                        if (member_lookup is FieldExpr){
@@ -4337,6 +4692,7 @@ namespace Mono.CSharp {
                                        if (c != null) {
                                                object o = c.LookupConstantValue (ec);
                                                object real_value = ((Constant) c.Expr).GetValue ();
+
                                                return Constantify (real_value, fi.FieldType);
                                        }
                                }
@@ -4353,7 +4709,8 @@ namespace Mono.CSharp {
                                        
                                        if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
                                                Expression enum_member = MemberLookup (
-                                                       ec, decl_type, "value__", false, loc); 
+                                                       ec, decl_type, "value__", MemberTypes.Field,
+                                                       AllBindingFlags, loc); 
 
                                                Enum en = TypeManager.LookupEnum (decl_type);
 
@@ -4375,6 +4732,11 @@ namespace Mono.CSharp {
                                        
                                        return exp;
                                }
+
+                               if (fi.FieldType.IsPointer && !ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
                                
                                if (left is TypeExpr){
                                        // and refers to a type name or an 
@@ -4428,8 +4790,9 @@ namespace Mono.CSharp {
                                // a FieldExpr
                                //
 
-                               Expression ml = MemberLookup (ec, ec.TypeContainer.TypeBuilder, ee.EventInfo.Name,
-                                                             true, MemberTypes.Event, AllBindingFlags, loc);
+                               Expression ml = MemberLookup (
+                                       ec, ec.TypeContainer.TypeBuilder,
+                                       ee.EventInfo.Name, MemberTypes.Event, AllBindingFlags, loc);
 
                                if (ml != null) {
                                        MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
@@ -4508,6 +4871,9 @@ namespace Mono.CSharp {
                        }
                                        
                        //
+                       // TODO: I mailed Ravi about this, and apparently we can get rid
+                       // of this and put it in the right place.
+                       // 
                        // Handle enums here when they are in transit.
                        // Note that we cannot afford to hit MemberLookup in this case because
                        // it will fail to find any members at all
@@ -4528,253 +4894,51 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       member_lookup = MemberLookup (ec, expr_type, Identifier, false, loc);
+                       if (expr_type.IsPointer){
+                               Report.Error (23, loc,
+                                             "The `.' operator can not be applied to pointer operands (" +
+                                             TypeManager.CSharpName (expr_type) + ")");
+                               return null;
+                       }
+                       
+                       member_lookup = MemberLookup (ec, expr_type, Identifier, loc);
 
-                       if (member_lookup == null)
+                       if (member_lookup == null){
+                               Report.Error (117, loc, "`" + expr_type + "' does not contain a " +
+                                             "definition for `" + Identifier + "'");
+                                             
                                return null;
+                       }
 
                        return ResolveMemberAccess (ec, member_lookup, expr, loc, original);
                }
 
-#else
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should not happen");
+               }
+       }
 
-               bla bla bla
-               //
-               // This code is more conformant to the spec (it follows it step by step),
-               // but it has not been tested yet, and there is nothing here that is not
-               // caught by the above code.  But it might be a better foundation to improve
-               // on in the future
-               //
-               public ResolveTypeMemberAccess (EmitContext ec, Expression member_lookup,
-                                               Expression left, Location loc)
+       /// <summary>
+       ///   Implements checked expressions
+       /// </summary>
+       public class CheckedExpr : Expression {
+
+               public Expression Expr;
+
+               public CheckedExpr (Expression e)
                {
-                       if (member_lookup is TypeExpr){
-                               member_lookup.Resolve (ec);
-                               return member_lookup;
-                       }
+                       Expr = e;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.ConstantCheckState = true;
+                       Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
                        
-                       if (member_lookup is MethodGroupExpr){
-                               if (!mg.RemoveStaticMethods ()){
-                                       SimpleName.Error120 (loc, mg.Methods [0].Name); 
-                                       return null;
-                               }
-                               
-                               return member_lookup;
-                       }
-                       
-                       if (member_lookup is PropertyExpr){
-                               PropertyExpr pe = (PropertyExpr) member_lookup;
-                                       
-                                       if (!pe.IsStatic){
-                                               SimpleName.Error120 (loc, pe.PropertyInfo.Name);
-                                               return null;
-                                       }
-                                       return pe;
-                       }
-                       
-                       if (member_lookup is FieldExpr){
-                               FieldExpr fe = (FieldExpr) member_lookup;
-                               FieldInfo fi = fe.FieldInfo;
-                               
-                               if (fi is FieldBuilder) {
-                                       Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
-                                       
-                                       if (c != null) {
-                                               object o = c.LookupConstantValue (ec);
-                                               return Constantify (o, fi.FieldType);
-                                       }
-                               }
-                               
-                               if (fi.IsLiteral) {
-                                       Type t = fi.FieldType;
-                                       Type decl_type = fi.DeclaringType;
-                                       object o;
-                                       
-                                       if (fi is FieldBuilder)
-                                               o = TypeManager.GetValue ((FieldBuilder) fi);
-                                       else
-                                               o = fi.GetValue (fi);
-                                       
-                                       if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
-                                               Expression enum_member = MemberLookup (
-                                                       ec, decl_type, "value__",
-                                                       false, loc); 
-                                               
-                                               Enum en = TypeManager.LookupEnum (decl_type);
-                                               
-                                               Constant c;
-                                               if (en != null)
-                                                       c = Constantify (o, en.UnderlyingType);
-                                               else 
-                                                       c = Constantify (o, enum_member.Type);
-                                               
-                                               return new EnumConstant (c, decl_type);
-                                       }
-                                       
-                                       Expression exp = Constantify (o, t);
-                                       
-                                       return exp;
-                               }
-
-                               if (!fe.FieldInfo.IsStatic){
-                                       error176 (loc, fe.FieldInfo.Name);
-                                       return null;
-                               }
-                               return member_lookup;
-                       }
-
-                       if (member_lookup is EventExpr){
-
-                               EventExpr ee = (EventExpr) member_lookup;
-                               
-                               //
-                               // If the event is local to this class, we transform ourselves into
-                               // a FieldExpr
-                               //
-
-                               Expression ml = MemberLookup (
-                                       ec, ec.TypeContainer.TypeBuilder, ee.EventInfo.Name,
-                                       true, MemberTypes.Event, AllBindingFlags, loc);
-
-                               if (ml != null) {
-                                       MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
-
-                                       ml = ExprClassFromMemberInfo (ec, mi, loc);
-                                       
-                                       if (ml == null) {
-                                               Report.Error (-200, loc, "Internal error!!");
-                                               return null;
-                                       }
-
-                                       return ResolveMemberAccess (ec, ml, left, loc);
-                               }
-
-                               if (!ee.IsStatic) {
-                                       SimpleName.Error120 (loc, ee.EventInfo.Name);
-                                       return null;
-                               }
-                               
-                               return ee;
-                       }
-
-                       Console.WriteLine ("Left is: " + left);
-                       Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
-                       Environment.Exit (0);
-
-                       return null;
-               }
-               
-               public ResolveInstanceMemberAccess (EmitContext ec, Expression member_lookup,
-                                                   Expression left, Location loc)
-               {
-                       if (member_lookup is MethodGroupExpr){
-                               //
-                               // Instance.MethodGroup
-                               //
-                               if (!mg.RemoveStaticMethods ()){
-                                       error176 (loc, mg.Methods [0].Name);
-                                       return null;
-                               }
-                               
-                               mg.InstanceExpression = left;
-                                       
-                               return member_lookup;
-                       }
-
-                       if (member_lookup is PropertyExpr){
-                               PropertyExpr pe = (PropertyExpr) member_lookup;
-
-                               if (pe.IsStatic){
-                                       error176 (loc, pe.PropertyInfo.Name);
-                                       return null;
-                               }
-                               pe.InstanceExpression = left;
-                               
-                               return pe;
-                       }
-
-                       Type left_type = left.type;
-
-                       if (left_type.IsValueType){
-                       } else {
-                               
-                       }
-               }
-               
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       //
-                       // We are the sole users of ResolveWithSimpleName (ie, the only
-                       // ones that can cope with it
-                       //
-                       expr = expr.ResolveWithSimpleName (ec);
-
-                       if (expr == null)
-                               return null;
-
-                       if (expr is SimpleName){
-                               SimpleName child_expr = (SimpleName) expr;
-                               
-                               expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
-
-                               return expr.ResolveWithSimpleName (ec);
-                       }
-
-                       //
-                       // Handle enums here when they are in transit.
-                       // Note that we cannot afford to hit MemberLookup in this case because
-                       // it will fail to find any members at all (Why?)
-                       //
-
-                       Type expr_type = expr.Type;
-                       if (expr_type.IsSubclassOf (TypeManager.enum_type)) {
-                               
-                               Enum en = TypeManager.LookupEnum (expr_type);
-                               
-                               if (en != null) {
-                                       object value = en.LookupEnumValue (ec, Identifier, loc);
-
-                                       if (value == null)
-                                               return null;
-                                       
-                                       Constant c = Constantify (value, en.UnderlyingType);
-                                       return new EnumConstant (c, expr_type);
-                               }
-                       }
-
-                       member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
-
-                       if (member_lookup == null)
-                               return null;
-
-                       if (expr is TypeExpr)
-                               return ResolveTypeMemberAccess (ec, member_lookup, expr, loc);
-                       else
-                               return ResolveInstanceMemberAccess (ec, member_lookup, expr, loc);
-               }
-#endif
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Should not happen");
-               }
-       }
-
-       /// <summary>
-       ///   Implements checked expressions
-       /// </summary>
-       public class CheckedExpr : Expression {
-
-               public Expression Expr;
-
-               public CheckedExpr (Expression e)
-               {
-                       Expr = e;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       Expr = Expr.Resolve (ec);
-
                        if (Expr == null)
                                return null;
 
@@ -4786,10 +4950,13 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
                        
                        ec.CheckState = true;
+                       ec.ConstantCheckState = true;
                        Expr.Emit (ec);
                        ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
                }
                
        }
@@ -4808,7 +4975,11 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.ConstantCheckState = false;
                        Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
 
                        if (Expr == null)
                                return null;
@@ -4821,10 +4992,13 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
                        
                        ec.CheckState = false;
+                       ec.ConstantCheckState = false;
                        Expr.Emit (ec);
                        ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
                }
                
        }
@@ -4875,7 +5049,27 @@ namespace Mono.CSharp {
 
                        return true;
                }
-                               
+
+               Expression MakePointerAccess ()
+               {
+                       Type t = Expr.Type;
+
+                       if (t == TypeManager.void_ptr_type){
+                               Report.Error (
+                                       242, loc,
+                                       "The array index operation is not valid for void pointers");
+                               return null;
+                       }
+                       if (Arguments.Count != 1){
+                               Report.Error (
+                                       196, loc,
+                                       "A pointer must be indexed by a single value");
+                               return null;
+                       }
+                       Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t);
+                       return new Indirection (p);
+               }
+               
                public override Expression DoResolve (EmitContext ec)
                {
                        if (!CommonResolve (ec))
@@ -4887,8 +5081,12 @@ namespace Mono.CSharp {
                        //
                        // I am experimenting with this pattern.
                        //
-                       if (Expr.Type.IsSubclassOf (TypeManager.array_type))
+                       Type t = Expr.Type;
+
+                       if (t.IsSubclassOf (TypeManager.array_type))
                                return (new ArrayAccess (this)).Resolve (ec);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
                        else
                                return (new IndexerAccess (this)).Resolve (ec);
                }
@@ -4898,8 +5096,11 @@ namespace Mono.CSharp {
                        if (!CommonResolve (ec))
                                return null;
 
-                       if (Expr.Type.IsSubclassOf (TypeManager.array_type))
+                       Type t = Expr.Type;
+                       if (t.IsSubclassOf (TypeManager.array_type))
                                return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
                        else
                                return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
                }
@@ -4933,7 +5134,6 @@ namespace Mono.CSharp {
                        }
 
                        Type t = ea.Expr.Type;
-
                        if (t.GetArrayRank () != ea.Arguments.Count){
                                Report.Error (22, ea.loc,
                                              "Incorrect number of indexes for array " +
@@ -4942,6 +5142,11 @@ namespace Mono.CSharp {
                                return null;
                        }
                        type = t.GetElementType ();
+                       if (type.IsPointer && !ec.InUnsafe){
+                               UnsafeError (ea.loc);
+                               return null;
+                       }
+                       
                        eclass = ExprClass.Variable;
 
                        return this;
@@ -4953,7 +5158,7 @@ namespace Mono.CSharp {
                /// </summary>
                static public void EmitLoadOpcode (ILGenerator ig, Type type)
                {
-                       if (type == TypeManager.byte_type)
+                       if (type == TypeManager.byte_type || type == TypeManager.bool_type)
                                ig.Emit (OpCodes.Ldelem_I1);
                        else if (type == TypeManager.sbyte_type)
                                ig.Emit (OpCodes.Ldelem_U1);
@@ -4975,9 +5180,10 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldelem_R8);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
-                       else if (type.IsValueType)
+                       else if (type.IsValueType){
                                ig.Emit (OpCodes.Ldelema, type);
-                       else 
+                               ig.Emit (OpCodes.Ldobj, type);
+                       } else 
                                ig.Emit (OpCodes.Ldelem_Ref);
                }
 
@@ -4987,9 +5193,10 @@ namespace Mono.CSharp {
                /// </summary>
                static public void EmitStoreOpcode (ILGenerator ig, Type t)
                {
-                       if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
+                       if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
+                           t == TypeManager.bool_type)
                                ig.Emit (OpCodes.Stelem_I1);
-                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
+                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type || t == TypeManager.char_type)
                                ig.Emit (OpCodes.Stelem_I2);
                        else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
                                ig.Emit (OpCodes.Stelem_I4);
@@ -5001,6 +5208,8 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Stelem_R8);
                        else if (t == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Stelem_I);
+                       else if (t.IsValueType)
+                               ig.Emit (OpCodes.Stobj, t);
                        else
                                ig.Emit (OpCodes.Stelem_Ref);
                }
@@ -5086,10 +5295,20 @@ namespace Mono.CSharp {
                        foreach (Argument a in ea.Arguments)
                                a.Expr.Emit (ec);
 
-                       source.Emit (ec);
-
                        Type t = source.Type;
 
+                       //
+                       // The stobj opcode used by value types will need
+                       // an address on the stack, not really an array/array
+                       // pair
+                       //
+                       if (rank == 1){
+                               if (t.IsValueType && !TypeManager.IsBuiltinType (t))
+                                       ig.Emit (OpCodes.Ldelema, t);
+                       }
+                       
+                       source.Emit (ec);
+
                        if (rank == 1)
                                EmitStoreOpcode (ig, t);
                        else {
@@ -5114,7 +5333,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
@@ -5240,6 +5459,11 @@ namespace Mono.CSharp {
                        }
 
                        type = get.ReturnType;
+                       if (type.IsPointer && !ec.InUnsafe){
+                               UnsafeError (ea.loc);
+                               return null;
+                       }
+                       
                        eclass = ExprClass.IndexerAccess;
                        return this;
                }
@@ -5275,7 +5499,7 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
-                       Invocation.EmitCall (ec, false, ea.Expr, get, ea.Arguments);
+                       Invocation.EmitCall (ec, false, false, ea.Expr, get, ea.Arguments);
                }
 
                //
@@ -5285,7 +5509,7 @@ namespace Mono.CSharp {
                //
                public void EmitAssign (EmitContext ec, Expression source)
                {
-                       Invocation.EmitCall (ec, false, ea.Expr, set, set_arguments);
+                       Invocation.EmitCall (ec, false, false, ea.Expr, set, set_arguments);
                }
        }
 
@@ -5307,8 +5531,15 @@ namespace Mono.CSharp {
                        Expression member_lookup;
                        Type current_type = ec.TypeContainer.TypeBuilder;
                        Type base_type = current_type.BaseType;
+                       Expression e;
+
+                       if (ec.IsStatic){
+                               Report.Error (1511, loc,
+                                             "Keyword base is not allowed in static method");
+                               return null;
+                       }
                        
-                       member_lookup = MemberLookup (ec, base_type, member, false, loc);
+                       member_lookup = MemberLookup (ec, base_type, member, loc);
                        if (member_lookup == null)
                                return null;
 
@@ -5317,9 +5548,16 @@ namespace Mono.CSharp {
                        if (ec.IsStatic)
                                left = new TypeExpr (base_type);
                        else
-                               left = new This (loc).Resolve (ec);
+                               left = ec.This;
                        
-                       return MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
+                       e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
+                       if (e is PropertyExpr){
+                               PropertyExpr pe = (PropertyExpr) e;
+
+                               pe.IsBase = true;
+                       }
+
+                       return e;
                }
 
                public override void Emit (EmitContext ec)
@@ -5333,22 +5571,36 @@ namespace Mono.CSharp {
        /// </summary>
        public class BaseIndexerAccess : Expression {
                ArrayList Arguments;
-
-               public BaseIndexerAccess (ArrayList args)
+               Location loc;
+               
+               public BaseIndexerAccess (ArrayList args, Location l)
                {
                        Arguments = args;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       // FIXME: Implement;
-                       throw new Exception ("Unimplemented");
-                       // return this;
+                       Type current_type = ec.TypeContainer.TypeBuilder;
+                       Type base_type = current_type.BaseType;
+                       Expression member_lookup;
+
+                       if (ec.IsStatic){
+                               Report.Error (1511, loc,
+                                             "Keyword base is not allowed in static method");
+                               return null;
+                       }
+                       
+                       member_lookup = MemberLookup (ec, base_type, "get_Item", MemberTypes.Method, AllBindingFlags, loc);
+                       if (member_lookup == null)
+                               return null;
+
+                       return MemberAccess.ResolveMemberAccess (ec, member_lookup, ec.This, loc, null);
                }
 
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Unimplemented");
+                       throw new Exception ("Should never be called");
                }
        }
        
@@ -5425,7 +5677,6 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Call, (ConstructorInfo) method);
 
                }
-
        }
 
        // <summary>
@@ -5462,6 +5713,11 @@ namespace Mono.CSharp {
                        if (type == null)
                                return null;
 
+                       if (!ec.InUnsafe && type.IsPointer){
+                               UnsafeError (loc);
+                               return null;
+                       }
+                       
                        eclass = ExprClass.Type;
                        return this;
                }
@@ -5471,4 +5727,148 @@ namespace Mono.CSharp {
                        throw new Exception ("This should never be called");
                }
        }
+
+       //
+       // This class is used to represent the address of an array, used
+       // only by the Fixed statement, this is like the C "&a [0]" construct.
+       //
+       public class ArrayPtr : Expression {
+               Expression array;
+               
+               public ArrayPtr (Expression array)
+               {
+                       Type array_type = array.Type.GetElementType ();
+
+                       this.array = array;
+                       
+                       string array_ptr_type_name = array_type.FullName + "*";
+                       
+                       type = Type.GetType (array_ptr_type_name);
+                       if (type == null){
+                               ModuleBuilder mb = RootContext.ModuleBuilder;
+                               
+                               type = mb.GetType (array_ptr_type_name);
+                       }
+
+                       eclass = ExprClass.Value;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       array.Emit (ec);
+                       IntLiteral.EmitInt (ig, 0);
+                       ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+       }
+
+       //
+       // Used by the fixed statement
+       //
+       public class StringPtr : Expression {
+               LocalBuilder b;
+               
+               public StringPtr (LocalBuilder b)
+               {
+                       this.b = b;
+                       eclass = ExprClass.Value;
+                       type = TypeManager.char_ptr_type;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldloc, b);
+                       ig.Emit (OpCodes.Conv_I);
+                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
+                       ig.Emit (OpCodes.Add);
+               }
+       }
+       
+       //
+       // Implements the `stackalloc' keyword
+       //
+       public class StackAlloc : Expression {
+               Type otype;
+               string t;
+               Expression count;
+               Location loc;
+               
+               public StackAlloc (string type, Expression count, Location l)
+               {
+                       t = type;
+                       this.count = count;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       count = count.Resolve (ec);
+                       if (count == null)
+                               return null;
+                       
+                       if (count.Type != TypeManager.int32_type){
+                               count = ConvertImplicitRequired (ec, count, TypeManager.int32_type, loc);
+                               if (count == null)
+                                       return null;
+                       }
+
+                       if (ec.InCatch || ec.InFinally){
+                               Report.Error (255, loc,
+                                             "stackalloc can not be used in a catch or finally block");
+                               return null;
+                       }
+                       
+                       otype = RootContext.LookupType (ec.TypeContainer, t, false, loc);
+
+                       if (otype == null)
+                               return null;
+
+                       if (!TypeManager.VerifyUnManaged (otype, loc))
+                               return null;
+
+                       string ptr_name = otype.FullName + "*";
+                       type = Type.GetType (ptr_name);
+                       if (type == null){
+                               ModuleBuilder mb = RootContext.ModuleBuilder;
+                               
+                               type = mb.GetType (ptr_name);
+                       }
+                       eclass = ExprClass.Value;
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int size = GetTypeSize (otype);
+                       ILGenerator ig = ec.ig;
+                               
+                       if (size == 0)
+                               ig.Emit (OpCodes.Sizeof, otype);
+                       else
+                               IntConstant.EmitInt (ig, size);
+                       count.Emit (ec);
+                       ig.Emit (OpCodes.Mul);
+                       ig.Emit (OpCodes.Localloc);
+               }
+       }
 }