Bug fixes and a couple of optimizations (used a nice profiler to find
[mono.git] / mcs / mcs / expression.cs
index b6d0e5f733d619eb6bc88756cd5d4d3a67276302..bcb07955575522d34ff9611621962558a55ed8f6 100755 (executable)
@@ -7,6 +7,7 @@
 // (C) 2001 Ximian, Inc.
 //
 //
+#define USE_OLD
 
 namespace Mono.CSharp {
        using System;
@@ -87,7 +88,7 @@ namespace Mono.CSharp {
        public class Unary : Expression {
                public enum Operator : byte {
                        UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
-                       Indirection, AddressOf, 
+                       Indirection, AddressOf,  TOP
                }
 
                Operator   oper;
@@ -124,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:
@@ -144,34 +145,111 @@ namespace Mono.CSharp {
                        return oper.ToString ();
                }
 
-               void error23 (Type t)
+               static string [] oper_names;
+
+               static Unary ()
+               {
+                       oper_names = new string [(int)Operator.TOP];
+
+                       oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";
+                       oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
+                       oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
+                       oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
+                       oper_names [(int) Operator.Indirection] = "op_Indirection";
+                       oper_names [(int) Operator.AddressOf] = "op_AddressOf";
+               }
+
+               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) + "'");
                }
 
+               /// <remarks>
+               ///   The result has been already resolved:
+               ///
+               ///   FIXME: a minus constant -128 sbyte cant be turned into a
+               ///   constant byte.
+               /// </remarks>
                static Expression TryReduceNegative (Expression expr)
                {
                        Expression e = null;
                        
-                       if (expr is IntLiteral)
-                               e = new IntLiteral (-((IntLiteral) expr).Value);
-                       else if (expr is UIntLiteral)
-                               e = new LongLiteral (-((UIntLiteral) expr).Value);
-                       else if (expr is LongLiteral)
-                               e = new LongLiteral (-((LongLiteral) expr).Value);
-                       else if (expr is FloatLiteral)
-                               e = new FloatLiteral (-((FloatLiteral) expr).Value);
-                       else if (expr is DoubleLiteral)
-                               e = new DoubleLiteral (-((DoubleLiteral) expr).Value);
-                       else if (expr is DecimalLiteral)
-                               e = new DecimalLiteral (-((DecimalLiteral) expr).Value);
+                       if (expr is IntConstant)
+                               e = new IntConstant (-((IntConstant) expr).Value);
+                       else if (expr is UIntConstant)
+                               e = new LongConstant (-((UIntConstant) expr).Value);
+                       else if (expr is LongConstant)
+                               e = new LongConstant (-((LongConstant) expr).Value);
+                       else if (expr is FloatConstant)
+                               e = new FloatConstant (-((FloatConstant) expr).Value);
+                       else if (expr is DoubleConstant)
+                               e = new DoubleConstant (-((DoubleConstant) expr).Value);
+                       else if (expr is DecimalConstant)
+                               e = new DecimalConstant (-((DecimalConstant) expr).Value);
+                       else if (expr is ShortConstant)
+                               e = new IntConstant (-((ShortConstant) expr).Value);
+                       else if (expr is UShortConstant)
+                               e = new IntConstant (-((UShortConstant) expr).Value);
 
                        return e;
                }
                
+               Expression Reduce (EmitContext ec, Expression e)
+               {
+                       Type expr_type = e.Type;
+                       
+                       switch (oper){
+                       case Operator.UnaryPlus:
+                               return e;
+                               
+                       case Operator.UnaryNegation:
+                               return TryReduceNegative (e);
+                               
+                       case Operator.LogicalNot:
+                               if (expr_type != TypeManager.bool_type) {
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+                               
+                               BoolConstant b = (BoolConstant) e;
+                               return new BoolConstant (!(b.Value));
+                               
+                       case Operator.OnesComplement:
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+
+                               if (e is EnumConstant){
+                                       EnumConstant enum_constant = (EnumConstant) e;
+                                       
+                                       Expression reduced = Reduce (ec, enum_constant.Child);
+
+                                       return new EnumConstant ((Constant) reduced, enum_constant.Type);
+                               }
+
+                               if (expr_type == TypeManager.int32_type)
+                                       return new IntConstant (~ ((IntConstant) e).Value);
+                               if (expr_type == TypeManager.uint32_type)
+                                       return new UIntConstant (~ ((UIntConstant) e).Value);
+                               if (expr_type == TypeManager.int64_type)
+                                       return new LongConstant (~ ((LongConstant) e).Value);
+                               if (expr_type == TypeManager.uint64_type)
+                                       return new ULongConstant (~ ((ULongConstant) e).Value);
+
+                               Error23 (expr_type);
+                               return null;
+                       }
+                       throw new Exception ("Can not constant fold");
+               }
+
                Expression ResolveOperator (EmitContext ec)
                {
                        Type expr_type = expr.Type;
@@ -182,38 +260,37 @@ namespace Mono.CSharp {
                        Expression mg;
                        string op_name;
                        
-                       op_name = "op_" + oper;
+                       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;
                                }
                                
                                return e;
                        }
 
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
                        // Only perform numeric promotions on:
                        // +, - 
 
                        if (expr_type == null)
                                return null;
                        
+                       //
+                       // Step 2: Default operations on CLI native types.
+                       //
+                       if (expr is Constant)
+                               return Reduce (ec, expr);
+
                        if (oper == Operator.LogicalNot){
                                if (expr_type != TypeManager.bool_type) {
-                                       error23 (expr.Type);
+                                       Error23 (expr.Type);
                                        return null;
                                }
                                
@@ -227,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;
@@ -250,25 +327,11 @@ namespace Mono.CSharp {
                        // decimal operator- (decimal d)
                        //
                        if (oper == Operator.UnaryNegation){
-                               //
-                               // Fold a "- Constant" into a negative constant
-                               //
-                       
                                Expression e = null;
 
                                //
-                               // Is this a constant? 
-                               //
-                               e = TryReduceNegative (expr);
-                               
-                               if (e != null){
-                                       e = e.Resolve (ec);
-                                       return e;
-                               }
-
-                               //
-                               // Not a constant we can optimize, perform numeric 
-                               // promotions to int, long, double.
+                               // perform numeric promotions to int,
+                               // long, double.
                                //
                                //
                                // The following is inneficient, because we call
@@ -281,7 +344,7 @@ namespace Mono.CSharp {
                                        //
                                        // FIXME: handle exception to this rule that
                                        // permits the int value -2147483648 (-2^31) to
-                                       // bt written as a decimal interger literal
+                                       // bt wrote as a decimal interger literal
                                        //
                                        type = TypeManager.int64_type;
                                        expr = ConvertImplicit (ec, expr, type, loc);
@@ -291,13 +354,18 @@ namespace Mono.CSharp {
                                if (expr_type == TypeManager.uint64_type){
                                        //
                                        // FIXME: Handle exception of `long value'
-                                       // -92233720368547758087 (-2^63) to be written as
+                                       // -92233720368547758087 (-2^63) to be wrote as
                                        // decimal integer literal.
                                        //
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
 
+                               if (expr_type == TypeManager.float_type){
+                                       type = expr_type;
+                                       return this;
+                               }
+                               
                                e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);
                                if (e != null){
                                        expr = e;
@@ -319,21 +387,59 @@ namespace Mono.CSharp {
                                        return this;
                                }
 
-                               error23 (expr_type);
+                               Error23 (expr_type);
                                return null;
                        }
 
                        if (oper == Operator.AddressOf){
-                               if (expr.ExprClass != ExprClass.Variable){
+                               if (expr.eclass != ExprClass.Variable){
                                        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;
                }
@@ -375,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 ());
@@ -398,50 +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 override Expression Reduce (EmitContext ec)
+               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)
                {
-                       Expression e;
-                       
                        //
-                       // First, reduce our child.  Note that although we handle 
+                       // Born fully resolved
                        //
-                       expr = expr.Reduce (ec);
-                       if (!(expr is Literal))
-                               return expr;
-                       
-                       switch (oper){
-                       case Operator.UnaryPlus:
-                               return expr;
-                               
-                       case Operator.UnaryNegation:
-                               e = TryReduceNegative (expr);
-                               if (e == null)
-                                       break;
-                               return e;
-                               
-                       case Operator.LogicalNot:
-                               BoolLiteral b = (BoolLiteral) expr;
-
-                               return new BoolLiteral (!(b.Value));
-                               
-                       case Operator.OnesComplement:
-                               Type et = expr.Type;
-                               
-                               if (et == TypeManager.int32_type)
-                                       return new IntLiteral (~ ((IntLiteral) expr).Value);
-                               if (et == TypeManager.uint32_type)
-                                       return new UIntLiteral (~ ((UIntLiteral) expr).Value);
-                               if (et == TypeManager.int64_type)
-                                       return new LongLiteral (~ ((LongLiteral) expr).Value);
-                               if (et == TypeManager.uint64_type)
-                                       return new ULongLiteral (~ ((ULongLiteral) expr).Value);
-                               break;
-                       }
                        return this;
                }
        }
-
+       
        /// <summary>
        ///   Unary Mutator expressions (pre and post ++ and --)
        /// </summary>
@@ -480,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) + "'");
                }
@@ -513,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)
@@ -531,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 (
@@ -550,12 +661,12 @@ namespace Mono.CSharp {
                        // a property access or an indexer access
                        //
                        type = expr_type;
-                       if (expr.ExprClass == ExprClass.Variable){
+                       if (expr.eclass == ExprClass.Variable){
                                if (IsIncrementableNumber (expr_type) ||
                                    expr_type == TypeManager.decimal_type){
                                        return this;
                                }
-                       } else if (expr.ExprClass == ExprClass.IndexerAccess){
+                       } else if (expr.eclass == ExprClass.IndexerAccess){
                                IndexerAccess ia = (IndexerAccess) expr;
                                
                                temp_storage = new LocalTemporary (ec, expr.Type);
@@ -565,7 +676,7 @@ namespace Mono.CSharp {
                                        return null;
 
                                return this;
-                       } else if (expr.ExprClass == ExprClass.PropertyAccess){
+                       } else if (expr.eclass == ExprClass.PropertyAccess){
                                PropertyExpr pe = (PropertyExpr) expr;
 
                                if (pe.VerifyAssignable ())
@@ -577,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;
                }
@@ -592,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,
@@ -603,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);
@@ -639,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);
@@ -669,27 +816,23 @@ namespace Mono.CSharp {
        }
 
        /// <summary>
-       ///   Implements the `is' and `as' tests.
+       ///   Base class for the `Is' and `As' classes. 
        /// </summary>
        ///
        /// <remarks>
        ///   FIXME: Split this in two, and we get to save the `Operator' Oper
        ///   size. 
        /// </remarks>
-       public class Probe : Expression {
+       public abstract class Probe : Expression {
                public readonly string ProbeType;
-               public readonly Operator Oper;
-               Expression expr;
-               Type probe_type;
-               
-               public enum Operator : byte {
-                       Is, As
-               }
+               protected Expression expr;
+               protected Type probe_type;
+               protected Location loc;
                
-               public Probe (Operator oper, Expression expr, string probe_type)
+               public Probe (Expression expr, string probe_type, Location l)
                {
-                       Oper = oper;
                        ProbeType = probe_type;
+                       loc = l;
                        this.expr = expr;
                }
 
@@ -698,21 +841,28 @@ namespace Mono.CSharp {
                                return expr;
                        }
                }
-               
+
                public override Expression DoResolve (EmitContext ec)
                {
-                       probe_type = ec.TypeContainer.LookupType (ProbeType, false);
+                       probe_type = RootContext.LookupType (ec.TypeContainer, ProbeType, false, loc);
 
                        if (probe_type == null)
                                return null;
 
                        expr = expr.Resolve (ec);
                        
-                       type = TypeManager.bool_type;
-                       eclass = ExprClass.Value;
-
                        return this;
                }
+       }
+
+       /// <summary>
+       ///   Implementation of the `is' operator.
+       /// </summary>
+       public class Is : Probe {
+               public Is (Expression expr, string probe_type, Location l)
+                       : base (expr, probe_type, l)
+               {
+               }
 
                public override void Emit (EmitContext ec)
                {
@@ -720,16 +870,73 @@ namespace Mono.CSharp {
                        
                        expr.Emit (ec);
                        
-                       if (Oper == Operator.Is){
-                               ig.Emit (OpCodes.Isinst, probe_type);
-                               ig.Emit (OpCodes.Ldnull);
-                               ig.Emit (OpCodes.Cgt_Un);
-                       } else {
-                               ig.Emit (OpCodes.Isinst, probe_type);
-                       }
+                       ig.Emit (OpCodes.Isinst, probe_type);
+                       ig.Emit (OpCodes.Ldnull);
+                       ig.Emit (OpCodes.Cgt_Un);
                }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+
+                       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;
+
+                       return this;
+               }                               
        }
 
+       /// <summary>
+       ///   Implementation of the `as' operator.
+       /// </summary>
+       public class As : Probe {
+               public As (Expression expr, string probe_type, Location l)
+                       : base (expr, probe_type, l)
+               {
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       expr.Emit (ec);
+                       ig.Emit (OpCodes.Isinst, probe_type);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+
+                       if (e == null)
+                               return null;
+
+                       type = probe_type;
+                       eclass = ExprClass.Value;
+
+                       return this;
+               }                               
+       }
+       
        /// <summary>
        ///   This represents a typecast in the source language.
        ///
@@ -762,6 +969,235 @@ namespace Mono.CSharp {
                                expr = value;
                        }
                }
+
+               /// <summary>
+               ///   Attempts to do a compile-time folding of a constant cast.
+               /// </summary>
+               Expression TryReduce (EmitContext ec, Type target_type)
+               {
+                       if (expr is ByteConstant){
+                               byte v = ((ByteConstant) expr).Value;
+       
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is SByteConstant){
+                               sbyte v = ((SByteConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is ShortConstant){
+                               short v = ((ShortConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is UShortConstant){
+                               ushort v = ((UShortConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is IntConstant){
+                               int v = ((IntConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is UIntConstant){
+                               uint v = ((UIntConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is LongConstant){
+                               long v = ((LongConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is ULongConstant){
+                               ulong v = ((ULongConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is FloatConstant){
+                               float v = ((FloatConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                       }
+                       if (expr is DoubleConstant){
+                               double v = ((DoubleConstant) expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                       }
+
+                       return null;
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
@@ -773,7 +1209,7 @@ namespace Mono.CSharp {
                        if (target_type == null)
                                return null;
 
-                       if (target_type.ExprClass != ExprClass.Type){
+                       if (target_type.eclass != ExprClass.Type){
                                report118 (loc, target_type, "class");
                                return null;
                        }
@@ -784,6 +1220,13 @@ namespace Mono.CSharp {
                        if (type == null)
                                return null;
 
+                       if (expr is Constant){
+                               Expression e = TryReduce (ec, type);
+
+                               if (e != null)
+                                       return e;
+                       }
+                       
                        expr = ConvertExplicit (ec, expr, type, loc);
                        return expr;
                }
@@ -819,7 +1262,8 @@ namespace Mono.CSharp {
                MethodBase method;
                ArrayList  Arguments;
                Location   loc;
-               
+
+               bool DelegateOperation;
 
                public Binary (Operator oper, Expression left, Expression right, Location loc)
                {
@@ -860,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:
@@ -911,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.
@@ -931,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);
@@ -947,17 +1401,38 @@ 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 && right is IntLiteral){
-                                               e = TryImplicitIntConversion (l, (IntLiteral) right);
-                                               if (e != null)
-                                                       right = e;
+                                       if (r != TypeManager.uint64_type){
+                                               if (right is IntConstant){
+                                                       IntConstant ic = (IntConstant) right;
+                                                       
+                                                       e = TryImplicitIntConversion (l, ic);
+                                                       if (e != null)
+                                                               right = e;
+                                               } else if (right is LongConstant){
+                                                       long ll = ((LongConstant) right).Value;
+
+                                                       if (ll > 0)
+                                                               right = new ULongConstant ((ulong) ll);
+                                               } else {
+                                                       e = ImplicitNumericConversion (ec, right, l, loc);
+                                                       if (e != null)
+                                                               right = e;
+                                               }
                                        }
                                        other = right.Type;
                                } else {
-                                       if (left is IntLiteral){
-                                               e = TryImplicitIntConversion (r, (IntLiteral) left);
+                                       if (left is IntConstant){
+                                               e = TryImplicitIntConversion (r, (IntConstant) left);
+                                               if (e != null)
+                                                       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;
                                        }
@@ -967,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){
                                //
@@ -996,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)
-                                       other = l;
+                               } 
+                               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) ||
@@ -1043,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;
@@ -1090,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 ();
@@ -1108,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 {
@@ -1119,7 +1620,7 @@ namespace Mono.CSharp {
                        //
                        // Step 2: Default operations on CLI native types.
                        //
-                       
+
                        // Only perform numeric promotions on:
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
@@ -1128,12 +1629,19 @@ 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 Literal && right is Literal){
-                                                       StringLiteral ls = (StringLiteral) left;
-                                                       StringLiteral rs = (StringLiteral) right;
+                                               if (left is Constant && right is Constant){
+                                                       StringConstant ls = (StringConstant) left;
+                                                       StringConstant rs = (StringConstant) right;
                                                        
-                                                       return new StringLiteral (ls.Value + rs.Value);
+                                                       return new StringConstant (
+                                                               ls.Value + rs.Value);
                                                }
                                                
                                                // string + string
@@ -1154,20 +1662,108 @@ 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;
                                }
+                       }
+
+                       if (oper == Operator.Addition || oper == Operator.Subtraction) {
+                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
+                                   r.IsSubclassOf (TypeManager.delegate_type)) {
+                                       
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       
+                                       if (oper == Operator.Addition)
+                                               method = TypeManager.delegate_combine_delegate_delegate;
+                                       else
+                                               method = TypeManager.delegate_remove_delegate_delegate;
+                                       
+                                       DelegateOperation = true;
+                                       type = l;
+                                       return this;
+                               }
 
                                //
-                               // FIXME: is Delegate operator + (D x, D y) handled?
+                               // 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);
+                       }
+                       
+                       //
+                       // Enumeration operators
+                       //
+                       bool lie = TypeManager.IsEnumType (l);
+                       bool rie = TypeManager.IsEnumType (r);
+                       if (lie || rie){
+                               Expression temp;
+
+                               if (!rie){
+                                       temp = ConvertImplicit (ec, right, l, loc);
+                                       if (temp != null)
+                                               right = temp;
+                               } if (!lie){
+                                       temp = ConvertImplicit (ec, left, r, loc);
+                                       if (temp != null){
+                                               left = temp;
+                                               l = r;
+                                       }
+                               }
+                               
+                               if (oper == Operator.Equality || oper == Operator.Inequality ||
+                                   oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||
+                                   oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (oper == Operator.BitwiseAnd ||
+                                   oper == Operator.BitwiseOr ||
+                                   oper == Operator.ExclusiveOr){
+                                       type = l;
+                                       return this;
+                               }
                        }
                        
                        if (oper == Operator.LeftShift || oper == Operator.RightShift)
@@ -1194,35 +1790,54 @@ namespace Mono.CSharp {
                                        return this;
                                }
 
-                       }
-
-                       //
-                       // We are dealing with numbers
-                       //
-
-                       if (!DoNumericPromotions (ec, l, r)){
-                               // Attempt:
                                //
                                // operator != (object a, object b)
                                // operator == (object a, object b)
                                //
+                               // For this to be used, both arguments have to be reference-types.
+                               // Read the rationale on the spec (14.9.6)
+                               //
+                               // Also, if at compile time we know that the classes do not inherit
+                               // one from the other, then we catch the error there.
+                               //
+                               if (!(l.IsValueType || r.IsValueType)){
+                                       type = TypeManager.bool_type;
 
-                               if (oper == Operator.Equality || oper == Operator.Inequality){
-                                       Expression li, ri;
-                                       li = ConvertImplicit (ec, left, TypeManager.object_type, loc);
-                                       if (li != null){
-                                               ri = ConvertImplicit (ec, right, TypeManager.object_type,
-                                                                     loc);
-                                               if (ri != null){
-                                                       left = li;
-                                                       right = ri;
-                                                       
-                                                       type = TypeManager.bool_type;
-                                                       return this;
-                                               }
-                                       }
+                                       if (l == r)
+                                               return this;
+                                       
+                                       if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
+                                               return this;
+
+                                       //
+                                       // We are going to have to convert to an object to compare
+                                       //
+                                       if (l != TypeManager.object_type)
+                                               left = new EmptyCast (left, TypeManager.object_type);
+                                       if (r != TypeManager.object_type)
+                                               right = new EmptyCast (right, TypeManager.object_type);
+
+                                       return this;
                                }
+                       }
+
+                       //
+                       // 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
+                       //
 
+                       if (!DoNumericPromotions (ec, l, r)){
                                error19 ();
                                return null;
                        }
@@ -1240,8 +1855,7 @@ namespace Mono.CSharp {
                            oper == Operator.BitwiseOr ||
                            oper == Operator.ExclusiveOr){
                                if (l == r){
-                                       if (l.IsSubclassOf (TypeManager.enum_type) ||
-                                           !((l == TypeManager.int32_type) ||
+                                       if (!((l == TypeManager.int32_type) ||
                                              (l == TypeManager.uint32_type) ||
                                              (l == TypeManager.int64_type) ||
                                              (l == TypeManager.uint64_type)))
@@ -1263,7 +1877,7 @@ namespace Mono.CSharp {
 
                        return this;
                }
-               
+
                public override Expression DoResolve (EmitContext ec)
                {
                        left = left.Resolve (ec);
@@ -1283,6 +1897,13 @@ namespace Mono.CSharp {
 
                        eclass = ExprClass.Value;
 
+                       if (left is Constant && right is Constant){
+                               Expression e = ConstantFold.BinaryFold (
+                                       ec, oper, (Constant) left, (Constant) right, loc);
+                               if (e != null)
+                                       return e;
+                       }
+
                        return ResolveOperator (ec);
                }
 
@@ -1406,6 +2027,9 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (OpCodes.Call, (ConstructorInfo) method);
 
+                               if (DelegateOperation)
+                                       ig.Emit (OpCodes.Castclass, type);
+                                       
                                return;
                        }
 
@@ -1554,32 +2178,79 @@ namespace Mono.CSharp {
 
                        ig.Emit (opcode);
                }
+       }
 
-               /// <summary>
-               ///   Constant expression reducer for binary operations
-               /// </summary>
-               public override Expression Reduce (EmitContext ec)
-               {
-                       
-                       left = left.Reduce (ec);
-                       right = right.Reduce (ec);
+       public class PointerArithmetic : Expression {
+               Expression left, right;
+               bool is_add;
 
-                       if (!(left is Literal && right is Literal))
-                               return this;
+               //
+               // 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;
+               }
 
-                       if (method == TypeManager.string_concat_string_string){
-                               StringLiteral ls = (StringLiteral) left;
-                               StringLiteral rs = (StringLiteral) right;
-                               
-                               return new StringLiteral (ls.Value + rs.Value);
-                       }
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
 
-                       // FINISH ME.
+               public override void Emit (EmitContext ec)
+               {
+                       Type op_type = left.Type;
+                       ILGenerator ig = ec.ig;
+                       int size = GetTypeSize (op_type.GetElementType ());
                        
-                       return this;
+                       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>
        public class Conditional : Expression {
                Expression expr, trueExpr, falseExpr;
                Location loc;
@@ -1624,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 " +
@@ -1649,16 +2343,15 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (expr is BoolLiteral){
-                               BoolLiteral bl = (BoolLiteral) expr;
+                       if (expr is BoolConstant){
+                               BoolConstant bc = (BoolConstant) expr;
 
-                               if (bl.Value)
+                               if (bc.Value)
                                        return trueExpr;
                                else
                                        return falseExpr;
                        }
-                       
-                       eclass = ExprClass.Value;
+
                        return this;
                }
 
@@ -1677,34 +2370,22 @@ namespace Mono.CSharp {
                        ig.MarkLabel (end_target);
                }
 
-               public override Expression Reduce (EmitContext ec)
-               {
-                       expr = expr.Reduce (ec);
-                       trueExpr = trueExpr.Reduce (ec);
-                       falseExpr = falseExpr.Reduce (ec);
-
-                       if (!(expr is Literal && trueExpr is Literal && falseExpr is Literal))
-                               return this;
-
-                       BoolLiteral bl = (BoolLiteral) expr;
-
-                       if (bl.Value)
-                               return trueExpr;
-                       else
-                               return falseExpr;
-               }
        }
 
+       /// <summary>
+       ///   Local variables
+       /// </summary>
        public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation {
                public readonly string Name;
                public readonly Block Block;
-
+               Location loc;
                VariableInfo variable_info;
                
-               public LocalVariableReference (Block block, string name)
+               public LocalVariableReference (Block block, string name, Location l)
                {
                        Block = block;
                        Name = name;
+                       loc = l;
                        eclass = ExprClass.Variable;
                }
 
@@ -1720,10 +2401,38 @@ namespace Mono.CSharp {
                {
                        VariableInfo vi = VariableInfo;
 
+                       if (Block.IsConstant (Name)) {
+                               Expression e = Block.GetConstantExpression (Name);
+
+                               vi.Used = true;
+                               return e;
+                       }
+
                        type = vi.VariableType;
                        return this;
                }
 
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       Expression e = DoResolve (ec);
+
+                       if (e == null)
+                               return null;
+
+                       VariableInfo vi = VariableInfo;
+                       
+                       if (vi.ReadOnly){
+                               if (vi.Assigned){
+                                       Report.Error (
+                                               1604, loc,
+                                               "cannot assign to `" + Name + "' because it is readonly");
+                                       return null;
+                               }
+                       }
+                       
+                       return this;
+               }
+
                public override void Emit (EmitContext ec)
                {
                        VariableInfo vi = VariableInfo;
@@ -1802,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);
@@ -1822,53 +2533,118 @@ namespace Mono.CSharp {
        ///   representation.
        /// </summary>
        public class ParameterReference : Expression, IAssignMethod, IMemoryLocation {
-               public readonly Parameters Pars;
-               public readonly String Name;
-               public readonly int Idx;
-               int arg_idx;
+               Parameters pars;
+               String name;
+               int idx;
+               public bool is_ref;
                
                public ParameterReference (Parameters pars, int idx, string name)
                {
-                       Pars = pars;
-                       Idx  = idx;
-                       Name = name;
+                       this.pars = pars;
+                       this.idx  = idx;
+                       this.name = name;
                        eclass = ExprClass.Variable;
                }
 
+               //
+               // Notice that for ref/out parameters, the type exposed is not the
+               // same type exposed externally.
+               //
+               // for "ref int a":
+               //   externally we expose "int&"
+               //   here we expose       "int".
+               //
+               // We record this in "is_ref".  This means that the type system can treat
+               // the type as it is expected, but when we generate the code, we generate
+               // the alternate kind of code.
+               //
                public override Expression DoResolve (EmitContext ec)
                {
-                       Type [] types = Pars.GetParameterInfo (ec.TypeContainer);
+                       type = pars.GetParameterInfo (ec.TypeContainer, idx, out is_ref);
+                       eclass = ExprClass.Variable;
+
+                       return this;
+               }
 
-                       type = types [Idx];
+               //
+               // 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;
 
-                       arg_idx = Idx;
                        if (!ec.IsStatic)
                                arg_idx++;
                        
-                       return this;
+                       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;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+                       
                        if (arg_idx <= 255)
-                               ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
+                               ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
                        else
-                               ec.ig.Emit (OpCodes.Ldarg, arg_idx);
+                               ig.Emit (OpCodes.Ldarg, arg_idx);
+
+                       if (!is_ref)
+                               return;
+
+                       //
+                       // If we are a reference, we loaded on the stack a pointer
+                       // Now lets load the real value
+                       //
+                       LoadFromPtr (ig, type, true);
                }
 
                public void EmitAssign (EmitContext ec, Expression source)
                {
-                       source.Emit (ec);
+                       ILGenerator ig = ec.ig;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       if (is_ref){
+                               // Load the pointer
+                               if (arg_idx <= 255)
+                                       ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
+                               else
+                                       ig.Emit (OpCodes.Ldarg, arg_idx);
+                       }
                        
-                       if (arg_idx <= 255)
-                               ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
-                       else
-                               ec.ig.Emit (OpCodes.Starg, arg_idx);
+                       source.Emit (ec);
+
+                       if (is_ref)
+                               StoreFromPtr (ig, type);
+                       else {
+                               if (arg_idx <= 255)
+                                       ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
+                               else
+                                       ig.Emit (OpCodes.Starg, arg_idx);
+                       }
                        
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
                        if (arg_idx <= 255)
                                ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
                        else
@@ -1913,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;
@@ -1936,10 +2709,21 @@ namespace Mono.CSharp {
                        if (ArgType == AType.Expression)
                                return expr != null;
 
-                       if (expr.ExprClass != ExprClass.Variable){
-                               Report.Error (206, loc,
-                                             "A property or indexer can not be passed as an out or ref " +
-                                             "parameter");
+                       if (expr.eclass != ExprClass.Variable){
+                               //
+                               // 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;
                        }
                                
@@ -1948,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);
                }
        }
@@ -1964,12 +2769,13 @@ namespace Mono.CSharp {
 
                Expression expr;
                MethodBase method = null;
-                       
+               bool is_base;
+               
                static Hashtable method_parameter_cache;
 
                static Invocation ()
                {
-                       method_parameter_cache = new Hashtable ();
+                       method_parameter_cache = new PtrHashtable ();
                }
                        
                //
@@ -2005,7 +2811,7 @@ namespace Mono.CSharp {
                                return (ParameterData) pd;
 
                        
-                       ip = TypeContainer.LookupParametersByBuilder (mb);
+                       ip = TypeManager.LookupParametersByBuilder (mb);
                        if (ip != null){
                                method_parameter_cache [mb] = ip;
 
@@ -2019,58 +2825,12 @@ 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
                ///            0 if a->q or neither is better 
                /// </summary>
-               static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, bool use_standard,
-                                            Location loc)
+               static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
                {
                        Type argument_type = a.Type;
                        Expression argument_expr = a.Expr;
@@ -2105,8 +2865,8 @@ namespace Mono.CSharp {
                        // taken place.  We dont do constant folding yet.
                        //
 
-                       if (argument_expr is IntLiteral){
-                               IntLiteral ei = (IntLiteral) argument_expr;
+                       if (argument_expr is IntConstant){
+                               IntConstant ei = (IntConstant) argument_expr;
                                int value = ei.Value;
                                
                                if (p == TypeManager.sbyte_type){
@@ -2136,33 +2896,26 @@ namespace Mono.CSharp {
                                        if (value >= 0)
                                                return 1;
                                }
-                       } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
-                               LongLiteral ll = (LongLiteral) argument_expr;
+                       } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){
+                               LongConstant lc = (LongConstant) argument_expr;
                                
                                if (p == TypeManager.uint64_type){
-                                       if (ll.Value > 0)
+                                       if (lc.Value > 0)
                                                return 1;
                                }
                        }
 
                        if (q == null) {
-
-                               Expression tmp;
-
-                               if (use_standard)
-                                       tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
-                               else
-                                       tmp = ConvertImplicit (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)
@@ -2196,78 +2949,100 @@ namespace Mono.CSharp {
                /// </remarks>
                static int BetterFunction (EmitContext ec, ArrayList args,
                                           MethodBase candidate, MethodBase best,
-                                          bool use_standard, Location loc)
+                                          bool expanded_form, Location loc)
                {
                        ParameterData candidate_pd = GetParameterData (candidate);
                        ParameterData best_pd;
                        int argument_count;
+               
 
                        if (args == null)
                                argument_count = 0;
                        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 (best == null) {
-                               if (candidate_pd.Count == argument_count) {
-                                       int x = 0;
-                                       for (int j = argument_count; j > 0;) {
-                                               j--;
-                                               
-                                               Argument a = (Argument) args [j];
-                                               
-                                               x = BetterConversion (
-                                                       ec, a, candidate_pd.ParameterType (j), null,
-                                                       use_standard, loc);
-                                               
-                                               if (x <= 0)
-                                                       break;
-                                       }
-                                       
-                                       if (x > 0)
-                                               return 1;
-                                       else
-                                               return 0;
-                                       
-                               } else
+                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+                               if (cand_count != argument_count)
                                        return 0;
-                       }
-
-                       best_pd = GetParameterData (best);
+                       
+                       if (best == null) {
+                               int x = 0;
 
-                       if (candidate_pd.Count == argument_count && best_pd.Count == argument_count) {
-                               int rating1 = 0, rating2 = 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--;
-                                       int x, y;
-                                       
+
                                        Argument a = (Argument) args [j];
+                                       Type t = candidate_pd.ParameterType (j);
 
-                                       x = BetterConversion (ec, a, candidate_pd.ParameterType (j),
-                                                             best_pd.ParameterType (j), use_standard, loc);
-                                       y = BetterConversion (ec, a, best_pd.ParameterType (j),
-                                                             candidate_pd.ParameterType (j), use_standard,
-                                                             loc);
+                                       if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                               if (expanded_form)
+                                                       t = t.GetElementType ();
+
+                                       x = BetterConversion (ec, a, t, null, loc);
                                        
-                                       rating1 += x;
-                                       rating2 += y;
+                                       if (x <= 0)
+                                               break;
                                }
-
-                               if (rating1 > rating2)
+                               
+                               if (x > 0)
                                        return 1;
                                else
                                        return 0;
-                       } else
-                               return 0;
+                       }
+
+                       best_pd = GetParameterData (best);
+
+                       int rating1 = 0, rating2 = 0;
                        
+                       for (int j = 0; j < argument_count; ++j) {
+                               int x, y;
+                               
+                               Argument a = (Argument) args [j];
+
+                               Type ct = candidate_pd.ParameterType (j);
+                               Type bt = best_pd.ParameterType (j);
+
+                               if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                       if (expanded_form)
+                                               ct = ct.GetElementType ();
+
+                               if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                       if (expanded_form)
+                                               bt = bt.GetElementType ();
+                               
+                               x = BetterConversion (ec, a, ct, bt, loc);
+                               y = BetterConversion (ec, a, bt, ct, loc);
+
+                               if (x < y)
+                                       return 0;
+                               
+                               rating1 += x;
+                               rating2 += y;
+                       }
+
+                       if (rating1 > rating2)
+                               return 1;
+                       else
+                               return 0;
                }
 
                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;
@@ -2275,7 +3050,7 @@ namespace Mono.CSharp {
                        
                        for (int i = count; i > 0; ) {
                                i--;
-                               
+
                                sb.Append (pd.ParameterDesc (count - i - 1));
                                if (i != 0)
                                        sb.Append (", ");
@@ -2367,21 +3142,49 @@ namespace Mono.CSharp {
                        
                        int pd_count = pd.Count;
 
+                       if (pd_count == 0)
+                               return false;
+                       
                        if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
                                return false;
-
+                       
                        if (pd_count - 1 > arg_count)
                                return false;
-
-                       // 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
+                       
+                       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.
+
+                       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))
                                        return false;
                        }
@@ -2448,21 +3251,18 @@ 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.
                ///
                /// </summary>
                public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
-                                                         ArrayList Arguments, Location loc,
-                                                         bool use_standard)
+                                                         ArrayList Arguments, Location loc)
                {
                        ArrayList afm = new ArrayList ();
                        int best_match_idx = -1;
                        MethodBase method = null;
                        int argument_count;
+                       ArrayList candidates = new ArrayList ();
                        
                        for (int i = me.Methods.Length; i > 0; ){
                                i--;
@@ -2473,7 +3273,9 @@ namespace Mono.CSharp {
                                if (!IsApplicable (Arguments, candidate))
                                        continue;
 
-                               x = BetterFunction (ec, Arguments, candidate, method, use_standard, loc);
+                               candidates.Add (candidate);
+
+                               x = BetterFunction (ec, Arguments, candidate, method, false, loc);
                                
                                if (x == 0)
                                        continue;
@@ -2493,16 +3295,28 @@ namespace Mono.CSharp {
                        // since if they were applicable in their normal form, they would have been selected
                        // above anyways
                        //
+                       bool chose_params_expanded = false;
+                       
                        if (best_match_idx == -1) {
 
+                               candidates = new ArrayList ();
                                for (int i = me.Methods.Length; i > 0; ) {
                                        i--;
                                        MethodBase candidate = me.Methods [i];
 
-                                       if (IsParamsMethodApplicable (Arguments, candidate)) {
+                                       if (!IsParamsMethodApplicable (Arguments, candidate))
+                                               continue;
+
+                                       candidates.Add (candidate);
+
+                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
+
+                                       if (x == 0)
+                                               continue;
+                                       else {
                                                best_match_idx = i;
                                                method = me.Methods [best_match_idx];
-                                               break;
+                                               chose_params_expanded = true;
                                        }
                                }
                        }
@@ -2511,7 +3325,8 @@ namespace Mono.CSharp {
                        // Now we see if we can at least find a method with the same number of arguments
                        //
                        ParameterData pd;
-                       
+                       int method_count = 0;
+
                        if (best_match_idx == -1) {
                                
                                for (int i = me.Methods.Length; i > 0;) {
@@ -2522,7 +3337,7 @@ namespace Mono.CSharp {
                                        if (pd.Count == argument_count) {
                                                best_match_idx = i;
                                                method = me.Methods [best_match_idx];
-                                               break;
+                                               method_count++;
                                        } else
                                                continue;
                                }
@@ -2530,6 +3345,40 @@ namespace Mono.CSharp {
 
                        if (method == null)
                                return null;
+
+
+                       //
+                       // Now check that there are no ambiguities i.e the selected method
+                       // should be better than all the others
+                       //
+
+                       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 : " + FullMethodDesc (candidate));
+                                       //Console.WriteLine ("Best : " + FullMethodDesc (method));
+                                       Report.Error (
+                                               121, loc,
+                                               "Ambiguous call when selecting function due to implicit casts");
+                                       return null;
+                               }
+                       }
                        
                        // And now convert implicitly, each argument to the required type
                        
@@ -2537,32 +3386,23 @@ namespace Mono.CSharp {
                        int pd_count = pd.Count;
 
                        for (int j = 0; j < argument_count; j++) {
-
                                Argument a = (Argument) Arguments [j];
                                Expression a_expr = a.Expr;
                                Type parameter_type = pd.ParameterType (j);
 
-                               //
-                               // Note that we need to compare against the element type
-                               // when we have a params method
-                               //
-                               if (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS) {
-                                       if (j >= pd_count - 1) 
-                                               parameter_type = pd.ParameterType (pd_count - 1).GetElementType ();
-                               }
+                               if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS && chose_params_expanded)
+                                       parameter_type = parameter_type.GetElementType ();
 
                                if (a.Type != parameter_type){
                                        Expression conv;
                                        
-                                       if (use_standard)
-                                               conv = ConvertImplicitStandard (ec, a_expr, parameter_type, Location.Null);
-                                       else
-                                               conv = ConvertImplicit (ec, a_expr, parameter_type, Location.Null);
+                                       conv = ConvertImplicitStandard (ec, a_expr, parameter_type, Location.Null);
 
                                        if (conv == null) {
                                                if (!Location.IsNull (loc)) {
                                                        Error (1502, loc,
-                                                       "The best overloaded match for method '" + FullMethodDesc (method)+
+                                                              "The best overloaded match for method '" +
+                                                              FullMethodDesc (method) +
                                                               "' has some invalid arguments");
                                                        Error (1503, loc,
                                                         "Argument " + (j+1) +
@@ -2572,8 +3412,6 @@ namespace Mono.CSharp {
                                                return null;
                                        }
                                        
-                       
-                                       
                                        //
                                        // Update the argument with the implicit conversion
                                        //
@@ -2586,8 +3424,11 @@ namespace Mono.CSharp {
                                }
                                
                                if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
-                                   pd.ParameterModifier (j) != Parameter.Modifier.PARAMS) {
+                                   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");
@@ -2598,25 +3439,20 @@ namespace Mono.CSharp {
                                        }
                                        return null;
                                }
-                               
-                               
                        }
                        
                        return method;
                }
                
-               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
-                                                         ArrayList Arguments, Location loc)
-               {
-                       return OverloadResolve (ec, me, Arguments, loc, false);
-               }
-                       
                public override Expression DoResolve (EmitContext ec)
                {
                        //
                        // 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;
@@ -2661,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;
                }
@@ -2678,7 +3521,7 @@ namespace Mono.CSharp {
                        LocalBuilder array;
                        
                        array = ig.DeclareLocal (Type.GetType (array_type));
-                       IntLiteral.EmitInt (ig, count);
+                       IntConstant.EmitInt (ig, count);
                        ig.Emit (OpCodes.Newarr, t);
                        ig.Emit (OpCodes.Stloc, array);
 
@@ -2687,7 +3530,7 @@ namespace Mono.CSharp {
                                a = (Argument) arguments [j];
                                
                                ig.Emit (OpCodes.Ldloc, array);
-                               IntLiteral.EmitInt (ig, j - idx);
+                               IntConstant.EmitInt (ig, j - idx);
                                a.Emit (ec);
                                
                                ArrayAccess.EmitStoreOpcode (ig, t);
@@ -2731,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)
                {
@@ -2739,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"
                                //
@@ -2749,27 +3610,37 @@ namespace Mono.CSharp {
                                        // Push the instance expression
                                        //
                                        if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
+                                               //
+                                               // Special case: calls to a function declared in a 
+                                               // reference-type with a value-type argument need
+                                               // to have their value boxed.  
 
                                                struct_call = true;
-
-                                               //
-                                               // If the expression implements IMemoryLocation, then
-                                               // we can optimize and use AddressOf on the
-                                               // return.
-                                               //
-                                               // If not we have to use some temporary storage for
-                                               // it.
-                                               if (instance_expr is IMemoryLocation)
-                                                       ((IMemoryLocation) instance_expr).AddressOf (ec);
-                                               else {
-                                                       Type t = instance_expr.Type;
-                                                       
+                                               if (method.DeclaringType.IsValueType){
+                                                       //
+                                                       // If the expression implements IMemoryLocation, then
+                                                       // we can optimize and use AddressOf on the
+                                                       // return.
+                                                       //
+                                                       // If not we have to use some temporary storage for
+                                                       // it.
+                                                       if (instance_expr is IMemoryLocation){
+                                                               ((IMemoryLocation)instance_expr).
+                                                                       AddressOf (ec, AddressOp.LoadStore);
+                                                       }
+                                                       else {
+                                                               Type t = instance_expr.Type;
+                                                               
+                                                               instance_expr.Emit (ec);
+                                                               LocalBuilder temp = ig.DeclareLocal (t);
+                                                               ig.Emit (OpCodes.Stloc, temp);
+                                                               ig.Emit (OpCodes.Ldloca, temp);
+                                                       }
+                                               } else {
                                                        instance_expr.Emit (ec);
-                                                       LocalBuilder temp = ig.DeclareLocal (t);
-                                                       ig.Emit (OpCodes.Stloc, temp);
-                                                       ig.Emit (OpCodes.Ldloca, temp);
-                                               }
-                                       } else 
+                                                       ig.Emit (OpCodes.Box, instance_expr.Type);
+                                               } 
+                                       } else
                                                instance_expr.Emit (ec);
                                }
                        }
@@ -2777,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
@@ -2793,7 +3664,8 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        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)
@@ -2845,7 +3717,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       type = ec.TypeContainer.LookupType (RequestedType, false);
+                       type = RootContext.LookupType (ec.TypeContainer, RequestedType, false, loc);
                        
                        if (type == null)
                                return null;
@@ -2855,13 +3727,19 @@ namespace Mono.CSharp {
                        if (IsDelegate)
                                return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
                        
-                       Expression ml;
-                       
-                       ml = MemberLookup (ec, type, ".ctor", false,
-                                          MemberTypes.Constructor, AllBindingsFlags, loc);
-                       
                        bool is_struct = false;
                        is_struct = type.IsSubclassOf (TypeManager.value_type);
+                       eclass = ExprClass.Value;
+
+                       //
+                       // SRE returns a match for .ctor () on structs (the object constructor), 
+                       // so we have to manually ignore it.
+                       //
+                       if (is_struct && Arguments == null)
+                               return this;
+                       
+                       Expression ml;
+                       ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, AllBindingFlags, loc);
                        
                        if (! (ml is MethodGroupExpr)){
                                if (!is_struct){
@@ -2883,6 +3761,7 @@ namespace Mono.CSharp {
 
                                method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
                                                                     Arguments, loc);
+                               
                        }
                        
                        if (method == null && !is_struct) {
@@ -2891,8 +3770,6 @@ namespace Mono.CSharp {
                                       "this argument list");
                                return null;
                        }
-                       
-                       eclass = ExprClass.Value;
                        return this;
                }
 
@@ -2905,34 +3782,54 @@ namespace Mono.CSharp {
                // need_value_on_stack.  The code *might* leave a value on the stack
                // so it must be popped manually
                //
+               // If we are dealing with a ValueType, we have a few
+               // situations to deal with:
+               //
+               //    * The target is a ValueType, and we have been provided
+               //      the instance (this is easy, we are being assigned).
+               //
+               //    * The target of New is being passed as an argument,
+               //      to a boxing operation or a function that takes a
+               //      ValueType.
+               //
+               //      In this case, we need to create a temporary variable
+               //      that is the argument of New.
+               //
                // Returns whether a value is left on the stack
                //
                bool DoEmit (EmitContext ec, bool need_value_on_stack)
                {
-                       if (method == null){
-                               IMemoryLocation ml = (IMemoryLocation) value_target;
+                       bool is_value_type = type.IsSubclassOf (TypeManager.value_type);
+                       ILGenerator ig = ec.ig;
+                       
+                       if (is_value_type){
+                               IMemoryLocation ml;
 
-                               ml.AddressOf (ec);
-                       } else {
-                               Invocation.EmitArguments (ec, method, Arguments);
-                               ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
-                               return true;
+                               if (value_target == null)
+                                       value_target = new LocalTemporary (ec, type);
+
+                               ml = (IMemoryLocation) value_target;
+                               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)
@@ -2954,10 +3851,10 @@ namespace Mono.CSharp {
        /// <remarks>
        ///   There are two possible scenarios here: one is an array creation
        ///   expression that specifies the dimensions and optionally the
-       ///   initialization data
+       ///   initialization data and the other which does not need dimensions
+       ///   specified but where initialization data is mandatory.
        /// </remarks>
        public class ArrayCreation : ExpressionStatement {
-
                string RequestedType;
                string Rank;
                ArrayList Initializers;
@@ -2967,17 +3864,22 @@ namespace Mono.CSharp {
                MethodBase method = null;
                Type array_element_type;
                bool IsOneDimensional = false;
-               
                bool IsBuiltinType = false;
+               bool ExpectInitializers = false;
 
                int dimensions = 0;
                Type underlying_type;
 
                ArrayList ArrayData;
-               ArrayList ArrayExprs;
 
-               ArrayList Bounds;
+               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)
                {
@@ -2990,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)
@@ -3004,6 +3905,7 @@ namespace Mono.CSharp {
                        string tmp = rank.Substring (rank.LastIndexOf ("["));
 
                        dimensions = tmp.Length - 1;
+                       ExpectInitializers = true;
                }
 
                public static string FormArrayType (string base_type, int idx_count, string rank)
@@ -3015,8 +3917,9 @@ namespace Mono.CSharp {
                        sb.Append ("[");
                        for (int i = 1; i < idx_count; i++)
                                sb.Append (",");
-                       sb.Append ("]");
                        
+                       sb.Append ("]");
+
                        return sb.ToString ();
                 }
 
@@ -3027,8 +3930,9 @@ namespace Mono.CSharp {
                        sb.Append ("[");
                        for (int i = 1; i < idx_count; i++)
                                sb.Append (",");
+                       
                        sb.Append ("]");
-
+                       
                        sb.Append (rank);
 
                        string val = sb.ToString ();
@@ -3049,48 +3953,47 @@ namespace Mono.CSharp {
                                if (!a.Resolve (ec, loc))
                                        return false;
                                
-                               Expression e = Expression.Reduce (ec, a.Expr);
-                               
-                               if (!(e is Literal)) {
+                               if (!(a.Expr is Constant)) {
                                        Report.Error (150, loc, "A constant value is expected");
                                        return false;
                                }
                                
-                               int value = (int) ((Literal) e).GetValue ();
+                               int value = (int) ((Constant) a.Expr).GetValue ();
                                
                                if (value != probe.Count) {
                                        error178 ();
                                        return false;
                                }
                                
-                               Bounds.Add (value);
+                               Bounds [idx] = value;
                        }
                        
                        foreach (object o in probe) {
-
                                if (o is ArrayList) {
                                        bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
                                        if (!ret)
                                                return false;
-                                       
                                } else {
                                        Expression tmp = (Expression) o;
                                        tmp = tmp.Resolve (ec);
-                                       tmp = Expression.Reduce (ec, tmp);
-
-                                       // Handle initialization from vars, fields etc.
+                                       if (tmp == null)
+                                               continue;
                                        
-                                       Expression conv = ConvertImplicitRequired (ec, tmp, underlying_type, loc);
+                                       // Handle initialization from vars, fields etc.
+
+                                       Expression conv = ConvertImplicitRequired (
+                                               ec, tmp, underlying_type, loc);
                                        
                                        if (conv == null) 
                                                return false;
 
-                                       if (tmp is Literal)
-                                               ArrayData.Add (((Literal) tmp).GetValue ());
-                                       else
-                                               ArrayData.Add ((object) 0);
-
-                                       ArrayExprs.Add (tmp);
+                                       if (conv is StringConstant)
+                                               ArrayData.Add (conv);
+                                       else if (conv is Constant) {
+                                               ArrayData.Add (conv);
+                                               num_automatic_initializers++;
+                                       } else
+                                               ArrayData.Add (conv);
                                }
                        }
 
@@ -3098,19 +4001,22 @@ namespace Mono.CSharp {
                }
                
                public void UpdateIndices (EmitContext ec)
-               {                       
+               {
+                       int i = 0;
                        for (ArrayList probe = Initializers; probe != null;) {
-
-                               if (probe [0] is ArrayList) {
-                                       Expression e = new IntLiteral (probe.Count);
+                               if (probe.Count > 0 && probe [0] is ArrayList) {
+                                       Expression e = new IntConstant (probe.Count);
                                        Arguments.Add (new Argument (e, Argument.AType.Expression));
-                                       Bounds.Add (probe.Count);
+
+                                       Bounds [i++] =  probe.Count;
+                                       
                                        probe = (ArrayList) probe [0];
                                        
                                } else {
-                                       Expression e = new IntLiteral (probe.Count);
+                                       Expression e = new IntConstant (probe.Count);
                                        Arguments.Add (new Argument (e, Argument.AType.Expression));
-                                       Bounds.Add (probe.Count);
+
+                                       Bounds [i++] = probe.Count;
                                        probe = null;
                                }
                        }
@@ -3119,18 +4025,22 @@ namespace Mono.CSharp {
                
                public bool ValidateInitializers (EmitContext ec)
                {
-                       if (Initializers == null)
-                               return true;
-
-                       underlying_type = ec.TypeContainer.LookupType (RequestedType, false);
-
+                       if (Initializers == null) {
+                               if (ExpectInitializers)
+                                       return false;
+                               else
+                                       return true;
+                       }
+                       
+                       underlying_type = RootContext.LookupType (
+                               ec.TypeContainer, RequestedType, false, loc);
+                       
                        //
                        // We use this to store all the date values in the order in which we
                        // will need to store them in the byte blob later
                        //
                        ArrayData = new ArrayList ();
-                       ArrayExprs = new ArrayList ();
-                       Bounds = new ArrayList ();
+                       Bounds = new Hashtable ();
                        
                        bool ret;
 
@@ -3161,21 +4071,33 @@ namespace Mono.CSharp {
                {
                        int arg_count;
 
+                       //
+                       // First step is to validate the initializers and fill
+                       // in any missing bits
+                       //
                        if (!ValidateInitializers (ec))
                                return null;
 
                        if (Arguments == null)
                                arg_count = 0;
-                       else
+                       else {
                                arg_count = Arguments.Count;
+                               for (int i = arg_count; i > 0;){
+                                       --i;
+                                       Argument a = (Argument) Arguments [i];
+                                       
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+                               }
+                       }
                        
                        string array_type = FormArrayType (RequestedType, arg_count, Rank);
-
                        string element_type = FormElementType (RequestedType, arg_count, Rank);
 
-                       type = ec.TypeContainer.LookupType (array_type, false);
+                       type = RootContext.LookupType (ec.TypeContainer, array_type, false, loc);
                        
-                       array_element_type = ec.TypeContainer.LookupType (element_type, false);
+                       array_element_type = RootContext.LookupType (
+                               ec.TypeContainer, element_type, false, loc);
                        
                        if (type == null)
                                return null;
@@ -3189,11 +4111,11 @@ namespace Mono.CSharp {
                        IsBuiltinType = TypeManager.IsBuiltinType (type);
                        
                        if (IsBuiltinType) {
-                               
+
                                Expression ml;
                                
-                               ml = MemberLookup (ec, type, ".ctor", false, MemberTypes.Constructor,
-                                                  AllBindingsFlags, loc);
+                               ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
+                                                  AllBindingFlags, loc);
                                
                                if (!(ml is MethodGroupExpr)){
                                        report118 (loc, ml, "method group");
@@ -3206,18 +4128,8 @@ namespace Mono.CSharp {
                                        return null;
                                }
                                
-                               if (Arguments != null) {
-                                       for (int i = arg_count; i > 0;){
-                                               --i;
-                                               Argument a = (Argument) Arguments [i];
-                                               
-                                               if (!a.Resolve (ec, loc))
-                                                       return null;
-                                       }
-                               }
-                               
                                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");
@@ -3229,7 +4141,7 @@ namespace Mono.CSharp {
                                
                        } else {
 
-                               ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
+                               ModuleBuilder mb = RootContext.ModuleBuilder;
 
                                ArrayList args = new ArrayList ();
                                if (Arguments != null){
@@ -3237,9 +4149,6 @@ namespace Mono.CSharp {
                                                --i;
                                                Argument a = (Argument) Arguments [i];
                                                
-                                               if (!a.Resolve (ec, loc))
-                                                       return null;
-                                               
                                                args.Add (a.Type);
                                        }
                                }
@@ -3253,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");
@@ -3270,145 +4179,267 @@ 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.char_type ||
-                                underlying_type == TypeManager.bool_type)      
-                               factor = 1;
-                       else if (underlying_type == TypeManager.short_type ||
-                                underlying_type == TypeManager.ushort_type)
-                               factor = 2;
-                       else {  
-                               Report.Error (-100, loc, "Unhandled type in MakeByteBlob!!");
+                       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) {
+                               object v = ArrayData [i];
+
+                               if (v is EnumConstant)
+                                       v = ((EnumConstant) v).Child;
                                
-                               if (underlying_type == TypeManager.int64_type ||
-                                   underlying_type == TypeManager.uint64_type){
-                                       long val = (long) ArrayData [i];
+                               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;
 
-                                       for (int j = 0; j < factor; ++j) {
-                                               data [(i * factor) + 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) {
-
-                                       // FIXME : How does one get the bits out ?
-                                       
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((float) v);
+                                                       
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
+                                       }
                                } else if (underlying_type == TypeManager.double_type) {
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((double) v);
 
-                                       // FIXME : Same here. '&' and '>>' don't work !
-                                 
-                                 
-                               } else {
-                                       int val = (int) ArrayData [i];
-                                 
-                                       for (int j = 0; j < factor; ++j) {
-                                               data [(i * factor) + j] = (byte) (val & 0xFF);
-                                               val = val >> 8;
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
                                        }
-                               }
+                               } else if (underlying_type == TypeManager.char_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((char) v);
+                                               
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (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);
+                                       }
+                               } 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) {
+                                       if (!(v is Expression)){
+                                               int 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);
+                                       }
+                               } 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");
+
+                                idx += factor;
                        }
 
                        return data;
                }
-               
-               public override void Emit (EmitContext ec)
+
+               //
+               // Emits the initializers for the array
+               //
+               void EmitStaticInitializers (EmitContext ec, bool is_expression)
                {
+                       //
+                       // First, the static data
+                       //
+                       FieldBuilder fb;
                        ILGenerator ig = ec.ig;
                        
-                       if (IsOneDimensional) {
-                               Invocation.EmitArguments (ec, null, Arguments);
-                               ig.Emit (OpCodes.Newarr, array_element_type);
-                               
-                       } else {
-                               Invocation.EmitArguments (ec, null, Arguments);
-
-                               if (IsBuiltinType)
-                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
-                               else
-                                       ig.Emit (OpCodes.Newobj, (MethodInfo) method);
+                       byte [] data = MakeByteBlob (ArrayData, underlying_type, loc);
+                       
+                       if (data != null) {
+                               fb = RootContext.MakeStaticData (data);
+
+                               if (is_expression)
+                                       ig.Emit (OpCodes.Dup);
+                               ig.Emit (OpCodes.Ldtoken, fb);
+                               ig.Emit (OpCodes.Call,
+                                        TypeManager.void_initializearray_array_fieldhandle);
                        }
+               }
+               
+               //
+               // Emits pieces of the array that can not be computed at compile
+               // time (variables and string locations).
+               //
+               // This always expect the top value on the stack to be the array
+               //
+               void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+               {
+                       ILGenerator ig = ec.ig;
+                       int dims = Bounds.Count;
+                       int [] current_pos = new int [dims];
+                       int top = ArrayData.Count;
+                       LocalBuilder temp = ig.DeclareLocal (type);
 
-                       if (Initializers != null) {
+                       ig.Emit (OpCodes.Stloc, temp);
 
-                               if (underlying_type != TypeManager.string_type) {
-                                       FieldBuilder fb;
-                                       
-                                       byte [] data = MakeByteBlob (ArrayData, underlying_type, loc);
-                                       
-                                       if (data != null) {
-                                               fb = ec.TypeContainer.RootContext.MakeStaticData (data);
-                                               
-                                               ig.Emit (OpCodes.Dup);
-                                               ig.Emit (OpCodes.Ldtoken, fb);
-                                               ig.Emit (OpCodes.Call, TypeManager.void_initializearray_array_fieldhandle);
-                                       }
-                               }
+                       MethodInfo set = null;
 
-                                       //for (int i = 0; i < ArrayExprs.Count; ++i) {
-//                                     Expression e = (Expression) ArrayExprs [i];
+                       if (dims != 1){
+                               Type [] args;
+                               ModuleBuilder mb = null;
+                               mb = RootContext.ModuleBuilder;
+                               args = new Type [dims + 1];
 
-//                                     if (e is Literal && !(e is StringLiteral))
-//                                             continue;
+                               int j;
+                               for (j = 0; j < dims; j++)
+                                       args [j] = TypeManager.int32_type;
 
-//                                     Expression elem_access = GenerateAccessExpr (i);
-//                                     elem_access = elem_access.Resolve (ec);
+                               args [j] = array_element_type;
+                               
+                               set = mb.GetArrayMethod (
+                                       type, "Set",
+                                       CallingConventions.HasThis | CallingConventions.Standard,
+                                       TypeManager.void_type, args);
+                       }
+                       
+                       for (int i = 0; i < top; i++){
 
-//                                     if (elem_access == null)
-//                                             return;
-                                       
-//                                     Expression assign = new Assign (elem_access, e, loc);
+                               Expression e = null;
 
-//                                     assign = assign.Resolve (ec);
+                               if (ArrayData [i] is Expression)
+                                       e = (Expression) ArrayData [i];
+
+                               if (e != null) {
+                                       //
+                                       // Basically we do this for string literals and
+                                       // other non-literal expressions
+                                       //
+                                       if (e is StringConstant || !(e is Constant) || num_automatic_initializers <= 2) {
 
-//                                     if (assign == null)
-//                                             return;
+                                               ig.Emit (OpCodes.Ldloc, temp);
 
-//                                     assign.Emit (ec);
-//                             }
+                                               for (int idx = dims; idx > 0; ) {
+                                                       idx--;
+                                                       IntConstant.EmitInt (ig, current_pos [idx]);
+                                               }
+
+                                               e.Emit (ec);
+                                               
+                                               if (dims == 1)
+                                                       ArrayAccess.EmitStoreOpcode (ig, array_element_type);
+                                               else 
+                                                       ig.Emit (OpCodes.Call, set);
+                                               
+                                       }
+                               }
+                               
+                               //
+                               // Advance counter
+                               //
+                               for (int j = 0; j < dims; j++){
+                                       current_pos [j]++;
+                                       if (current_pos [j] < (int) Bounds [j])
+                                               break;
+                                       current_pos [j] = 0;
+                               }
                        }
+
+                       if (is_expression)
+                               ig.Emit (OpCodes.Ldloc, temp);
                }
 
-               Expression GenerateAccessExpr (int i)
+               void DoEmit (EmitContext ec, bool is_statement)
                {
-                       int n_dims = Bounds.Count;
+                       ILGenerator ig = ec.ig;
                        
-                       int [] indices = new int [n_dims];
-
-                       for (int j = 0; j < n_dims; ++j) {
-                               indices [j]++;
-
-
-                               // FIXME : Please finish me !! I can't be completed by dumb idiots
-                               // like Ravi !! :-)
+                       if (IsOneDimensional) {
+                               Invocation.EmitArguments (ec, null, Arguments);
+                               ig.Emit (OpCodes.Newarr, array_element_type);
                                
+                       } else {
+                               Invocation.EmitArguments (ec, null, Arguments);
+
+                               if (IsBuiltinType) 
+                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+                               else 
+                                       ig.Emit (OpCodes.Newobj, (MethodInfo) method);
+                       }
+                       
+                       if (Initializers != null){
+                               //
+                               // FIXME: Set this variable correctly.
+                               // 
+                               bool dynamic_initializers = true;
+
+                               if (underlying_type != TypeManager.string_type &&
+                                   underlying_type != TypeManager.object_type) {
+                                       if (num_automatic_initializers > 2)
+                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+                               }
                                
+                               if (dynamic_initializers)
+                                       EmitDynamicInitializers (ec, !is_statement);
                        }
-
-                       return null;
                }
                
+               public override void Emit (EmitContext ec)
+               {
+                       DoEmit (ec, false);
+               }
+
                public override void EmitStatement (EmitContext ec)
                {
-                       Emit (ec);
-                       ec.ig.Emit (OpCodes.Pop);
+                       DoEmit (ec, true);
                }
                
        }
@@ -3438,7 +4469,7 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public Expression DoResolveLValue (EmitContext ec)
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        DoResolve (ec);
                        
@@ -3461,9 +4492,18 @@ 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.Ldarga_S, (byte) 0);
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+
+                       // FIMXE
+                       // FIGURE OUT WHY LDARG_S does not work
+                       //
+                       // consider: struct X { int val; int P { set { val = value; }}}
+                       //
+                       // Yes, this looks very bad. Look at `NOTAS' for
+                       // an explanation.
+                       // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
                }
        }
 
@@ -3473,15 +4513,18 @@ namespace Mono.CSharp {
        public class TypeOf : Expression {
                public readonly string QueriedType;
                Type typearg;
+               Location loc;
                
-               public TypeOf (string queried_type)
+               public TypeOf (string queried_type, Location l)
                {
                        QueriedType = queried_type;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       typearg = ec.TypeContainer.LookupType (QueriedType, false);
+                       typearg = RootContext.LookupType (
+                               ec.TypeContainer, QueriedType, false, loc);
 
                        if (typearg == null)
                                return null;
@@ -3503,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);
                }
        }
 
@@ -3544,48 +4600,45 @@ namespace Mono.CSharp {
                        }
                }
 
-               void error176 (Location loc, string name)
+               static void error176 (Location loc, string name)
                {
                        Report.Error (176, loc, "Static member `" +
                                      name + "' cannot be accessed " +
                                      "with an instance reference, qualify with a " +
                                      "type name instead");
                }
-               
-               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;
+               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
+               {
+                       if (left_original == null)
+                               return false;
 
-                       if (expr is SimpleName){
-                               SimpleName child_expr = (SimpleName) expr;
+                       if (!(left_original is SimpleName))
+                               return false;
 
-                               expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
+                       SimpleName sn = (SimpleName) left_original;
 
-                               return expr.Resolve (ec);
-                       }
-                                       
-                       member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
+                       Type t = RootContext.LookupType (ec.TypeContainer, sn.Name, true, loc);
+                       if (t != null)
+                               return true;
 
-                       if (member_lookup == null)
-                               return null;
-                       
+                       return false;
+               }
+               
+               public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
+                                                             Expression left, Location loc,
+                                                             Expression left_original)
+               {
                        //
                        // Method Groups
                        //
                        if (member_lookup is MethodGroupExpr){
                                MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
-                               
+
                                //
                                // Type.MethodGroup
                                //
-                               if (expr is TypeExpr){
+                               if (left is TypeExpr){
                                        if (!mg.RemoveInstanceMethods ()){
                                                SimpleName.Error120 (loc, mg.Methods [0].Name); 
                                                return null;
@@ -3597,20 +4650,53 @@ 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 ()){
+                                                       SimpleName.Error120 (loc, mg.Methods [0].Name);
+                                                       return null;
+                                               }
+                                               return member_lookup;
+                                       }
+                                       
                                        error176 (loc, mg.Methods [0].Name);
                                        return null;
                                }
                                
-                               mg.InstanceExpression = expr;
+                               mg.InstanceExpression = left;
                                        
                                return member_lookup;
+#endif
                        }
 
                        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);
+                                               object real_value = ((Constant) c.Expr).GetValue ();
+
+                                               return Constantify (real_value, fi.FieldType);
+                                       }
+                               }
+
                                if (fi.IsLiteral) {
                                        Type t = fi.FieldType;
                                        Type decl_type = fi.DeclaringType;
@@ -3622,28 +4708,38 @@ namespace Mono.CSharp {
                                                o = fi.GetValue (fi);
                                        
                                        if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
-                                               Expression enum_member = MemberLookup (ec, decl_type, "value__",
-                                                                                      false, loc); 
+                                               Expression enum_member = MemberLookup (
+                                                       ec, decl_type, "value__", MemberTypes.Field,
+                                                       AllBindingFlags, loc); 
 
                                                Enum en = TypeManager.LookupEnum (decl_type);
 
-                                               Expression e;
+                                               Constant c;
                                                if (en != null)
-                                                       e = Literalize (o, en.UnderlyingType);
+                                                       c = Constantify (o, en.UnderlyingType);
                                                else 
-                                                       e = Literalize (o, enum_member.Type);
+                                                       c = Constantify (o, enum_member.Type);
                                                
-                                               e.Resolve (ec);
-                                               return new EnumLiteral (e, decl_type);
+                                               return new EnumConstant (c, decl_type);
                                        }
                                        
-                                       Expression exp = Literalize (o, t);
-                                       exp.Resolve (ec);
+                                       Expression exp = Constantify (o, t);
+
+                                       if (!(left is TypeExpr)) {
+                                               error176 (loc, fe.FieldInfo.Name);
+                                               return null;
+                                       }
                                        
                                        return exp;
                                }
+
+                               if (fi.FieldType.IsPointer && !ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
                                
-                               if (expr is TypeExpr){
+                               if (left is TypeExpr){
+                                       // and refers to a type name or an 
                                        if (!fe.FieldInfo.IsStatic){
                                                error176 (loc, fe.FieldInfo.Name);
                                                return null;
@@ -3651,10 +4747,13 @@ namespace Mono.CSharp {
                                        return member_lookup;
                                } else {
                                        if (fe.FieldInfo.IsStatic){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
+
                                                error176 (loc, fe.FieldInfo.Name);
                                                return null;
                                        }
-                                       fe.InstanceExpression = expr;
+                                       fe.InstanceExpression = left;
 
                                        return fe;
                                }
@@ -3663,7 +4762,7 @@ namespace Mono.CSharp {
                        if (member_lookup is PropertyExpr){
                                PropertyExpr pe = (PropertyExpr) member_lookup;
 
-                               if (expr is TypeExpr){
+                               if (left is TypeExpr){
                                        if (!pe.IsStatic){
                                                SimpleName.Error120 (loc, pe.PropertyInfo.Name);
                                                return null;
@@ -3671,23 +4770,152 @@ namespace Mono.CSharp {
                                        return pe;
                                } else {
                                        if (pe.IsStatic){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
                                                error176 (loc, pe.PropertyInfo.Name);
                                                return null;
                                        }
-                                       pe.InstanceExpression = expr;
-
+                                       pe.InstanceExpression = left;
+                                       
                                        return pe;
                                }
                        }
+
+                       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, MemberTypes.Event, AllBindingFlags, loc);
+
+                               if (ml != null) {
+                                       MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
+
+                                       if (mi == null) {
+                                               //
+                                               // If this happens, then we have an event with its own
+                                               // accessors and private field etc so there's no need
+                                               // to transform ourselves : we should instead flag an error
+                                               //
+                                               Assign.error70 (ee.EventInfo, loc);
+                                               return null;
+                                       }
+
+                                       ml = ExprClassFromMemberInfo (ec, mi, loc);
+                                       
+                                       if (ml == null) {
+                                               Report.Error (-200, loc, "Internal error!!");
+                                               return null;
+                                       }
+                                       return ResolveMemberAccess (ec, ml, left, loc, left_original);
+                               }
+
+                               if (left is TypeExpr) {
+                                       if (!ee.IsStatic) {
+                                               SimpleName.Error120 (loc, ee.EventInfo.Name);
+                                               return null;
+                                       }
+
+                                       return ee;
+
+                               } else {
+                                       if (ee.IsStatic) {
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return ee;
+                                                   
+                                               error176 (loc, ee.EventInfo.Name);
+                                               return null;
+                                       }
+
+                                       ee.InstanceExpression = left;
+
+                                       return ee;
+                               }
+                       }
+
+                       if (member_lookup is TypeExpr){
+                               member_lookup.Resolve (ec);
+                               return member_lookup;
+                       }
                        
-                       Console.WriteLine ("Support for [" + member_lookup + "] is not present yet");
+                       Console.WriteLine ("Left is: " + left);
+                       Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
                        Environment.Exit (0);
                        return null;
                }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are the sole users of ResolveWithSimpleName (ie, the only
+                       // ones that can cope with it
+                       //
+                       Expression original = expr;
+                       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);
+                       }
+                                       
+                       //
+                       // 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
+                       //
+
+                       Type expr_type = expr.Type;
+                       if ((expr is TypeExpr) && (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){
+                                               Constant c = Constantify (value, en.UnderlyingType);
+                                               return new EnumConstant (c, expr_type);
+                                       }
+                               }
+                       }
+
+                       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){
+                               Report.Error (117, loc, "`" + expr_type + "' does not contain a " +
+                                             "definition for `" + Identifier + "'");
+                                             
+                               return null;
+                       }
+
+                       return ResolveMemberAccess (ec, member_lookup, expr, loc, original);
+               }
 
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Should not happen I think");
+                       throw new Exception ("Should not happen");
                }
        }
 
@@ -3705,12 +4933,16 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       Expr = Expr.Resolve (ec);
+                       bool last_const_check = ec.ConstantCheckState;
 
+                       ec.ConstantCheckState = true;
+                       Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
+                       
                        if (Expr == null)
                                return null;
 
-                       eclass = Expr.ExprClass;
+                       eclass = Expr.eclass;
                        type = Expr.Type;
                        return this;
                }
@@ -3718,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;
                }
                
        }
@@ -3740,12 +4975,16 @@ 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;
 
-                       eclass = Expr.ExprClass;
+                       eclass = Expr.eclass;
                        type = Expr.Type;
                        return this;
                }
@@ -3753,18 +4992,22 @@ 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;
                }
                
        }
 
        /// <summary>
-       ///   An Element Access expression.  During semantic
-       ///   analysis these are transformed into IndexerAccess or
-       ///   ArrayAccess expressions
+       ///   An Element Access expression.
+       ///
+       ///   During semantic analysis these are transformed into 
+       ///   IndexerAccess or ArrayAccess 
        /// </summary>
        public class ElementAccess : Expression {
                public ArrayList  Arguments;
@@ -3775,11 +5018,15 @@ namespace Mono.CSharp {
                {
                        Expr = e;
 
+                       loc  = l;
+                       
+                       if (e_list == null)
+                               return;
+                       
                        Arguments = new ArrayList ();
                        foreach (Expression tmp in e_list)
                                Arguments.Add (new Argument (tmp, Argument.AType.Expression));
                        
-                       loc  = l;
                }
 
                bool CommonResolve (EmitContext ec)
@@ -3802,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))
@@ -3814,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);
                }
@@ -3825,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);
                }
@@ -3840,7 +5114,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements array access 
        /// </summary>
-       public class ArrayAccess : Expression, IAssignMethod {
+       public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
                //
                // Points to our "data" repository
                //
@@ -3854,13 +5128,12 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       if (ea.Expr.ExprClass != ExprClass.Variable) {
+                       if (ea.Expr.eclass != ExprClass.Variable) {
                                report118 (ea.loc, ea.Expr, "variable");
                                return null;
                        }
 
                        Type t = ea.Expr.Type;
-
                        if (t.GetArrayRank () != ea.Arguments.Count){
                                Report.Error (22, ea.loc,
                                              "Incorrect number of indexes for array " +
@@ -3869,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;
@@ -3880,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);
@@ -3902,7 +5180,10 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldelem_R8);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
-                       else
+                       else if (type.IsValueType){
+                               ig.Emit (OpCodes.Ldelema, type);
+                               ig.Emit (OpCodes.Ldobj, type);
+                       } else 
                                ig.Emit (OpCodes.Ldelem_Ref);
                }
 
@@ -3912,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);
@@ -3926,9 +5208,62 @@ 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);
                }
+
+               MethodInfo FetchGetMethod ()
+               {
+                       ModuleBuilder mb = RootContext.ModuleBuilder;
+                       Type [] args = new Type [ea.Arguments.Count];
+                       MethodInfo get;
+                       
+                       int i = 0;
+                               
+                       foreach (Argument a in ea.Arguments)
+                               args [i++] = a.Type;
+                       
+                       get = mb.GetArrayMethod (
+                               ea.Expr.Type, "Get",
+                               CallingConventions.HasThis |
+                               CallingConventions.Standard,
+                               type, args);
+                       return get;
+               }
+                               
+
+               MethodInfo FetchAddressMethod ()
+               {
+                       ModuleBuilder mb = RootContext.ModuleBuilder;
+                       Type [] args = new Type [ea.Arguments.Count];
+                       MethodInfo address;
+                       string ptr_type_name;
+                       Type ret_type;
+                       int i = 0;
+                       
+                       ptr_type_name = type.FullName + "&";
+                       ret_type = Type.GetType (ptr_type_name);
+                       
+                       //
+                       // It is a type defined by the source code we are compiling
+                       //
+                       if (ret_type == null){
+                               ret_type = mb.GetType (ptr_type_name);
+                       }
+                       
+                       foreach (Argument a in ea.Arguments)
+                               args [i++] = a.Type;
+                       
+                       address = mb.GetArrayMethod (
+                               ea.Expr.Type, "Address",
+                               CallingConventions.HasThis |
+                               CallingConventions.Standard,
+                               ret_type, args);
+
+                       return address;
+               }
                
                public override void Emit (EmitContext ec)
                {
@@ -3943,22 +5278,10 @@ namespace Mono.CSharp {
                        if (rank == 1)
                                EmitLoadOpcode (ig, type);
                        else {
-                               ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
-                               Type [] args = new Type [ea.Arguments.Count];
-                               MethodInfo get;
-                               
-                               int i = 0;
+                               MethodInfo method;
                                
-                               foreach (Argument a in ea.Arguments)
-                                       args [i++] = a.Type;
-                               
-                               get = mb.GetArrayMethod (
-                                       ea.Expr.Type, "Get",
-                                       CallingConventions.HasThis |
-                                       CallingConventions.Standard,
-                                       type, args);
-                               
-                               ig.Emit (OpCodes.Call, get);
+                               method = FetchGetMethod ();
+                               ig.Emit (OpCodes.Call, method);
                        }
                }
 
@@ -3972,13 +5295,24 @@ namespace Mono.CSharp {
                        foreach (Argument a in ea.Arguments)
                                a.Expr.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);
 
-                       Type t = source.Type;
                        if (rank == 1)
                                EmitStoreOpcode (ig, t);
                        else {
-                               ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
+                               ModuleBuilder mb = RootContext.ModuleBuilder;
                                Type [] args = new Type [ea.Arguments.Count + 1];
                                MethodInfo set;
                                
@@ -3998,6 +5332,24 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Call, set);
                        }
                }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+                       
+                       ea.Expr.Emit (ec);
+
+                       foreach (Argument a in ea.Arguments)
+                               a.Expr.Emit (ec);
+
+                       if (rank == 1){
+                               ig.Emit (OpCodes.Ldelema, type);
+                       } else {
+                               MethodInfo address = FetchAddressMethod ();
+                               ig.Emit (OpCodes.Call, address);
+                       }
+               }
        }
 
        
@@ -4089,7 +5441,7 @@ namespace Mono.CSharp {
 
                        if (ilist == null)
                                ilist = Indexers.GetIndexersForType (
-                                       indexer_type, ec.TypeContainer.RootContext.TypeManager, ea.loc);
+                                       indexer_type, RootContext.TypeManager, ea.loc);
 
 
                        //
@@ -4107,6 +5459,11 @@ namespace Mono.CSharp {
                        }
 
                        type = get.ReturnType;
+                       if (type.IsPointer && !ec.InUnsafe){
+                               UnsafeError (ea.loc);
+                               return null;
+                       }
+                       
                        eclass = ExprClass.IndexerAccess;
                        return this;
                }
@@ -4118,7 +5475,7 @@ namespace Mono.CSharp {
 
                        if (ilist == null)
                                ilist = Indexers.GetIndexersForType (
-                                       indexer_type, ec.TypeContainer.RootContext.TypeManager, ea.loc);
+                                       indexer_type, RootContext.TypeManager, ea.loc);
 
                        if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
                                set_arguments = (ArrayList) ea.Arguments.Clone ();
@@ -4142,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);
                }
 
                //
@@ -4152,42 +5509,101 @@ 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);
                }
        }
-       
-       public class BaseAccess : Expression {
 
-               public enum BaseAccessType : byte {
-                       Member,
-                       Indexer
-               };
+       /// <summary>
+       ///   The base operator for method names
+       /// </summary>
+       public class BaseAccess : Expression {
+               string member;
+               Location loc;
                
-               public readonly BaseAccessType BAType;
-               public readonly string         Member;
-               public readonly ArrayList      Arguments;
+               public BaseAccess (string member, Location l)
+               {
+                       this.member = member;
+                       loc = l;
+               }
 
-               public BaseAccess (BaseAccessType t, string member, ArrayList args)
+               public override Expression DoResolve (EmitContext ec)
                {
-                       BAType = t;
-                       Member = member;
-                       Arguments = args;
+                       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, loc);
+                       if (member_lookup == null)
+                               return null;
+
+                       Expression left;
+                       
+                       if (ec.IsStatic)
+                               left = new TypeExpr (base_type);
+                       else
+                               left = ec.This;
+                       
+                       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)
+               {
+                       throw new Exception ("Should never be called"); 
+               }
+       }
+
+       /// <summary>
+       ///   The base indexer operator
+       /// </summary>
+       public class BaseIndexerAccess : Expression {
+               ArrayList Arguments;
+               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");
                }
        }
-
+       
        /// <summary>
        ///   This class exists solely to pass the Type around and to be a dummy
        ///   that can be passed to the conversion functions (this is used by
@@ -4217,6 +5633,16 @@ namespace Mono.CSharp {
                {
                        // nothing, as we only exist to not do anything.
                }
+
+               //
+               // This is just because we might want to reuse this bad boy
+               // instead of creating gazillions of EmptyExpressions.
+               // (CanConvertImplicit uses it)
+               //
+               public void SetType (Type t)
+               {
+                       type = t;
+               }
        }
 
        public class UserCast : Expression {
@@ -4251,7 +5677,6 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Call, (ConstructorInfo) method);
 
                }
-
        }
 
        // <summary>
@@ -4278,15 +5703,21 @@ namespace Mono.CSharp {
                        if (left == null)
                                return null;
 
-                       if (left.ExprClass != ExprClass.Type){
+                       if (left.eclass != ExprClass.Type){
                                report118 (loc, left, "type");
                                return null;
                        }
                        
-                       type = ec.TypeContainer.LookupType (left.Type.FullName + dim, false);
+                       type = RootContext.LookupType (
+                               ec.TypeContainer, left.Type.FullName + dim, false, loc);
                        if (type == null)
                                return null;
 
+                       if (!ec.InUnsafe && type.IsPointer){
+                               UnsafeError (loc);
+                               return null;
+                       }
+                       
                        eclass = ExprClass.Type;
                        return this;
                }
@@ -4296,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);
+               }
+       }
 }