2004-08-03 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mbas / expression.cs
index 7c019350275957c2983728f3f3037077be2d083e..ceed21db3885a84b2039a265a8b3ad9f82db3eef 100644 (file)
@@ -9,10 +9,9 @@
 //
 #define USE_OLD
 
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
        using System;
        using System.Collections;
-       using System.Diagnostics;
        using System.Reflection;
        using System.Reflection.Emit;
        using System.Text;
@@ -26,13 +25,14 @@ namespace Mono.CSharp {
                ArrayList args;
                MethodInfo mi;
 
-               StaticCallExpr (MethodInfo m, ArrayList a)
+               StaticCallExpr (MethodInfo m, ArrayList a, Location l)
                {
                        mi = m;
                        args = a;
 
                        type = m.ReturnType;
                        eclass = ExprClass.Value;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -65,13 +65,13 @@ namespace Mono.CSharp {
                        if (method == null)
                                return null;
 
-                       return new StaticCallExpr ((MethodInfo) method, args);
+                       return new StaticCallExpr ((MethodInfo) method, args, loc);
                }
 
                public override void EmitStatement (EmitContext ec)
                {
                        Emit (ec);
-                       if (type != TypeManager.void_type)
+                       if (TypeManager.TypeToCoreType (type) != TypeManager.void_type)
                                ec.ig.Emit (OpCodes.Pop);
                }
        }
@@ -93,7 +93,6 @@ namespace Mono.CSharp {
 
                public Operator Oper;
                public Expression Expr;
-               Location   loc;
                
                public Unary (Operator op, Expression expr, Location loc)
                {
@@ -141,10 +140,10 @@ namespace Mono.CSharp {
 
                void Error23 (Type t)
                {
-                       Report.Error (
-                               23, loc, "Operator " + OperName (Oper) +
-                               " cannot be applied to operand of type `" +
-                               TypeManager.CSharpName (t) + "'");
+                       Error (
+                               23, "Operator " + OperName (Oper) +
+                               " cannot be applied to operand of type '" +
+                               TypeManager.MonoBASIC_Name (t) + "'");
                }
 
                /// <remarks>
@@ -153,7 +152,7 @@ namespace Mono.CSharp {
                ///   FIXME: a minus constant -128 sbyte cant be turned into a
                ///   constant byte.
                /// </remarks>
-               static Expression TryReduceNegative (Expression expr)
+               static Expression TryReduceNegative (Constant expr)
                {
                        Expression e = null;
                        
@@ -169,6 +168,12 @@ namespace Mono.CSharp {
                        }
                        else if (expr is LongConstant)
                                e = new LongConstant (-((LongConstant) expr).Value);
+                       else if (expr is ULongConstant){
+                               ulong value = ((ULongConstant) expr).Value;
+
+                               if (value < 9223372036854775809)
+                                       return new LongConstant(-(long)value);
+                       }
                        else if (expr is FloatConstant)
                                e = new FloatConstant (-((FloatConstant) expr).Value);
                        else if (expr is DoubleConstant)
@@ -181,26 +186,36 @@ namespace Mono.CSharp {
                                e = new IntConstant (-((UShortConstant) expr).Value);
                        return e;
                }
-               
-               Expression Reduce (EmitContext ec, Expression e)
+
+               // <summary>
+               //   This routine will attempt to simplify the unary expression when the
+               //   argument is a constant.  The result is returned in 'result' and the
+               //   function returns true or false depending on whether a reduction
+               //   was performed or not
+               // </summary>
+               bool Reduce (EmitContext ec, Constant e, out Expression result)
                {
                        Type expr_type = e.Type;
                        
                        switch (Oper){
                        case Operator.UnaryPlus:
-                               return e;
+                               result = e;
+                               return true;
                                
                        case Operator.UnaryNegation:
-                               return TryReduceNegative (e);
+                               result = TryReduceNegative (e);
+                               return true;
                                
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
+                                       result = null;
                                        Error23 (expr_type);
-                                       return null;
+                                       return false;
                                }
                                
                                BoolConstant b = (BoolConstant) e;
-                               return new BoolConstant (!(b.Value));
+                               result = new BoolConstant (!(b.Value));
+                               return true;
                                
                        case Operator.OnesComplement:
                                if (!((expr_type == TypeManager.int32_type) ||
@@ -208,31 +223,48 @@ namespace Mono.CSharp {
                                      (expr_type == TypeManager.int64_type) ||
                                      (expr_type == TypeManager.uint64_type) ||
                                      (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+                                       result = null;
                                        Error23 (expr_type);
-                                       return null;
+                                       return false;
                                }
 
                                if (e is EnumConstant){
                                        EnumConstant enum_constant = (EnumConstant) e;
+                                       Expression reduced;
                                        
-                                       Expression reduced = Reduce (ec, enum_constant.Child);
+                                       if (Reduce (ec, enum_constant.Child, out reduced)){
+                                               result = new EnumConstant ((Constant) reduced, enum_constant.Type);
+                                               return true;
+                                       } else {
+                                               result = null;
+                                               return false;
+                                       }
+                               }
 
-                                       return new EnumConstant ((Constant) reduced, enum_constant.Type);
+                               if (expr_type == TypeManager.int32_type){
+                                       result = new IntConstant (~ ((IntConstant) e).Value);
+                               } else if (expr_type == TypeManager.uint32_type){
+                                       result = new UIntConstant (~ ((UIntConstant) e).Value);
+                               } else if (expr_type == TypeManager.int64_type){
+                                       result = new LongConstant (~ ((LongConstant) e).Value);
+                               } else if (expr_type == TypeManager.uint64_type){
+                                       result = new ULongConstant (~ ((ULongConstant) e).Value);
+                               } else {
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
                                }
+                               return true;
 
-                               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);
+                       case Operator.AddressOf:
+                               result = this;
+                               return false;
 
-                               Error23 (expr_type);
-                               return null;
+                       case Operator.Indirection:
+                               result = this;
+                               return false;
                        }
-                       throw new Exception ("Can not constant fold");
+                       throw new Exception ("Can not constant fold: " + Oper.ToString());
                }
 
                Expression ResolveOperator (EmitContext ec)
@@ -270,10 +302,17 @@ namespace Mono.CSharp {
                        //
                        // Step 2: Default operations on CLI native types.
                        //
-                       if (Expr is Constant)
-                               return Reduce (ec, Expr);
 
-                       if (Oper == Operator.LogicalNot){
+                       // Attempt to use a constant folding operation.
+                       if (Expr is Constant){
+                               Expression result;
+                               
+                               if (Reduce (ec, (Constant) Expr, out result))
+                                       return result;
+                       }
+
+                       switch (Oper){
+                       case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
                                        Error23 (Expr.Type);
                                        return null;
@@ -281,9 +320,8 @@ namespace Mono.CSharp {
                                
                                type = TypeManager.bool_type;
                                return this;
-                       }
 
-                       if (Oper == Operator.OnesComplement) {
+                       case Operator.OnesComplement:
                                if (!((expr_type == TypeManager.int32_type) ||
                                      (expr_type == TypeManager.uint32_type) ||
                                      (expr_type == TypeManager.int64_type) ||
@@ -316,32 +354,69 @@ namespace Mono.CSharp {
                                }
                                type = expr_type;
                                return this;
-                       }
 
-                       if (Oper == Operator.UnaryPlus) {
+                       case Operator.AddressOf:
+                               if (Expr.eclass != ExprClass.Variable){
+                                       Error (211, "Cannot take the address of non-variables");
+                                       return null;
+                               }
+                               
+                               if (!ec.InUnsafe) {
+                                       UnsafeError (loc); 
+                                       return null;
+                               }
+                               
+                               if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){
+                                       return null;
+                               }
+                               
+                               string ptr_type_name = Expr.Type.FullName + "*";
+                               type = TypeManager.LookupType (ptr_type_name);
+                               
+                               return this;
+
+                       case Operator.Indirection:
+                               if (!ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+                               
+                               if (!expr_type.IsPointer){
+                                       Error (
+                                               193,
+                                               "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, loc);
+                       
+                       case Operator.UnaryPlus:
                                //
                                // A plus in front of something is just a no-op, so return the child.
                                //
                                return Expr;
-                       }
 
-                       //
-                       // Deals with -literals
-                       // int     operator- (int x)
-                       // long    operator- (long x)
-                       // float   operator- (float f)
-                       // double  operator- (double d)
-                       // decimal operator- (decimal d)
-                       //
-                       if (Oper == Operator.UnaryNegation){
-                               Expression e = null;
+                       case Operator.UnaryNegation:
+                               //
+                               // Deals with -literals
+                               // int     operator- (int x)
+                               // long    operator- (long x)
+                               // float   operator- (float f)
+                               // double  operator- (double d)
+                               // decimal operator- (decimal d)
+                               //
+                               Expression expr = null;
 
                                //
                                // transform - - expr into expr
                                //
                                if (Expr is Unary){
                                        Unary unary = (Unary) Expr;
-
+                                       
                                        if (unary.Oper == Operator.UnaryNegation)
                                                return unary.Expr;
                                }
@@ -370,7 +445,7 @@ namespace Mono.CSharp {
 
                                if (expr_type == TypeManager.uint64_type){
                                        //
-                                       // FIXME: Handle exception of `long value'
+                                       // FIXME: Handle exception of 'long value'
                                        // -92233720368547758087 (-2^63) to be wrote as
                                        // decimal integer literal.
                                        //
@@ -383,87 +458,42 @@ namespace Mono.CSharp {
                                        return this;
                                }
                                
-                               e = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
-                               if (e != null){
-                                       Expr = e;
-                                       type = e.Type;
+                               expr = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
                                        return this;
                                } 
 
-                               e = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
-                               if (e != null){
-                                       Expr = e;
-                                       type = e.Type;
+                               expr = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
                                        return this;
                                }
 
-                               e = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
-                               if (e != null){
-                                       Expr = e;
-                                       type = e.Type;
+                               expr = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
                                        return this;
                                }
-
+                               
                                Error23 (expr_type);
                                return null;
                        }
 
-                       if (Oper == Operator.AddressOf){
-                               if (Expr.eclass != ExprClass.Variable){
-                                       Error (211, loc, "Cannot take the address of non-variables");
-                                       return null;
-                               }
-
-                               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 = CodeGen.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 (Oper) + "' defined for type '" +
-                              TypeManager.CSharpName (expr_type) + "'");
+                       Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" +
+                              TypeManager.MonoBASIC_Name (expr_type) + "'");
                        return null;
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       Expr = Expr.Resolve (ec);
+                       if (Oper == Operator.AddressOf)
+                               Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
+                       else
+                               Expr = Expr.Resolve (ec);
                        
                        if (Expr == null)
                                return null;
@@ -508,7 +538,7 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///   This will emit the child expression for `ec' avoiding the logical
+               ///   This will emit the child expression for 'ec' avoiding the logical
                ///   not.  The parent will take care of changing brfalse/brtrue
                /// </summary>
                public void EmitLogicalNot (EmitContext ec)
@@ -536,11 +566,12 @@ namespace Mono.CSharp {
                LocalTemporary temporary;
                bool have_temporary;
                
-               public Indirection (Expression expr)
+               public Indirection (Expression expr, Location l)
                {
                        this.expr = expr;
-                       this.type = expr.Type.GetElementType ();
+                       this.type = TypeManager.TypeToCoreType (expr.Type.GetElementType ());
                        eclass = ExprClass.Variable;
+                       loc = l;
                }
 
                void LoadExprValue (EmitContext ec)
@@ -627,7 +658,7 @@ namespace Mono.CSharp {
        /// classes (indexers require temporary access;  overloaded require method)
        ///
        /// Maybe we should have classes PreIncrement, PostIncrement, PreDecrement,
-       /// PostDecrement, that way we could save the `Mode' byte as well.  
+       /// PostDecrement, that way we could save the 'Mode' byte as well.  
        /// </remarks>
        public class UnaryMutator : ExpressionStatement {
                public enum Mode : byte {
@@ -635,7 +666,6 @@ namespace Mono.CSharp {
                }
                
                Mode mode;
-               Location loc;
                Expression expr;
                LocalTemporary temp_storage;
 
@@ -659,14 +689,14 @@ namespace Mono.CSharp {
                
                void Error23 (Type t)
                {
-                       Report.Error (
-                               23, loc, "Operator " + OperName (mode) + 
-                               " cannot be applied to operand of type `" +
-                               TypeManager.CSharpName (t) + "'");
+                       Error (
+                               23, "Operator " + OperName (mode) + 
+                               " cannot be applied to operand of type '" +
+                               TypeManager.MonoBASIC_Name (t) + "'");
                }
 
                /// <summary>
-               ///   Returns whether an object of type `t' can be incremented
+               ///   Returns whether an object of type 't' can be incremented
                ///   or decremented with add/sub (ie, basically whether we can
                ///   use pre-post incr-decr operations on it, but it is not a
                ///   System.Decimal, which we require operator overloading to catch)
@@ -746,12 +776,12 @@ namespace Mono.CSharp {
 
                                return null;
                        } else {
-                               report118 (loc, expr, "variable, indexer or property access");
+                               expr.Error118 ("variable, indexer or property access");
                                return null;
                        }
 
-                       Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
-                              TypeManager.CSharpName (expr_type) + "'");
+                       Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
+                              TypeManager.MonoBASIC_Name (expr_type) + "'");
                        return null;
                }
 
@@ -918,20 +948,19 @@ namespace Mono.CSharp {
        }
 
        /// <summary>
-       ///   Base class for the `Is' and `As' classes. 
+       ///   Base class for the 'Is' and 'As' classes. 
        /// </summary>
        ///
        /// <remarks>
-       ///   FIXME: Split this in two, and we get to save the `Operator' Oper
+       ///   FIXME: Split this in two, and we get to save the 'Operator' Oper
        ///   size. 
        /// </remarks>
        public abstract class Probe : Expression {
-               public readonly string ProbeType;
+               public readonly Expression ProbeType;
                protected Expression expr;
                protected Type probe_type;
-               protected Location loc;
                
-               public Probe (Expression expr, string probe_type, Location l)
+               public Probe (Expression expr, Expression probe_type, Location l)
                {
                        ProbeType = probe_type;
                        loc = l;
@@ -946,7 +975,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       probe_type = RootContext.LookupType (ec.DeclSpace, ProbeType, false, loc);
+                       probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
 
                        if (probe_type == null)
                                return null;
@@ -958,10 +987,10 @@ namespace Mono.CSharp {
        }
 
        /// <summary>
-       ///   Implementation of the `is' operator.
+       ///   Implementation of the 'is' operator.
        /// </summary>
        public class Is : Probe {
-               public Is (Expression expr, string probe_type, Location l)
+               public Is (Expression expr, Expression probe_type, Location l)
                        : base (expr, probe_type, l)
                {
                }
@@ -989,7 +1018,7 @@ namespace Mono.CSharp {
                                IntConstant.EmitInt (ig, 1);
                                return;
                        case Action.LeaveOnStack:
-                               // the `e != null' rule.
+                               // the 'e != null' rule.
                                return;
                        case Action.Probe:
                                ig.Emit (OpCodes.Isinst, probe_type);
@@ -1004,7 +1033,7 @@ namespace Mono.CSharp {
                {
                        Expression e = base.DoResolve (ec);
 
-                       if (e == null)
+                       if ((e == null) || (expr == null))
                                return null;
 
                        Type etype = expr.Type;
@@ -1042,16 +1071,16 @@ namespace Mono.CSharp {
                        
                        if (RootContext.WarningLevel >= 1){
                                if (warning_always_matches)
-                                       Report.Warning (
-                                               183, loc,
-                                               "The expression is always of type `" +
-                                               TypeManager.CSharpName (probe_type) + "'");
+                                       Warning (
+                                               183,
+                                               "The expression is always of type '" +
+                                               TypeManager.MonoBASIC_Name (probe_type) + "'");
                                else if (warning_never_matches){
                                        if (!(probe_type.IsInterface || expr.Type.IsInterface))
-                                               Report.Warning (
-                                                       184, loc,
-                                                       "The expression is never of type `" +
-                                                       TypeManager.CSharpName (probe_type) + "'");
+                                               Warning (
+                                                       184,
+                                                       "The expression is never of type '" +
+                                                       TypeManager.MonoBASIC_Name (probe_type) + "'");
                                }
                        }
 
@@ -1060,10 +1089,10 @@ namespace Mono.CSharp {
        }
 
        /// <summary>
-       ///   Implementation of the `as' operator.
+       ///   Implementation of the 'as' operator.
        /// </summary>
        public class As : Probe {
-               public As (Expression expr, string probe_type, Location l)
+               public As (Expression expr, Expression probe_type, Location l)
                        : base (expr, probe_type, l)
                {
                }
@@ -1083,9 +1112,9 @@ namespace Mono.CSharp {
                static void Error_CannotConvertType (Type source, Type target, Location loc)
                {
                        Report.Error (
-                               39, loc, "as operator can not convert from `" +
-                               TypeManager.CSharpName (source) + "' to `" +
-                               TypeManager.CSharpName (target) + "'");
+                               39, loc, "as operator can not convert from '" +
+                               TypeManager.MonoBASIC_Name (source) + "' to '" +
+                               TypeManager.MonoBASIC_Name (target) + "'");
                }
                
                public override Expression DoResolve (EmitContext ec)
@@ -1098,6 +1127,13 @@ namespace Mono.CSharp {
                        type = probe_type;
                        eclass = ExprClass.Value;
                        Type etype = expr.Type;
+
+                       if (TypeManager.IsValueType (probe_type)){
+                               Report.Error (77, loc, "The as operator should be used with a reference type only (" +
+                                             TypeManager.MonoBASIC_Name (probe_type) + " is a value type)");
+                               return null;
+                       
+                       }
                        
                        e = ConvertImplicit (ec, expr, probe_type, loc);
                        if (e != null){
@@ -1125,13 +1161,14 @@ namespace Mono.CSharp {
        public class Cast : Expression {
                Expression target_type;
                Expression expr;
-               Location   loc;
+               bool runtime_cast;
                        
                public Cast (Expression cast_type, Expression expr, Location loc)
                {
                        this.target_type = cast_type;
                        this.expr = expr;
                        this.loc = loc;
+                       runtime_cast = false;
                }
 
                public Expression TargetType {
@@ -1149,6 +1186,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsRuntimeCast\r
+               {
+                       get {
+                               return runtime_cast;
+                       }
+                       set{
+                               runtime_cast = value;
+                       }
+               }
+
                /// <summary>
                ///   Attempts to do a compile-time folding of a constant cast.
                /// </summary>
@@ -1175,6 +1222,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is SByteConstant){
                                sbyte v = ((SByteConstant) expr).Value;
@@ -1197,6 +1248,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is ShortConstant){
                                short v = ((ShortConstant) expr).Value;
@@ -1219,6 +1274,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is UShortConstant){
                                ushort v = ((UShortConstant) expr).Value;
@@ -1241,6 +1300,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is IntConstant){
                                int v = ((IntConstant) expr).Value;
@@ -1263,6 +1326,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is UIntConstant){
                                uint v = ((UIntConstant) expr).Value;
@@ -1285,6 +1352,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is LongConstant){
                                long v = ((LongConstant) expr).Value;
@@ -1307,6 +1378,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is ULongConstant){
                                ulong v = ((ULongConstant) expr).Value;
@@ -1329,6 +1404,10 @@ namespace Mono.CSharp {
                                        return new FloatConstant ((float) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is FloatConstant){
                                float v = ((FloatConstant) expr).Value;
@@ -1351,6 +1430,10 @@ namespace Mono.CSharp {
                                        return new ULongConstant ((ulong) v);
                                if (target_type == TypeManager.double_type)
                                        return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
                        if (expr is DoubleConstant){
                                double v = ((DoubleConstant) expr).Value;
@@ -1373,6 +1456,10 @@ namespace Mono.CSharp {
                                        return new ULongConstant ((ulong) v);
                                if (target_type == TypeManager.float_type)
                                        return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
                        }
 
                        return null;
@@ -1384,27 +1471,15 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       bool old_state = ec.OnlyLookupTypes;
-                       ec.OnlyLookupTypes = true;
-                       target_type = target_type.Resolve (ec);
-                       ec.OnlyLookupTypes = old_state;
-                       
-                       if (target_type == null){
-                               Report.Error (-10, loc, "Can not resolve type");
-                               return null;
-                       }
+                       int errors = Report.Errors;
+
+                       type = ec.DeclSpace.ResolveType (target_type, false, Location);
 
-                       if (target_type.eclass != ExprClass.Type){
-                               report118 (loc, target_type, "class");
-                               return null;
-                       }
-                       
-                       type = target_type.Type;
-                       eclass = ExprClass.Value;
-                       
                        if (type == null)
                                return null;
 
+                       eclass = ExprClass.Value;
+                       
                        if (expr is Constant){
                                Expression e = TryReduce (ec, type);
 
@@ -1412,7 +1487,7 @@ namespace Mono.CSharp {
                                        return e;
                        }
                        
-                       expr = ConvertExplicit (ec, expr, type, loc);
+                       expr = ConvertExplicit (ec, expr, type, runtime_cast, loc);
                        return expr;
                }
 
@@ -1453,8 +1528,6 @@ namespace Mono.CSharp {
                protected MethodBase method;
                ArrayList  Arguments;
 
-               Location   loc;
-
                bool DelegateOperation;
 
                // This must be kept in sync with Operator!!!
@@ -1578,16 +1651,16 @@ namespace Mono.CSharp {
                        if (expr.Type == target_type)
                                return expr;
 
-                       return ConvertImplicit (ec, expr, target_type, new Location (-1));
+                       return ConvertImplicit (ec, expr, target_type, Location.Null);
                }
 
                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)
+                               34, loc, "Operator '" + OperName (oper) 
+                               + "' is ambiguous on operands of type '"
+                               + TypeManager.MonoBASIC_Name (l) + "' "
+                               + "and '" + TypeManager.MonoBASIC_Name (r)
                                + "'");
                }
 
@@ -1679,7 +1752,7 @@ namespace Mono.CSharp {
                                        left = ConvertImplicit (ec, left, TypeManager.int64_type, loc);
                                if (r != TypeManager.int64_type)
                                        right = ConvertImplicit (ec, right, TypeManager.int64_type, loc);
-
+                               
                                type = TypeManager.int64_type;
                        } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
                                //
@@ -1735,36 +1808,26 @@ namespace Mono.CSharp {
                        } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
                                if (l != TypeManager.decimal_type)
                                        left = ConvertImplicit (ec, left, TypeManager.decimal_type, loc);
+
                                if (r != TypeManager.decimal_type)
                                        right = ConvertImplicit (ec, right, TypeManager.decimal_type, loc);
-
                                type = TypeManager.decimal_type;
                        } else {
-                               Expression l_tmp, r_tmp;
-
-                               l_tmp = ForceConversion (ec, left, TypeManager.int32_type);
-                               if (l_tmp == null)
-                                       return false;
-                               
-                               r_tmp = ForceConversion (ec, right, TypeManager.int32_type);
-                               if (r_tmp == null)
-                                       return false;
+                               left = ForceConversion (ec, left, TypeManager.int32_type);
+                               right = ForceConversion (ec, right, TypeManager.int32_type);
 
-                               left = l_tmp;
-                               right = r_tmp;
-                               
                                type = TypeManager.int32_type;
                        }
 
-                       return true;
+                       return (left != null) && (right != null);
                }
 
                static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
                {
-                       Error (19, loc,
-                              "Operator " + name + " cannot be applied to operands of type `" +
-                              TypeManager.CSharpName (l) + "' and `" +
-                              TypeManager.CSharpName (r) + "'");
+                       Report.Error (19, loc,
+                              "Operator " + name + " cannot be applied to operands of type '" +
+                              TypeManager.MonoBASIC_Name (l) + "' and '" +
+                              TypeManager.MonoBASIC_Name (r) + "'");
                }
                
                void Error_OperatorCannotBeApplied ()
@@ -1777,6 +1840,12 @@ namespace Mono.CSharp {
                        return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
                                t == TypeManager.int64_type || t == TypeManager.uint64_type);
                }
+
+               static bool is_unsigned (Type t)
+               {
+                       return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
+                               t == TypeManager.short_type || t == TypeManager.byte_type);
+               }
                                        
                Expression CheckShiftArguments (EmitContext ec)
                {
@@ -1878,6 +1947,10 @@ namespace Mono.CSharp {
                                                method = TypeManager.string_concat_object_object;
                                                right = ConvertImplicit (ec, right,
                                                                         TypeManager.object_type, loc);
+                                               if (right == null){
+                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                                       return null;
+                                               }
                                        }
                                        type = TypeManager.string_type;
 
@@ -1897,6 +1970,10 @@ namespace Mono.CSharp {
                                        
                                        method = TypeManager.string_concat_object_object;
                                        left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
+                                       if (left == null){
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                               return null;
+                                       }
                                        Arguments = new ArrayList ();
                                        Arguments.Add (new Argument (left, Argument.AType.Expression));
                                        Arguments.Add (new Argument (right, Argument.AType.Expression));
@@ -1971,6 +2048,14 @@ namespace Mono.CSharp {
                                        //
                                        return this;
                                }
+
+                               //
+                               // One of them is a valuetype, but the other one is not.
+                               //
+                               if (!l.IsValueType || !r.IsValueType) {
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
                        }
 
                        // Only perform numeric promotions on:
@@ -1988,7 +2073,12 @@ namespace Mono.CSharp {
                                                method = TypeManager.delegate_combine_delegate_delegate;
                                        else
                                                method = TypeManager.delegate_remove_delegate_delegate;
-                                       
+
+                                       if (l != r) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
                                        DelegateOperation = true;
                                        type = l;
                                        return this;
@@ -2018,13 +2108,14 @@ namespace Mono.CSharp {
                                        if (r.IsPointer && oper == Operator.Subtraction){
                                                if (r == l)
                                                        return new PointerArithmetic (
-                                                               false, left, right, TypeManager.int64_type);
+                                                               false, left, right, TypeManager.int64_type,
+                                                               loc);
                                        } else if (is_32_or_64 (r))
                                                return new PointerArithmetic (
-                                                       oper == Operator.Addition, left, right, l);
+                                                       oper == Operator.Addition, left, right, l, loc);
                                } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
                                        return new PointerArithmetic (
-                                               true, right, left, r);
+                                               true, right, left, r, loc);
                        }
                        
                        //
@@ -2035,15 +2126,21 @@ namespace Mono.CSharp {
                        if (lie || rie){
                                Expression temp;
 
+                               // U operator - (E e, E f)
+                               if (lie && rie && oper == Operator.Subtraction){
+                                       if (l == r){
+                                               type = TypeManager.EnumToUnderlying (l);
+                                               return this;
+                                       } 
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+                                       
                                //
                                // operator + (E e, U x)
+                               // operator - (E e, U x)
                                //
-                               if (oper == Operator.Addition){
-                                       if (lie && rie){
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
-
+                               if (oper == Operator.Addition || oper == Operator.Subtraction){
                                        Type enum_type = lie ? l : r;
                                        Type other_type = lie ? r : l;
                                        Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
@@ -2062,14 +2159,21 @@ namespace Mono.CSharp {
                                        temp = ConvertImplicit (ec, right, l, loc);
                                        if (temp != null)
                                                right = temp;
+                                       else {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
                                } if (!lie){
                                        temp = ConvertImplicit (ec, left, r, loc);
                                        if (temp != null){
                                                left = temp;
                                                l = r;
+                                       } else {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
                                        }
                                }
-                                
+
                                if (oper == Operator.Equality || oper == Operator.Inequality ||
                                    oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||
                                    oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){
@@ -2083,6 +2187,7 @@ namespace Mono.CSharp {
                                        type = l;
                                        return this;
                                }
+                               Error_OperatorCannotBeApplied ();
                                return null;
                        }
                        
@@ -2133,14 +2238,15 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (!DoNumericPromotions (ec, l, r)){
-                               Error_OperatorCannotBeApplied ();
+                       //
+                       // This will leave left or right set to null if there is an error
+                       //
+                       DoNumericPromotions (ec, l, r);
+                       if (left == null || right == null){
+                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                return null;
                        }
 
-                       if (left == null || right == null)
-                               return null;
-
                        //
                        // reload our cached types if required
                        //
@@ -2203,105 +2309,131 @@ namespace Mono.CSharp {
                        return ResolveOperator (ec);
                }
 
-               public bool IsBranchable ()
+               /// <remarks>
+               ///   EmitBranchable is called from Statement.EmitBoolExpression in the
+               ///   context of a conditional bool expression.  This function will return
+               ///   false if it is was possible to use EmitBranchable, or true if it was.
+               ///
+               ///   The expression's code is generated, and we will generate a branch to 'target'
+               ///   if the resulting expression value is equal to isTrue
+               /// </remarks>
+               public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (oper == Operator.Equality ||
-                           oper == Operator.Inequality ||
-                           oper == Operator.LessThan ||
-                           oper == Operator.GreaterThan ||
-                           oper == Operator.LessThanOrEqual ||
-                           oper == Operator.GreaterThanOrEqual){
-                               return true;
-                       } else
+                       if (method != null)
                                return false;
-               }
 
-               /// <summary>
-               ///   This entry point is used by routines that might want
-               ///   to emit a brfalse/brtrue after an expression, and instead
-               ///   they could use a more compact notation.
-               ///
-               ///   Typically the code would generate l.emit/r.emit, followed
-               ///   by the comparission and then a brtrue/brfalse.  The comparissions
-               ///   are sometimes inneficient (there are not as complete as the branches
-               ///   look for the hacks in Emit using double ceqs).
-               ///
-               ///   So for those cases we provide EmitBranchable that can emit the
-               ///   branch with the test
-               /// </summary>
-               public void EmitBranchable (EmitContext ec, int target)
-               {
-                       OpCode opcode;
-                       bool close_target = false;
                        ILGenerator ig = ec.ig;
-                               
+
                        //
-                       // short-circuit operators
+                       // This is more complicated than it looks, but its just to avoid
+                       // duplicated tests: basically, we allow ==, !=, >, <, >= and <=
+                       // but on top of that we want for == and != to use a special path
+                       // if we are comparing against null
                        //
-                       if (oper == Operator.LogicalAnd){
-                               left.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, target);
-                               right.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, target);
-                       } else if (oper == Operator.LogicalOr){
-                               left.Emit (ec);
-                               ig.Emit (OpCodes.Brtrue, target);
-                               right.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, target);
-                       }
+                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                               bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
                                
+                               if (left is NullLiteral){
+                                       right.Emit (ec);
+                                       if (my_on_true)
+                                               ig.Emit (OpCodes.Brtrue, target);
+                                       else
+                                               ig.Emit (OpCodes.Brfalse, target);
+                                       return true;
+                               } else if (right is NullLiteral){
+                                       left.Emit (ec);
+                                       if (my_on_true)
+                                               ig.Emit (OpCodes.Brtrue, target);
+                                       else
+                                               ig.Emit (OpCodes.Brfalse, target);
+                                       return true;
+                               } 
+                       } else if (!(oper == Operator.LessThan ||
+                                     oper == Operator.GreaterThan ||
+                                     oper == Operator.LessThanOrEqual ||
+                                     oper == Operator.GreaterThanOrEqual))
+                               return false;
+                       
+
+                       
                        left.Emit (ec);
                        right.Emit (ec);
-                       
+
+                       bool isUnsigned = is_unsigned (left.Type);
+
                        switch (oper){
                        case Operator.Equality:
-                               if (close_target)
-                                       opcode = OpCodes.Beq_S;
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Beq, target);
                                else
-                                       opcode = OpCodes.Beq;
+                                       ig.Emit (OpCodes.Bne_Un, target);
                                break;
 
                        case Operator.Inequality:
-                               if (close_target)
-                                       opcode = OpCodes.Bne_Un_S;
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Bne_Un, target);
                                else
-                                       opcode = OpCodes.Bne_Un;
+                                       ig.Emit (OpCodes.Beq, target);
                                break;
 
                        case Operator.LessThan:
-                               if (close_target)
-                                       opcode = OpCodes.Blt_S;
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Blt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Blt, target);
                                else
-                                       opcode = OpCodes.Blt;
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bge_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bge, target);
                                break;
 
                        case Operator.GreaterThan:
-                               if (close_target)
-                                       opcode = OpCodes.Bgt_S;
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bgt, target);
                                else
-                                       opcode = OpCodes.Bgt;
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Ble_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Ble, target);
                                break;
 
                        case Operator.LessThanOrEqual:
-                               if (close_target)
-                                       opcode = OpCodes.Ble_S;
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Ble_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Ble, target);
                                else
-                                       opcode = OpCodes.Ble;
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bgt, target);
                                break;
 
+
                        case Operator.GreaterThanOrEqual:
-                               if (close_target)
-                                       opcode = OpCodes.Bge_S;
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bge_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bge, target);
                                else
-                                       opcode = OpCodes.Ble;
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Blt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Blt, target);
                                break;
 
                        default:
-                               throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
-                                                    + oper.ToString ());
+                               return false;
                        }
-
-                       ig.Emit (opcode, target);
+                       
+                       return true;
                }
                
                public override void Emit (EmitContext ec)
@@ -2490,12 +2622,14 @@ namespace Mono.CSharp {
                bool is_add;
 
                //
-               // We assume that `l' is always a pointer
+               // We assume that 'l' is always a pointer
                //
-               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t)
+               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t,
+                                         Location loc)
                {
                        type = t;
                        eclass = ExprClass.Variable;
+                       this.loc = loc;
                        left = l;
                        right = r;
                        is_add = is_addition;
@@ -2554,11 +2688,10 @@ namespace Mono.CSharp {
        }
        
        /// <summary>
-       ///   Implements the ternary conditiona operator (?:)
+       ///   Implements the ternary conditional operator (?:)
        /// </summary>
        public class Conditional : Expression {
                Expression expr, trueExpr, falseExpr;
-               Location loc;
                
                public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
                {
@@ -2590,6 +2723,9 @@ namespace Mono.CSharp {
                {
                        expr = expr.Resolve (ec);
 
+                       if (expr == null)
+                               return null;
+                       
                        if (expr.Type != TypeManager.bool_type)
                                expr = Expression.ConvertImplicitRequired (
                                        ec, expr, TypeManager.bool_type, loc);
@@ -2597,7 +2733,7 @@ namespace Mono.CSharp {
                        trueExpr = trueExpr.Resolve (ec);
                        falseExpr = falseExpr.Resolve (ec);
 
-                       if (expr == null || trueExpr == null || falseExpr == null)
+                       if (trueExpr == null || falseExpr == null)
                                return null;
 
                        eclass = ExprClass.Value;
@@ -2626,12 +2762,11 @@ namespace Mono.CSharp {
                                        // 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");
+                                               Error (172,
+                                                      "Can not compute type of conditional expression " +
+                                                      "as '" + TypeManager.MonoBASIC_Name (trueExpr.Type) +
+                                                      "' and '" + TypeManager.MonoBASIC_Name (falseExpr.Type) +
+                                                      "' convert implicitly to each other");
                                                return null;
                                        }
                                        type = false_type;
@@ -2640,10 +2775,10 @@ namespace Mono.CSharp {
                                        type = true_type;
                                        falseExpr = conv;
                                } else {
-                                       Error (173, loc, "The type of the conditional expression can " +
+                                       Error (173, "The type of the conditional expression can " +
                                               "not be computed because there is no implicit conversion" +
-                                              " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
-                                              " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
+                                              " from '" + TypeManager.MonoBASIC_Name (trueExpr.Type) + "'" +
+                                              " and '" + TypeManager.MonoBASIC_Name (falseExpr.Type) + "'");
                                        return null;
                                }
                        }
@@ -2666,8 +2801,7 @@ namespace Mono.CSharp {
                        Label false_target = ig.DefineLabel ();
                        Label end_target = ig.DefineLabel ();
 
-                       expr.Emit (ec);
-                       ig.Emit (OpCodes.Brfalse, false_target);
+                       Statement.EmitBoolExpression (ec, expr, false_target, false);
                        trueExpr.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -2680,11 +2814,11 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Local variables
        /// </summary>
-       public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation {
+       public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
                public readonly string Name;
                public readonly Block Block;
-               Location loc;
                VariableInfo variable_info;
+               bool is_readonly;
                
                public LocalVariableReference (Block block, string name, Location l)
                {
@@ -2694,13 +2828,55 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Variable;
                }
 
+               // Setting 'is_readonly' to false will allow you to create a writable
+               // reference to a read-only variable.  This is used by foreach and using.
+               public LocalVariableReference (Block block, string name, Location l,
+                                              VariableInfo variable_info, bool is_readonly)
+                       : this (block, name, l)
+               {
+                       this.variable_info = variable_info;
+                       this.is_readonly = is_readonly;
+               }
+
                public VariableInfo VariableInfo {
                        get {
-                               if (variable_info == null)
+                               if (variable_info == null) {
                                        variable_info = Block.GetVariableInfo (Name);
+                                       is_readonly = variable_info.ReadOnly;
+                               }
                                return variable_info;
                        }
                }
+
+               public bool IsAssigned (EmitContext ec, Location loc)
+               {
+                       return VariableInfo.IsAssigned (ec, loc);
+               }
+
+               public bool IsFieldAssigned (EmitContext ec, string name, Location loc)
+               {
+                       return VariableInfo.IsFieldAssigned (ec, name, loc);
+               }
+
+               public void SetAssigned (EmitContext ec)
+               {
+                       VariableInfo.SetAssigned (ec);
+               }
+
+               public void SetFieldAssigned (EmitContext ec, string name)
+               {
+                       VariableInfo.SetFieldAssigned (ec, name);
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               if (variable_info == null) {
+                                       variable_info = Block.GetVariableInfo (Name);
+                                       is_readonly = variable_info.ReadOnly;
+                               }
+                               return is_readonly;
+                       }
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
@@ -2713,30 +2889,29 @@ namespace Mono.CSharp {
                                return e;
                        }
 
+                       if (ec.DoFlowAnalysis && !IsAssigned (ec, loc))
+                               return null;
+
                        type = vi.VariableType;
                        return this;
                }
 
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
+                       VariableInfo vi = VariableInfo;
+
+                       if (ec.DoFlowAnalysis)
+                               ec.SetVariableAssigned (vi);
+
                        Expression e = DoResolve (ec);
 
                        if (e == null)
                                return null;
 
-                       VariableInfo vi = VariableInfo;
-
-#if BROKEN
-                       //
-                       // Sigh:  this breaks `using' and `fixed'.  Need to review that
-                       //
-                       if (vi.ReadOnly){
-                               Report.Error (
-                                       1604, loc,
-                                       "cannot assign to `" + Name + "' because it is readonly");
+                       if (is_readonly){
+                               Error (1604, "cannot assign to '" + Name + "' because it is readonly");
                                return null;
                        }
-#endif
                        
                        return this;
                }
@@ -2766,11 +2941,6 @@ namespace Mono.CSharp {
                {
                        VariableInfo vi = VariableInfo;
 
-                       if ((mode & AddressOp.Load) != 0)
-                               vi.Used = true;
-                       if ((mode & AddressOp.Store) != 0)
-                               vi.Assigned = true;
-
                        ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);
                }
        }
@@ -2779,20 +2949,65 @@ namespace Mono.CSharp {
        ///   This represents a reference to a parameter in the intermediate
        ///   representation.
        /// </summary>
-       public class ParameterReference : Expression, IAssignMethod, IMemoryLocation {
+       public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
                Parameters pars;
                String name;
                int idx;
-               public bool is_ref;
+               public Parameter.Modifier mod;
+               public bool is_ref, is_out;
                
-               public ParameterReference (Parameters pars, int idx, string name)
+               public ParameterReference (Parameters pars, int idx, string name, Location loc)
                {
                        this.pars = pars;
                        this.idx  = idx;
                        this.name = name;
+                       this.loc = loc;
                        eclass = ExprClass.Variable;
                }
 
+               public bool IsAssigned (EmitContext ec, Location loc)
+               {
+                       if (!is_out || !ec.DoFlowAnalysis)
+                               return true;
+
+                       if (!ec.CurrentBranching.IsParameterAssigned (idx)) {
+                               Report.Error (165, loc,
+                                             "Use of unassigned local variable '" + name + "'");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
+               {
+                       if (!is_out || !ec.DoFlowAnalysis)
+                               return true;
+
+                       if (ec.CurrentBranching.IsParameterAssigned (idx))
+                               return true;
+
+                       if (!ec.CurrentBranching.IsParameterAssigned (idx, field_name)) {
+                               Report.Error (170, loc,
+                                             "Use of possibly unassigned field '" + field_name + "'");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               public void SetAssigned (EmitContext ec)
+               {
+                       if (is_out && ec.DoFlowAnalysis)
+                               ec.CurrentBranching.SetParameterAssigned (idx);
+               }
+
+               public void SetFieldAssigned (EmitContext ec, string field_name)
+               {
+                       if (is_out && ec.DoFlowAnalysis)
+                               ec.CurrentBranching.SetParameterAssigned (idx, field_name);
+               }
+
                //
                // Notice that for ref/out parameters, the type exposed is not the
                // same type exposed externally.
@@ -2807,12 +3022,44 @@ namespace Mono.CSharp {
                //
                public override Expression DoResolve (EmitContext ec)
                {
-                       type = pars.GetParameterInfo (ec.DeclSpace, idx, out is_ref);
+                       type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
+                       is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
+                       is_out = (mod & Parameter.Modifier.OUT) != 0;
+                       eclass = ExprClass.Variable;
+
+                       if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
+                               return null;
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
+                       is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
+                       is_out = (mod & Parameter.Modifier.OUT) != 0;
                        eclass = ExprClass.Variable;
 
+                       if (is_out && ec.DoFlowAnalysis)
+                               ec.SetParameterAssigned (idx);
+
                        return this;
                }
 
+               static void EmitLdArg (ILGenerator ig, int x)
+               {
+                       if (x <= 255){
+                               switch (x){
+                               case 0: ig.Emit (OpCodes.Ldarg_0); break;
+                               case 1: ig.Emit (OpCodes.Ldarg_1); break;
+                               case 2: ig.Emit (OpCodes.Ldarg_2); break;
+                               case 3: ig.Emit (OpCodes.Ldarg_3); break;
+                               default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break;
+                               }
+                       } else
+                               ig.Emit (OpCodes.Ldarg, x);
+               }
+               
                //
                // This method is used by parameters that are references, that are
                // being passed as references:  we only want to pass the pointer (that
@@ -2826,11 +3073,8 @@ namespace Mono.CSharp {
 
                        if (!ec.IsStatic)
                                arg_idx++;
-                       
-                       if (arg_idx <= 255)
-                               ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
-                       else
-                               ig.Emit (OpCodes.Ldarg, arg_idx);
+
+                       EmitLdArg (ig, arg_idx);
                }
                
                public override void Emit (EmitContext ec)
@@ -2840,11 +3084,8 @@ namespace Mono.CSharp {
 
                        if (!ec.IsStatic)
                                arg_idx++;
-                       
-                       if (arg_idx <= 255)
-                               ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
-                       else
-                               ig.Emit (OpCodes.Ldarg, arg_idx);
+
+                       EmitLdArg (ig, arg_idx);
 
                        if (!is_ref)
                                return;
@@ -2864,13 +3105,8 @@ namespace Mono.CSharp {
                        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 (is_ref)
+                               EmitLdArg (ig, arg_idx);
                        
                        source.Emit (ec);
 
@@ -2882,7 +3118,6 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (OpCodes.Starg, arg_idx);
                        }
-                       
                }
 
                public void AddressOf (EmitContext ec, AddressOp mode)
@@ -2892,136 +3127,33 @@ namespace Mono.CSharp {
                        if (!ec.IsStatic)
                                arg_idx++;
 
-                       if (arg_idx <= 255)
-                               ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
-                       else
-                               ec.ig.Emit (OpCodes.Ldarga, arg_idx);
-               }
-       }
-       
-       /// <summary>
-       ///   Used for arguments to New(), Invocation()
-       /// </summary>
-       public class Argument {
-               public enum AType : byte {
-                       Expression,
-                       Ref,
-                       Out
-               };
-
-               public readonly AType ArgType;
-               public Expression expr;
-               
-               public Argument (Expression expr, AType type)
-               {
-                       this.expr = expr;
-                       this.ArgType = type;
-               }
-
-               public Expression Expr {
-                       get {
-                               return expr;
-                       }
-
-                       set {
-                               expr = value;
-                       }
-               }
-
-               public Type Type {
-                       get {
-                               if (ArgType == AType.Ref || ArgType == AType.Out)
-                                       return TypeManager.LookupType (expr.Type.ToString () + "&");
+                       if (is_ref){
+                               if (arg_idx <= 255)
+                                       ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
                                else
-                                       return expr.Type;
-                       }
-               }
-
-               public Parameter.Modifier GetParameterModifier ()
-               {
-                       if (ArgType == AType.Ref || ArgType == AType.Out)
-                               return Parameter.Modifier.OUT;
-
-                       return Parameter.Modifier.NONE;
-               }
-
-               public static string FullDesc (Argument a)
-               {
-                       return (a.ArgType == AType.Ref ? "ref " :
-                               (a.ArgType == AType.Out ? "out " : "")) +
-                               TypeManager.CSharpName (a.Expr.Type);
-               }
-               
-               public bool Resolve (EmitContext ec, Location loc)
-               {
-                       expr = expr.Resolve (ec);
-
-                       if (ArgType == AType.Expression)
-                               return expr != null;
-
-                       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;
+                                       ec.ig.Emit (OpCodes.Ldarg, arg_idx);
+                       } else {
+                               if (arg_idx <= 255)
+                                       ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
+                               else
+                                       ec.ig.Emit (OpCodes.Ldarga, arg_idx);
                        }
-                               
-                       return expr != null;
-               }
-
-               public void Emit (EmitContext ec)
-               {
-                       //
-                       // 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);
                }
        }
-
+       
+       
        /// <summary>
        ///   Invocation of methods or delegates.
        /// </summary>
        public class Invocation : ExpressionStatement {
-               public readonly ArrayList Arguments;
-               Location loc;
+               public ArrayList Arguments;
 
-               Expression expr;
+               public Expression expr;
                MethodBase method = null;
                bool is_base;
-               
+               bool is_left_hand; // Needed for late bound calls
                static Hashtable method_parameter_cache;
+               static MemberFilter CompareName;
 
                static Invocation ()
                {
@@ -3040,6 +3172,7 @@ namespace Mono.CSharp {
                        this.expr = expr;
                        Arguments = arguments;
                        loc = l;
+                       CompareName = new MemberFilter (compare_name_filter);
                }
 
                public Expression Expr {
@@ -3050,7 +3183,7 @@ namespace Mono.CSharp {
 
                /// <summary>
                ///   Returns the Parameters (a ParameterData interface) for the
-               ///   Method `mb'
+               ///   Method 'mb'
                /// </summary>
                public static ParameterData GetParameterData (MethodBase mb)
                {
@@ -3088,6 +3221,15 @@ namespace Mono.CSharp {
                        if (argument_type == null)
                                throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
 
+                       //
+                       // This is a special case since csc behaves this way. I can't find
+                       // it anywhere in the spec but oh well ...
+                       //
+                       if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+                               return 1;
+                       else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+                               return 0;
+                       
                        if (p == q)
                                return 0;
                        
@@ -3104,7 +3246,7 @@ namespace Mono.CSharp {
                        // An implicit constant expression conversion permits the following
                        // conversions:
                        //
-                       //    * A constant-expression of type `int' can be converted to type
+                       //    * A constant-expression of type 'int' can be converted to type
                        //      sbyte, byute, short, ushort, uint, ulong provided the value of
                        //      of the expression is withing the range of the destination type.
                        //
@@ -3244,7 +3386,7 @@ namespace Mono.CSharp {
                                        if (x <= 0)
                                                break;
                                }
-                               
+
                                if (x > 0)
                                        return 1;
                                else
@@ -3292,9 +3434,9 @@ namespace Mono.CSharp {
                        string ret_type = "";
 
                        if (mb is MethodInfo)
-                               ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
+                               ret_type = TypeManager.MonoBASIC_Name (((MethodInfo) mb).ReturnType) + " ";
                        
-                       StringBuilder sb = new StringBuilder (ret_type + " " + mb.Name);
+                       StringBuilder sb = new StringBuilder (ret_type + mb.Name);
                        ParameterData pd = GetParameterData (mb);
 
                        int count = pd.Count;
@@ -3398,8 +3540,10 @@ namespace Mono.CSharp {
 
                                Argument a = (Argument) arguments [i];
 
-                               Parameter.Modifier a_mod = a.GetParameterModifier ();
-                               Parameter.Modifier p_mod = pd.ParameterModifier (i);
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
 
                                if (a_mod == p_mod) {
 
@@ -3407,8 +3551,7 @@ namespace Mono.CSharp {
                                                if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
                                                        return false;
                                                                                
-                                       if (a_mod == Parameter.Modifier.REF ||
-                                           a_mod == Parameter.Modifier.OUT) {
+                                       if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
                                                Type pt = pd.ParameterType (i);
 
                                                if (!pt.IsByRef)
@@ -3434,59 +3577,226 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               static bool CheckParameterAgainstArgument (EmitContext ec, ParameterData pd, int i, Argument a, Type ptype)
+               {
+                       Parameter.Modifier a_mod = a.GetParameterModifier () &
+                               ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                       Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                               ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
+                       if (a_mod == p_mod || (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
+                               if (a_mod == Parameter.Modifier.NONE)   
+                                       if (! (ImplicitConversionExists (ec, a.Expr, ptype) || RuntimeConversionExists (ec, a.Expr, ptype)) )
+                                               return false;
+                               
+                               if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+                                       Type pt = pd.ParameterType (i);
+                                       
+                                       if (!pt.IsByRef)
+                                               pt = TypeManager.LookupType (pt.FullName + "&");
+
+                                       if (pt != a.Type)
+                                               return false;
+                               }
+                       } else
+                               return false;                                   
+                       return true;                                    
+               }
+               
                /// <summary>
                ///  Determines if the candidate method is applicable (section 14.4.2.1)
                ///  to the given set of arguments
                /// </summary>
-               static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
+               static bool IsApplicable (EmitContext ec, ref ArrayList arguments, MethodBase candidate)
                {
-                       int arg_count;
-
+                       int arg_count, ps_count, po_count;
+                       Type param_type;
+                       
                        if (arguments == null)
                                arg_count = 0;
                        else
                                arg_count = arguments.Count;
 
                        ParameterData pd = GetParameterData (candidate);
-
+                       Parameters ps = GetFullParameters (candidate);
+                       if (ps == null) {
+                               ps_count = 0;
+                               po_count = 0;
+                       }
+                       else {
+                               ps_count = ps.CountStandardParams();                    
+                               po_count = ps.CountOptionalParams();
+                       }
                        int pd_count = pd.Count;
 
-                       if (arg_count != pd.Count)
-                               return false;
-                       
-                       for (int i = arg_count; i > 0; ) {
-                               i--;
+                       // Validate argument count
+                       if (po_count == 0) {
+                               if (arg_count != pd.Count)
+                                       return false;
+                       }
+                       else {
+                               if ((arg_count < ps_count) || (arg_count > pd_count))
+                                       return false;   
+                       }       
+                       
+                       if (arg_count > 0) {
+                               for (int i = arg_count; i > 0 ; ) {
+                                       i--;
+
+                                       Argument a = (Argument) arguments [i];
+                                       if (a.ArgType == Argument.AType.NoArg) {
+                                               Parameter p = (Parameter) ps.FixedParameters[i];
+                                               a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
+                                               param_type = p.ParameterInitializer.Type;
+                                       }
+                                       else {
+                                               param_type = pd.ParameterType (i);
+                                               if (ps != null) {
+                                                       Parameter p = (Parameter) ps.FixedParameters[i];
+                                                       bool IsDelegate = TypeManager.IsDelegateType (param_type);
+
+                                                       if (IsDelegate) {       
+                                                               if (a.ArgType == Argument.AType.AddressOf) {
+                                                                       a = new Argument ((Expression) a.Expr, Argument.AType.Expression);
+                                                                       ArrayList args = new ArrayList();
+                                                                       args.Add (a);
+                                                                       string param_name = pd.ParameterDesc(i).Replace('+', '.');
+                                                                       Expression pname = MonoBASIC.Parser.DecomposeQI (param_name, Location.Null);
+
+
+                                                                       New temp_new = new New ((Expression)pname, args, Location.Null);
+                                                                       Expression del_temp = temp_new.DoResolve(ec);
+
+                                                                       if (del_temp == null)
+                                                                               return false;
+
+                                                                       a = new Argument (del_temp, Argument.AType.Expression);
+                                                                       if (!a.Resolve(ec, Location.Null))\r
+                                                                               return false;
+                                                               }
+                                                       }
+                                                       else {
+                                                               if (a.ArgType == Argument.AType.AddressOf)
+                                                                       return false;
+                                                       }
 
+                                                       if ((p.ModFlags & Parameter.Modifier.REF) != 0) {
+                                                               a = new Argument (a.Expr, Argument.AType.Ref);
+                                                               if (!a.Resolve(ec,Location.Null))
+                                                                       return false;
+                                                       }
+                                               }
+                                       }       
+\r
+                                       if (!CheckParameterAgainstArgument (ec, pd, i, a, param_type))
+                                               return (false);
+                               }
+                       }
+                       else {
+                               // If we have no arguments AND the first parameter is optional
+                               // we must check for a candidate (the loop above wouldn't)      
+                               if (po_count > 0) {
+                                       ArrayList arglist = new ArrayList();
+                                       
+                                       // Since we got so far, there's no need to check if
+                                       // arguments are optional; we simply retrieve
+                                       // parameter default values and build a brand-new 
+                                       // argument list.
+                                       
+                                       for (int i = 0; i < ps.FixedParameters.Length; i++) {
+                                               Parameter p = ps.FixedParameters[i];
+                                               Argument a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
+                                               a.Resolve(ec, Location.Null);
+                                               arglist.Add (a);
+                                       }
+                                       arguments = arglist;
+                                       return true;
+                               }
+                       }
+                       // We've found a candidate, so we exchange the dummy NoArg arguments
+                       // with new arguments containing the default value for that parameter
+
+                       ArrayList newarglist = new ArrayList();
+                       for (int i = 0; i < arg_count; i++) {
                                Argument a = (Argument) arguments [i];
+                               Parameter p = null;
 
-                               Parameter.Modifier a_mod = a.GetParameterModifier ();
-                               Parameter.Modifier p_mod = pd.ParameterModifier (i);
+                               if (ps != null)
+                                       p = (Parameter) ps.FixedParameters[i];
 
-                               if (a_mod == p_mod ||
-                                   (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
-                                       if (a_mod == Parameter.Modifier.NONE)
-                                               if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
-                                                       return false;
-                                       
-                                       if (a_mod == Parameter.Modifier.REF ||
-                                           a_mod == Parameter.Modifier.OUT) {
-                                               Type pt = pd.ParameterType (i);
+                               if (a.ArgType == Argument.AType.NoArg){
+                                       a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
+                                       a.Resolve(ec, Location.Null);
+                               }
 
-                                               if (!pt.IsByRef)
-                                                       pt = TypeManager.LookupType (pt.FullName + "&");
+                               // ToDo - This part is getting resolved second time within this function
+                               // This is a costly operation
+                               // The earlier resoved result should be used here.
+                               // Has to be done during compiler optimization.
+                               if (a.ArgType == Argument.AType.AddressOf) {
+                                       param_type = pd.ParameterType (i);
+                                       bool IsDelegate = TypeManager.IsDelegateType (param_type);
+
+                                       a = new Argument ((Expression) a.Expr, Argument.AType.Expression);
+                                       ArrayList args = new ArrayList();
+                                       args.Add (a);
+                                       string param_name = pd.ParameterDesc(i).Replace('+', '.');
+                                       Expression pname = MonoBASIC.Parser.DecomposeQI (param_name, Location.Null);
+                                                               
+                                       New temp_new = new New ((Expression)pname, args, Location.Null);
+                                       Expression del_temp = temp_new.DoResolve(ec);
 
-                                               if (pt != a.Type)
-                                                       return false;
+                                       if (del_temp == null)
+                                               return false;
+
+                                       a = new Argument (del_temp, Argument.AType.Expression);
+                                       if (!a.Resolve(ec, Location.Null))\r
+                                               return false;
+                               }
+
+                               if ((p != null) && ((p.ModFlags & Parameter.Modifier.REF) != 0)) {
+                                       a.ArgType = Argument.AType.Ref;
+                                       a.Resolve(ec, Location.Null);
+                               }       
+                               newarglist.Add(a);
+                               int n = pd_count - arg_count;
+                               if (n > 0) {
+                                       for (int x = 0; x < n; x++) {
+                                               Parameter op = (Parameter) ps.FixedParameters[x + arg_count];
+                                               Argument b = new Argument (op.ParameterInitializer, Argument.AType.Expression);
+                                               b.Resolve(ec, Location.Null);
+                                               newarglist.Add (b);
                                        }
-                               } else
-                                       return false;
+                               }
                        }
-
+                       arguments = newarglist;
                        return true;
                }
                
-               
+               static bool compare_name_filter (MemberInfo m, object filterCriteria)
+               {
+                       return (m.Name == ((string) filterCriteria));
+               }
 
+               static Parameters GetFullParameters (MethodBase mb)
+               {
+                       TypeContainer tc = TypeManager.LookupTypeContainer (mb.DeclaringType);
+                       InternalParameters ip = TypeManager.LookupParametersByBuilder(mb);
+                       
+                       return (ip != null) ? ip.Parameters : null;
+               }
+               
+               // We need an overload for OverloadResolve because Invocation.DoResolve
+               // must pass Arguments by reference, since a later call to IsApplicable
+               // can change the argument list if optional parameters are defined
+               // in the method declaration
+               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
+                                                         ArrayList Arguments, Location loc)
+               {
+                       ArrayList a = Arguments;
+                       return OverloadResolve (ec, me, ref a, loc);    
+               }
+               
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -3504,19 +3814,27 @@ namespace Mono.CSharp {
                ///
                /// </summary>
                public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
-                                                         ArrayList Arguments, Location loc)
+                                                         ref ArrayList Arguments, Location loc)
                {
                        ArrayList afm = new ArrayList ();
                        MethodBase method = null;
+                       Type current_type = null;
                        int argument_count;
                        ArrayList candidates = new ArrayList ();
-                       
 
                        foreach (MethodBase candidate in me.Methods){
                                int x;
 
+                               // If we're going one level higher in the class hierarchy, abort if
+                               // we already found an applicable method.
+                               if (candidate.DeclaringType != current_type) {
+                                       current_type = candidate.DeclaringType;
+                                       if (method != null)
+                                               break;
+                               }
+
                                // Check if candidate is applicable (section 14.4.2.1)
-                               if (!IsApplicable (ec, Arguments, candidate))
+                               if (!IsApplicable (ec, ref Arguments, candidate))
                                        continue;
 
                                candidates.Add (candidate);
@@ -3533,6 +3851,7 @@ namespace Mono.CSharp {
                        else
                                argument_count = Arguments.Count;
                        
+                       
                        //
                        // Now we see if we can find params functions, applicable in their expanded form
                        // since if they were applicable in their normal form, they would have been selected
@@ -3557,8 +3876,25 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (method == null)
+                       if (method == null) {
+                               //
+                               // Okay so we have failed to find anything so we
+                               // return by providing info about the closest match
+                               //
+                               for (int i = 0; i < me.Methods.Length; ++i) {
+
+                                       MethodBase c = (MethodBase) me.Methods [i];
+                                       ParameterData pd = GetParameterData (c);
+
+                                       if (pd.Count != argument_count)
+                                               continue;
+
+                                       VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
+                                                              null, loc);
+                               }
+                               
                                return null;
+                       }
 
                        //
                        // Now check that there are no ambiguities i.e the selected method
@@ -3575,7 +3911,7 @@ namespace Mono.CSharp {
                                // so we debar the params method.
                                //
                                if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                   IsApplicable (ec, Arguments, method))
+                                   IsApplicable (ec, ref Arguments, method))
                                        continue;
                                        
                                int x = BetterFunction (ec, Arguments, method, candidate,
@@ -3593,7 +3929,6 @@ namespace Mono.CSharp {
                        // And now check if the arguments are all compatible, perform conversions
                        // if necessary etc. and return if everything is all right
                        //
-
                        if (VerifyArgumentsCompat (ec, Arguments, argument_count, method,
                                                   chose_params_expanded, null, loc))
                                return method;
@@ -3602,23 +3937,41 @@ namespace Mono.CSharp {
                }
 
                public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
+                       int argument_count,
+                       MethodBase method, 
+                       bool chose_params_expanded,
+                       Type delegate_type,
+                       Location loc)
+               {
+                       return (VerifyArgumentsCompat (ec, Arguments, argument_count,
+                               method, chose_params_expanded, delegate_type, loc, null));
+               }
+                                                                                 
+               public static bool VerifyArgumentsCompat (EmitContext ec, 
+                                                         ArrayList Arguments,
                                                          int argument_count,
                                                          MethodBase method, 
                                                          bool chose_params_expanded,
                                                          Type delegate_type,
-                                                         Location loc)
+                                                         Location loc,
+                                                         string InvokingProperty)
                {
                        ParameterData pd = GetParameterData (method);
                        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);
-
+                               Type parameter_type = pd.ParameterType(j);
+                                       
+                               if (parameter_type == null)
+                               {
+                                       Error_WrongNumArguments(loc, (InvokingProperty == null)?((delegate_type == null)?FullMethodDesc (method):delegate_type.ToString ()):InvokingProperty, argument_count);
+                                       return false;   
+                               }
                                if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS &&
-                                   chose_params_expanded)
-                                       parameter_type = parameter_type.GetElementType ();
+                               chose_params_expanded)
+                                       parameter_type = TypeManager.TypeToCoreType (parameter_type.GetElementType ());
 
                                if (a.Type != parameter_type){
                                        Expression conv;
@@ -3628,15 +3981,21 @@ namespace Mono.CSharp {
                                        if (conv == null) {
                                                if (!Location.IsNull (loc)) {
                                                        if (delegate_type == null) 
-                                                               Error (1502, loc,
-                                                                      "The best overloaded match for method '" +
-                                                                      FullMethodDesc (method) +
-                                                                      "' has some invalid arguments");
+                                                               if (InvokingProperty == null)
+                                                                       Report.Error (1502, loc,
+                                                                               "The best overloaded match for method '" +
+                                                                               FullMethodDesc (method) +
+                                                                               "' has some invalid arguments");
+                                                               else
+                                                                       Report.Error (1502, loc,
+                                                                               "Property '" +
+                                                                               InvokingProperty +
+                                                                               "' has some invalid arguments");
                                                        else
                                                                Report.Error (1594, loc,
                                                                              "Delegate '" + delegate_type.ToString () +
                                                                              "' has some invalid arguments.");
-                                                       Error (1503, loc,
+                                                       Report.Error (1503, loc,
                                                         "Argument " + (j+1) +
                                                         ": Cannot convert from '" + Argument.FullDesc (a) 
                                                         + "' to '" + pd.ParameterDesc (j) + "'");
@@ -3651,17 +4010,20 @@ namespace Mono.CSharp {
                                        if (a_expr != conv)
                                                a.Expr = conv;
                                }
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (j) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
                                
-                               if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
+                               if (a_mod != p_mod &&
                                    pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
                                        if (!Location.IsNull (loc)) {
-                                               Console.WriteLine ("A:P: " + a.GetParameterModifier ());
-                                               Console.WriteLine ("PP:: " + pd.ParameterModifier (j));
-                                               Console.WriteLine ("PT:  " + parameter_type.IsByRef);
-                                               Error (1502, loc,
+                                               Report.Error (1502, loc,
                                                       "The best overloaded match for method '" + FullMethodDesc (method)+
                                                       "' has some invalid arguments");
-                                               Error (1503, loc,
+                                               Report.Error (1503, loc,
                                                       "Argument " + (j+1) +
                                                       ": Cannot convert from '" + Argument.FullDesc (a) 
                                                       + "' to '" + pd.ParameterDesc (j) + "'");
@@ -3673,24 +4035,48 @@ namespace Mono.CSharp {
 
                        return true;
                }
-               
+       
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       this.is_left_hand = true;
+                       return DoResolve (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        //
                        // First, resolve the expression that is used to
                        // trigger the invocation
                        //
+                       Expression expr_to_return = null;
+
                        if (expr is BaseAccess)
                                is_base = true;
 
-                       expr = expr.Resolve (ec);
+                       if ((ec.ReturnType != null) && (expr.ToString() == ec.BlockName)) {
+                               ec.InvokingOwnOverload = true;
+                               expr = expr.Resolve (ec, ResolveFlags.MethodGroup);
+                               ec.InvokingOwnOverload = false;
+                       }
+                       else                            
+                       {
+                               ec.InvokingOwnOverload = false;
+                               expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+                       }       
                        if (expr == null)
                                return null;
 
-                       if (!(expr is MethodGroupExpr)) {
+                       if (expr is Invocation) {
+                               // FIXME Calls which return an Array are not resolved (here or in the grammar)
+                               expr = expr.Resolve(ec);
+                       }
+
+                       if (!(expr is MethodGroupExpr)) 
+                       {
                                Type expr_type = expr.Type;
 
-                               if (expr_type != null){
+                               if (expr_type != null)
+                               {
                                        bool IsDelegate = TypeManager.IsDelegateType (expr_type);
                                        if (IsDelegate)
                                                return (new DelegateInvocation (
@@ -3698,43 +4084,138 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (!(expr is MethodGroupExpr)){
-                               report118 (loc, this.expr, "method group");
-                               return null;
-                       }
-
                        //
                        // Next, evaluate all the expressions in the argument list
                        //
-                       if (Arguments != null){
-                               foreach (Argument a in Arguments){
+                       if (Arguments != null)
+                       {
+                               foreach (Argument a in Arguments)
+                               {
+                                       if ((a.ArgType == Argument.AType.NoArg) && (!(expr is MethodGroupExpr)))
+                                               Report.Error (999, "This item cannot have empty arguments");
+
+                       
                                        if (!a.Resolve (ec, loc))
+                                               return null;                            
+                               }
+                       }
+                       
+                       if (expr is MethodGroupExpr) 
+                       {
+                               MethodGroupExpr mg = (MethodGroupExpr) expr;
+                               method = OverloadResolve (ec, mg, ref Arguments, loc);
+
+                               if (method == null)
+                               {
+                                       Error (30455,
+                                               "Could not find any applicable function to invoke for this argument list");
+                                       return null;
+                               }
+
+                               if ((method as MethodInfo) != null) 
+                               {
+                                       MethodInfo mi = method as MethodInfo;
+                                       type = TypeManager.TypeToCoreType (mi.ReturnType);
+                                       if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
+                                               SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
+                               }
+
+                               if ((method as ConstructorInfo) != null) 
+                               {
+                                       ConstructorInfo ci = method as ConstructorInfo;
+                                       type = TypeManager.void_type;
+                                       if (!ci.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
+                                               SimpleName.Error_ObjectRefRequired (ec, loc, ci.Name);
+                               }
+
+                               if (type.IsPointer)
+                               {
+                                       if (!ec.InUnsafe)
+                                       {
+                                               UnsafeError (loc);
                                                return null;
+                                       }
                                }
+                               eclass = ExprClass.Value;
+                               expr_to_return = this;
                        }
 
-                       method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments, loc);
+                       if (expr is PropertyExpr) 
+                       {
+                               PropertyExpr pe = ((PropertyExpr) expr);
+                               pe.PropertyArgs = (ArrayList) Arguments.Clone();
+                               Arguments.Clear();
+                               Arguments = new ArrayList();
+                               MethodBase mi = pe.PropertyInfo.GetGetMethod(true);
 
-                       if (method == null){
-                               Error (-6, loc,
-                                      "Could not find any applicable function for this argument list");
-                               return null;
+                               if(VerifyArgumentsCompat (ec, pe.PropertyArgs, 
+                                       pe.PropertyArgs.Count, mi, false, null, loc, pe.Name)) 
+                               {
+
+                                       expr_to_return = pe.DoResolve (ec);
+                                       expr_to_return.eclass = ExprClass.PropertyAccess;
+                               }
+                               else
+                               {
+                                       throw new Exception("Error resolving Property Access expression\n" + pe.ToString());
+                               }
                        }
 
-                       if (method is MethodInfo)
-                               type = ((MethodInfo)method).ReturnType;
+                       if (expr is FieldExpr || expr is LocalVariableReference || expr is ParameterReference) {
+                               if (expr.Type.IsArray) {
+                                       // If we are here, expr must be an ArrayAccess
+                                       ArrayList idxs = new ArrayList();
+                                       foreach (Argument a in Arguments)
+                                       {
+                                               idxs.Add (a.Expr);
+                                       }
+                                       ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
+                                       ArrayAccess aa = new ArrayAccess (ea, expr.Location);
+                                       expr_to_return = aa.DoResolve(ec);
+                                       expr_to_return.eclass = ExprClass.Variable;
+                               }
+                               else
+                               {
+                                       // We can't resolve now, but we
+                                       // have to try to access the array with a call
+                                       // to LateIndexGet/Set in the runtime
+                                       Expression lig_call_expr;
+
+                                       if (!is_left_hand)
+                                               lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexGet", Location.Null);
+                                       else
+                                               lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexSet", Location.Null);
+                                       Expression obj_type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", Location.Null);
+                                       ArrayList adims = new ArrayList();
 
-                       if (type.IsPointer){
-                               if (!ec.InUnsafe){
-                                       UnsafeError (loc);
-                                       return null;
+                                       ArrayList ainit = new ArrayList();
+                                       foreach (Argument a in Arguments)
+                                               ainit.Add ((Expression) a.Expr);
+
+                                       adims.Add ((Expression) new IntLiteral (Arguments.Count));
+
+                                       Expression oace = new ArrayCreation (obj_type, adims, "", ainit, Location.Null);
+
+                                       ArrayList args = new ArrayList();
+                                       args.Add (new Argument(expr, Argument.AType.Expression));
+                                       args.Add (new Argument(oace, Argument.AType.Expression));
+                                       args.Add (new Argument(NullLiteral.Null, Argument.AType.Expression));
+
+                                       Expression lig_call = new Invocation (lig_call_expr, args, Location.Null);
+                                       expr_to_return = lig_call.Resolve(ec);
+                                       expr_to_return.eclass = ExprClass.Variable;
                                }
                        }
-                       
-                       eclass = ExprClass.Value;
-                       return this;
+
+                       return expr_to_return;
                }
 
+        static void Error_WrongNumArguments (Location loc, String name, int arg_count)
+        {
+            Report.Error (1501, loc, "No overload for method `" + name + "' takes `" +
+                                      arg_count + "' arguments");
+        }
+
                // <summary>
                //   Emits the list of arguments as an array
                // </summary>
@@ -3743,13 +4224,13 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        int count = arguments.Count - idx;
                        Argument a = (Argument) arguments [idx];
-                       Type t = a.expr.Type;
+                       Type t = a.Expr.Type;
                        string array_type = t.FullName + "[]";
                        LocalBuilder array;
 
-                       array = ig.DeclareLocal (Type.GetType (array_type));
+                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
                        IntConstant.EmitInt (ig, count);
-                       ig.Emit (OpCodes.Newarr, t);
+                       ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
                        ig.Emit (OpCodes.Stloc, array);
 
                        int top = arguments.Count;
@@ -3771,8 +4252,8 @@ namespace Mono.CSharp {
                /// 
                ///   The MethodBase argument might be null if the
                ///   emission of the arguments is known not to contain
-               ///   a `params' field (for example in constructors or other routines
-               ///   that keep their arguments in this structure
+               ///   a 'params' field (for example in constructors or other routines
+               ///   that keep their arguments in this structure)
                /// </summary>
                public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
                {
@@ -3793,7 +4274,6 @@ namespace Mono.CSharp {
                                        IntConstant.EmitInt (ig, 0);
                                        ig.Emit (OpCodes.Newarr, pd.ParameterType (0).GetElementType ());
                                }
-
                                return;
                        }
 
@@ -3818,10 +4298,18 @@ namespace Mono.CSharp {
                                            
                                a.Emit (ec);
                        }
+
+                       if (pd != null && pd.Count > top &&
+                           pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
+                               ILGenerator ig = ec.ig;
+
+                               IntConstant.EmitInt (ig, 0);
+                               ig.Emit (OpCodes.Newarr, pd.ParameterType (top).GetElementType ());
+                       }
                }
 
                /// <remarks>
-               ///   is_base tells whether we want to force the use of the `call'
+               ///   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.
@@ -3837,32 +4325,76 @@ namespace Mono.CSharp {
                /// </remarks>
                public static void EmitCall (EmitContext ec, bool is_base,
                                             bool is_static, Expression instance_expr,
-                                            MethodBase method, ArrayList Arguments)
+                                            MethodBase method, ArrayList Arguments, Location loc)
+               {
+                       EmitCall (ec, is_base, is_static, instance_expr, method, Arguments, null, loc);
+               }
+               
+               public static void EmitCall (EmitContext ec, bool is_base,
+                       bool is_static, Expression instance_expr,
+                       MethodBase method, ArrayList Arguments, ArrayList prop_args, Location loc)
                {
                        ILGenerator ig = ec.ig;
                        bool struct_call = false;
-                               
-                       if (!is_static){
-                               
-                               if (method.DeclaringType.IsValueType)
+
+                       Type decl_type = method.DeclaringType;
+
+                       if (!RootContext.StdLib) 
+                       {
+                               // Replace any calls to the system's System.Array type with calls to
+                               // the newly created one.
+                               if (method == TypeManager.system_int_array_get_length)
+                                       method = TypeManager.int_array_get_length;
+                               else if (method == TypeManager.system_int_array_get_rank)
+                                       method = TypeManager.int_array_get_rank;
+                               else if (method == TypeManager.system_object_array_clone)
+                                       method = TypeManager.object_array_clone;
+                               else if (method == TypeManager.system_int_array_get_length_int)
+                                       method = TypeManager.int_array_get_length_int;
+                               else if (method == TypeManager.system_int_array_get_lower_bound_int)
+                                       method = TypeManager.int_array_get_lower_bound_int;
+                               else if (method == TypeManager.system_int_array_get_upper_bound_int)
+                                       method = TypeManager.int_array_get_upper_bound_int;
+                               else if (method == TypeManager.system_void_array_copyto_array_int)
+                                       method = TypeManager.void_array_copyto_array_int;
+                       }
+
+                       //
+                       // This checks the 'ConditionalAttribute' on the method, and the
+                       // ObsoleteAttribute
+                       //
+                       TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
+                       if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
+                               return;
+                       if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+                               return;
+                       
+                       if (!is_static)
+                       {
+                               if (decl_type.IsValueType)
                                        struct_call = true;
                                //
                                // If this is ourselves, push "this"
                                //
-                               if (instance_expr == null){
+                               if (instance_expr == null)
+                               {
                                        ig.Emit (OpCodes.Ldarg_0);
-                               } else {
+                               } 
+                               else 
+                               {
                                        //
                                        // Push the instance expression
                                        //
-                                       if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
+                                       if (instance_expr.Type.IsValueType)
+                                       {
                                                //
                                                // 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 (method.DeclaringType.IsValueType){
+                                               if (decl_type.IsValueType)
+                                               {
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -3870,11 +4402,13 @@ namespace Mono.CSharp {
                                                        //
                                                        // If not we have to use some temporary storage for
                                                        // it.
-                                                       if (instance_expr is IMemoryLocation){
+                                                       if (instance_expr is IMemoryLocation)
+                                                       {
                                                                ((IMemoryLocation)instance_expr).
                                                                        AddressOf (ec, AddressOp.LoadStore);
                                                        }
-                                                       else {
+                                                       else 
+                                                       {
                                                                Type t = instance_expr.Type;
                                                                
                                                                instance_expr.Emit (ec);
@@ -3882,23 +4416,43 @@ namespace Mono.CSharp {
                                                                ig.Emit (OpCodes.Stloc, temp);
                                                                ig.Emit (OpCodes.Ldloca, temp);
                                                        }
-                                               } else {
+                                               } 
+                                               else 
+                                               {
                                                        instance_expr.Emit (ec);
                                                        ig.Emit (OpCodes.Box, instance_expr.Type);
                                                } 
-                                       } else
+                                       } 
+                                       else
                                                instance_expr.Emit (ec);
                                }
                        }
+                       
+                       if (prop_args != null && prop_args.Count > 0)
+                       {
+                               if (Arguments == null) 
+                                       Arguments = new ArrayList();
+
+                               for (int i = prop_args.Count-1; i >=0 ; i--) 
+                               {
+                                       Arguments.Insert (0,prop_args[i]);
+                               }
+
+                       }
 
                        EmitArguments (ec, method, Arguments);
 
-                       if (is_static || struct_call || is_base){
-                               if (method is MethodInfo)
+                       if (is_static || struct_call || is_base)
+                       {
+                               if (method is MethodInfo) 
+                               {
                                        ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               } 
                                else
                                        ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-                       } else {
+                       } 
+                       else 
+                       {
                                if (method is MethodInfo)
                                        ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
                                else
@@ -3906,11 +4460,23 @@ namespace Mono.CSharp {
                        }
                }
                
+               static void EmitPropertyArgs (EmitContext ec, ArrayList prop_args)
+               {
+                       int top = prop_args.Count;
+
+                       for (int i = 0; i < top; i++)
+                       {
+                               Argument a = (Argument) prop_args [i];
+                               a.Emit (ec);
+                       }
+               }
+
                public override void Emit (EmitContext ec)
                {
                        MethodGroupExpr mg = (MethodGroupExpr) this.expr;
 
-                       EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments);
+                       EmitCall (
+                               ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
                }
                
                public override void EmitStatement (EmitContext ec)
@@ -3921,7 +4487,8 @@ namespace Mono.CSharp {
                        // Pop the return value if there is one
                        //
                        if (method is MethodInfo){
-                               if (((MethodInfo)method).ReturnType != TypeManager.void_type)
+                               Type ret = ((MethodInfo)method).ReturnType;
+                               if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
                                        ec.ig.Emit (OpCodes.Pop);
                        }
                }
@@ -3943,9 +4510,8 @@ namespace Mono.CSharp {
        /// </summary>
        public class New : ExpressionStatement {
                public readonly ArrayList Arguments;
-               public readonly string    RequestedType;
+               public readonly Expression RequestedType;
 
-               Location loc;
                MethodBase method = null;
 
                //
@@ -3953,8 +4519,10 @@ namespace Mono.CSharp {
                // we will not leave anything on the stack.
                //
                Expression value_target;
+               bool value_target_set = false;
+               public bool isDelegate = false;
                
-               public New (string requested_type, ArrayList arguments, Location l)
+               public New (Expression requested_type, ArrayList arguments, Location l)
                {
                        RequestedType = requested_type;
                        Arguments = arguments;
@@ -3968,6 +4536,7 @@ namespace Mono.CSharp {
 
                        set {
                                value_target = value;
+                               value_target_set = true;
                        }
                }
 
@@ -3993,14 +4562,23 @@ namespace Mono.CSharp {
                        // To enable this, look into:
                        // test-34 and test-89 and self bootstrapping.
                        //
-                       // For instance, we can avoid a copy by using `newobj'
+                       // For instance, we can avoid a copy by using 'newobj'
                        // instead of Call + Push-temp on value types.
 //                     value_target = MyEmptyExpression;
                }
                
                public override Expression DoResolve (EmitContext ec)
                {
-                       type = RootContext.LookupType (ec.DeclSpace, RequestedType, false, loc);
+                       if (this.isDelegate) {
+                               // if its a delegate resolve the type of RequestedType first
+                               Expression dtype = RequestedType.Resolve(ec);
+                               string ts = (dtype.Type.ToString()).Replace ('+','.');
+                               dtype = Mono.MonoBASIC.Parser.DecomposeQI (ts, Location.Null);
+
+                               type = ec.DeclSpace.ResolveType (dtype, false, loc);
+                       }
+                       else
+                               type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
                        
                        if (type == null)
                                return null;
@@ -4011,14 +4589,14 @@ namespace Mono.CSharp {
                                return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
 
                        if (type.IsInterface || type.IsAbstract){
-                               Report.Error (
-                                       144, "It is not possible to create instances of interfaces " +
-                                       "or abstract classes");
+                               Error (
+                                       30376, "It is not possible to create instances of Interfaces " +
+                                       "or classes marked as MustInherit");
                                return null;
                        }
                        
                        bool is_struct = false;
-                       is_struct = type.IsSubclassOf (TypeManager.value_type);
+                       is_struct = type.IsValueType;
                        eclass = ExprClass.Value;
 
                        //
@@ -4031,14 +4609,14 @@ namespace Mono.CSharp {
                        Expression ml;
                        ml = MemberLookupFinal (ec, type, ".ctor",
                                                MemberTypes.Constructor,
-                                               AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+                                               AllBindingFlags | BindingFlags.Public, loc);
 
                        if (ml == null)
                                return null;
                        
                        if (! (ml is MethodGroupExpr)){
                                if (!is_struct){
-                                       report118 (loc, ml, "method group");
+                                       ml.Error118 ("method group");
                                        return null;
                                }
                        }
@@ -4055,12 +4633,14 @@ namespace Mono.CSharp {
                                                                     Arguments, loc);
                                
                        }
-                       
-                       if (method == null && !is_struct) {
-                               Error (1501, loc,
-                                      "New invocation: Can not find a constructor for " +
-                                      "this argument list");
-                               return null;
+
+                       if (method == null) { 
+                                if (!is_struct || Arguments.Count > 0) {
+                                       Error (1501,
+                                              "New invocation: Can not find a constructor for " +
+                                              "this argument list");
+                                       return null;
+                                }
                        }
                        return this;
                }
@@ -4091,13 +4671,16 @@ namespace Mono.CSharp {
                //
                bool DoEmit (EmitContext ec, bool need_value_on_stack)
                {
-                       bool is_value_type = type.IsSubclassOf (TypeManager.value_type);
+                       bool is_value_type = type.IsValueType;
                        ILGenerator ig = ec.ig;
 
                        if (is_value_type){
                                IMemoryLocation ml;
 
-                               if (value_target == null)
+                               // Allow DoEmit() to be called multiple times.
+                               // We need to create a new LocalTemporary each time since
+                               // you can't share LocalBuilders among ILGeneators.
+                               if (!value_target_set)
                                        value_target = new LocalTemporary (ec, type);
                                        
                                ml = (IMemoryLocation) value_target;
@@ -4136,7 +4719,7 @@ namespace Mono.CSharp {
        }
 
        /// <summary>
-       ///   Represents an array creation expression.
+       ///   14.5.10.2: Represents an array creation expression.
        /// </summary>
        ///
        /// <remarks>
@@ -4146,29 +4729,32 @@ namespace Mono.CSharp {
        ///   specified but where initialization data is mandatory.
        /// </remarks>
        public class ArrayCreation : ExpressionStatement {
-               string RequestedType;
-               string Rank;
-               ArrayList Initializers;
-               Location  loc;
+               Expression requested_base_type;
+               ArrayList initializers;
 
                //
                // The list of Argument types.
-               // This is used to constrcut the `newarray' or constructor signature
+               // This is used to construct the 'newarray' or constructor signature
                //
-               ArrayList Arguments;
+               ArrayList arguments;
 
-               MethodBase method = null;
+               //
+               // Method used to create the array object.
+               //
+               MethodBase new_method = null;
+               
                Type array_element_type;
-               bool IsOneDimensional = false;
-               bool IsBuiltinType = false;
-               bool ExpectInitializers = false;
-
-               int dimensions = 0;
                Type underlying_type;
+               bool is_one_dimensional = false;
+               bool is_builtin_type = false;
+               bool expect_initializers = false;
+               int num_arguments = 0;
+               int dimensions = 0;
+               string rank;
 
-               ArrayList ArrayData;
+               ArrayList array_data;
 
-               Hashtable Bounds;
+               Hashtable bounds;
 
                //
                // The number of array initializers that we can handle
@@ -4176,105 +4762,104 @@ namespace Mono.CSharp {
                //
                int num_automatic_initializers;
                
-               public ArrayCreation (string requested_type, ArrayList exprs,
-                                     string rank, ArrayList initializers, Location l)
+               public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
                {
-                       RequestedType = requested_type;
-                       Rank          = rank;
-                       Initializers  = initializers;
+                       this.requested_base_type = requested_base_type;
+                       this.initializers = initializers;
+                       this.rank = rank;
                        loc = l;
 
-                       Arguments = new ArrayList ();
+                       arguments = new ArrayList ();
 
-                       foreach (Expression e in exprs)
-                               Arguments.Add (new Argument (e, Argument.AType.Expression));
+                       foreach (Expression e in exprs) {
+                               arguments.Add (new Argument (e, Argument.AType.Expression));
+                               num_arguments++;
+                       }
                }
 
-               public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
+               public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
                {
-                       RequestedType = requested_type;
-                       Initializers = initializers;
+                       this.requested_base_type = requested_base_type;
+                       this.initializers = initializers;
+                       this.rank = rank;
                        loc = l;
 
-                       Rank = rank.Substring (0, rank.LastIndexOf ("["));
-
-                       string tmp = rank.Substring (rank.LastIndexOf ("["));
-
-                       dimensions = tmp.Length - 1;
-                       ExpectInitializers = true;
+                       //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+                       //
+                       //string tmp = rank.Substring (rank.LastIndexOf ("["));
+                       //
+                       //dimensions = tmp.Length - 1;
+                       expect_initializers = true;
                }
 
-               public static string FormArrayType (string base_type, int idx_count, string rank)
-               {
-                       StringBuilder sb = new StringBuilder (base_type);
-
-                       sb.Append (rank);
-                       
-                       sb.Append ("[");
-                       for (int i = 1; i < idx_count; i++)
-                               sb.Append (",");
-                       
-                       sb.Append ("]");
-
-                       return sb.ToString ();
-                }
-
-               public static string FormElementType (string base_type, int idx_count, string rank)
+               public Expression FormArrayType (Expression base_type, int idx_count, string rank)
                {
-                       StringBuilder sb = new StringBuilder (base_type);
+                       StringBuilder sb = new StringBuilder (rank);
                        
                        sb.Append ("[");
                        for (int i = 1; i < idx_count; i++)
                                sb.Append (",");
                        
                        sb.Append ("]");
-                       
-                       sb.Append (rank);
-
-                       string val = sb.ToString ();
 
-                       return val.Substring (0, val.LastIndexOf ("["));
+                       return new ComposedCast (base_type, sb.ToString (), loc);
                }
 
-               void error178 ()
+               void Error_IncorrectArrayInitializer ()
                {
-                       Report.Error (178, loc, "Incorrectly structured array initializer");
+                       Error (30567, "Incorrectly structured array initializer");
                }
                
                public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
                {
                        if (specified_dims) { 
-                               Argument a = (Argument) Arguments [idx];
+                               Argument a = (Argument) arguments [idx];
                                
                                if (!a.Resolve (ec, loc))
                                        return false;
                                
                                if (!(a.Expr is Constant)) {
-                                       Report.Error (150, loc, "A constant value is expected");
+                                       Error (150, "A constant value is expected");
                                        return false;
                                }
                                
                                int value = (int) ((Constant) a.Expr).GetValue ();
                                
                                if (value != probe.Count) {
-                                       error178 ();
+                                       Error_IncorrectArrayInitializer ();
                                        return false;
                                }
                                
-                               Bounds [idx] = value;
+                               bounds [idx] = value;
                        }
-                       
+
+                       int child_bounds = -1;
                        foreach (object o in probe) {
                                if (o is ArrayList) {
+                                       int current_bounds = ((ArrayList) o).Count;
+                                       
+                                       if (child_bounds == -1) 
+                                               child_bounds = current_bounds;
+
+                                       else if (child_bounds != current_bounds){
+                                               Error_IncorrectArrayInitializer ();
+                                               return false;
+                                       }
                                        bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
                                        if (!ret)
                                                return false;
                                } else {
+                                       if (child_bounds != -1){
+                                               Error_IncorrectArrayInitializer ();
+                                               return false;
+                                       }
+                                       
                                        Expression tmp = (Expression) o;
                                        tmp = tmp.Resolve (ec);
                                        if (tmp == null)
                                                continue;
-                                       
+
+                                       // Console.WriteLine ("I got: " + tmp);
                                        // Handle initialization from vars, fields etc.
 
                                        Expression conv = ConvertImplicitRequired (
@@ -4284,12 +4869,12 @@ namespace Mono.CSharp {
                                                return false;
 
                                        if (conv is StringConstant)
-                                               ArrayData.Add (conv);
+                                               array_data.Add (conv);
                                        else if (conv is Constant) {
-                                               ArrayData.Add (conv);
+                                               array_data.Add (conv);
                                                num_automatic_initializers++;
                                        } else
-                                               ArrayData.Add (conv);
+                                               array_data.Add (conv);
                                }
                        }
 
@@ -4299,160 +4884,230 @@ namespace Mono.CSharp {
                public void UpdateIndices (EmitContext ec)
                {
                        int i = 0;
-                       for (ArrayList probe = Initializers; probe != null;) {
+                       for (ArrayList probe = initializers; probe != null;) {
                                if (probe.Count > 0 && probe [0] is ArrayList) {
                                        Expression e = new IntConstant (probe.Count);
-                                       Arguments.Add (new Argument (e, Argument.AType.Expression));
+                                       arguments.Add (new Argument (e, Argument.AType.Expression));
 
-                                       Bounds [i++] =  probe.Count;
+                                       bounds [i++] =  probe.Count;
                                        
                                        probe = (ArrayList) probe [0];
                                        
                                } else {
                                        Expression e = new IntConstant (probe.Count);
-                                       Arguments.Add (new Argument (e, Argument.AType.Expression));
+                                       arguments.Add (new Argument (e, Argument.AType.Expression));
 
-                                       Bounds [i++] = probe.Count;
+                                       bounds [i++] = probe.Count;
                                        probe = null;
                                }
                        }
 
                }
                
-               public bool ValidateInitializers (EmitContext ec)
+               public bool ValidateInitializers (EmitContext ec, Type array_type)
                {
-                       if (Initializers == null) {
-                               if (ExpectInitializers)
+                       if (initializers == null) {
+                               if (expect_initializers)
                                        return false;
                                else
                                        return true;
                        }
                        
-                       underlying_type = RootContext.LookupType (
-                               ec.DeclSpace, RequestedType, false, loc);
+                       if (underlying_type == null)
+                               return false;
                        
                        //
                        // 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 ();
-                       Bounds = new Hashtable ();
+                       array_data = new ArrayList ();
+                       bounds = new Hashtable ();
                        
                        bool ret;
 
-                       if (Arguments != null) {
-                               ret = CheckIndices (ec, Initializers, 0, true);
+                       if (arguments != null) {
+                               ret = CheckIndices (ec, initializers, 0, true);
                                return ret;
-                               
                        } else {
-                               Arguments = new ArrayList ();
+                               arguments = new ArrayList ();
 
-                               ret = CheckIndices (ec, Initializers, 0, false);
+                               ret = CheckIndices (ec, initializers, 0, false);
                                
                                if (!ret)
                                        return false;
                                
                                UpdateIndices (ec);
                                
-                               if (Arguments.Count != dimensions) {
-                                       error178 ();
+                               if (arguments.Count != dimensions) {
+                                       Error_IncorrectArrayInitializer ();
                                        return false;
                                }
 
                                return ret;
                        }
                }
+
+               void Error_NegativeArrayIndex ()
+               {
+                       Error (284, "Can not create array with a negative size");
+               }
+               
+               //
+               // Converts 'source' to an int, uint, long or ulong.
+               //
+               Expression ExpressionToArrayArgument (EmitContext ec, Expression source)
+               {
+                       Expression target;
+                       
+                       bool old_checked = ec.CheckState;
+                       ec.CheckState = true;
+                       
+                       target = ConvertImplicit (ec, source, TypeManager.int32_type, loc);
+                       if (target == null){
+                               target = ConvertImplicit (ec, source, TypeManager.uint32_type, loc);
+                               if (target == null){
+                                       target = ConvertImplicit (ec, source, TypeManager.int64_type, loc);
+                                       if (target == null){
+                                               target = ConvertImplicit (ec, source, TypeManager.uint64_type, loc);
+                                               if (target == null)
+                                                       Expression.Error_CannotConvertImplicit (loc, source.Type, TypeManager.int32_type);
+                                       }
+                               }
+                       } 
+                       ec.CheckState = old_checked;
+
+                       //
+                       // Only positive constants are allowed at compile time
+                       //
+                       if (target is Constant){
+                               if (target is IntConstant){
+                                       if (((IntConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex ();
+                                               return null;
+                                       }
+                               }
+
+                               if (target is LongConstant){
+                                       if (((LongConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex ();
+                                               return null;
+                                       }
+                               }
+                               
+                       }
+
+                       return target;
+               }
+
+               //
+               // Creates the type of the array
+               //
+               bool LookupType (EmitContext ec)
+               {
+                       StringBuilder array_qualifier = new StringBuilder (rank);
+
+                       //
+                       // 'In the first form allocates an array instace of the type that results
+                       // from deleting each of the individual expression from the expression list'
+                       //
+                       if (num_arguments > 0) {
+                               array_qualifier.Append ("[");
+                               for (int i = num_arguments-1; i > 0; i--)
+                                       array_qualifier.Append (",");
+                               array_qualifier.Append ("]");                           
+                       }
+
+                       //
+                       // Lookup the type
+                       //
+                       Expression array_type_expr;
+                       array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
+                       string sss = array_qualifier.ToString ();
+                       type = ec.DeclSpace.ResolveType (array_type_expr, false, loc);
+
+                       if (type == null)
+                               return false;
+
+                       underlying_type = type;
+                       if (underlying_type.IsArray)
+                               underlying_type = TypeManager.TypeToCoreType (underlying_type.GetElementType ());
+                       dimensions = type.GetArrayRank ();
+
+                       return true;
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
                        int arg_count;
 
+                       if (!LookupType (ec))
+                               return null;
+                       
                        //
                        // First step is to validate the initializers and fill
                        // in any missing bits
                        //
-                       if (!ValidateInitializers (ec))
+                       if (!ValidateInitializers (ec, type))
                                return null;
 
-                       if (Arguments == null)
+                       if (arguments == null)
                                arg_count = 0;
                        else {
-                               arg_count = Arguments.Count;
-                               foreach (Argument a in Arguments){
+                               arg_count = arguments.Count;
+                               foreach (Argument a in arguments){
                                        if (!a.Resolve (ec, loc))
                                                return null;
 
-                                       //
-                                       // Now, convert that to an integer
-                                       //
-                                       Expression real_arg;
-                                       bool old_checked = ec.CheckState;
-                                       ec.CheckState = true;
-                       
-                                       real_arg = ConvertExplicit (
-                                               ec, a.expr, TypeManager.uint32_type, loc);
-                                       ec.CheckState = old_checked;
+                                       Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc);
                                        if (real_arg == null)
                                                return null;
 
-                                       a.expr = real_arg;
+                                       a.Expr = real_arg;
                                }
                        }
                        
-                       string array_type = FormArrayType (RequestedType, arg_count, Rank);
-                       string element_type = FormElementType (RequestedType, arg_count, Rank);
+                       array_element_type = TypeManager.TypeToCoreType (type.GetElementType ());
 
-                       type = RootContext.LookupType (ec.DeclSpace, array_type, false, loc);
-                       
-                       array_element_type = RootContext.LookupType (
-                               ec.DeclSpace, element_type, false, loc);
-                       
-                       if (type == null)
-                               return null;
-                       
                        if (arg_count == 1) {
-                               IsOneDimensional = true;
+                               is_one_dimensional = true;
                                eclass = ExprClass.Value;
                                return this;
                        }
 
-                       IsBuiltinType = TypeManager.IsBuiltinType (type);
-                       
-                       if (IsBuiltinType) {
+                       is_builtin_type = TypeManager.IsBuiltinType (type);
 
+                       if (is_builtin_type) {
                                Expression ml;
                                
                                ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
                                                   AllBindingFlags, loc);
                                
-                               if (!(ml is MethodGroupExpr)){
-                                       report118 (loc, ml, "method group");
+                               if (!(ml is MethodGroupExpr)) {
+                                       ml.Error118 ("method group");
                                        return null;
                                }
                                
                                if (ml == null) {
-                                       Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
+                                       Error (-6, "New invocation: Can not find a constructor for " +
                                                      "this argument list");
                                        return null;
                                }
                                
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
+                               new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
 
-                               if (method == null) {
-                                       Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
+                               if (new_method == null) {
+                                       Error (-6, "New invocation: Can not find a constructor for " +
                                                      "this argument list");
                                        return null;
                                }
                                
                                eclass = ExprClass.Value;
                                return this;
-                               
                        } else {
-
                                ModuleBuilder mb = CodeGen.ModuleBuilder;
-
                                ArrayList args = new ArrayList ();
-                               if (Arguments != null){
+                               
+                               if (arguments != null) {
                                        for (int i = 0; i < arg_count; i++)
                                                args.Add (TypeManager.int32_type);
                                }
@@ -4464,37 +5119,39 @@ namespace Mono.CSharp {
                                
                                args.CopyTo (arg_types, 0);
                                
-                               method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
+                               new_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 " +
+                               if (new_method == null) {
+                                       Error (-6, "New invocation: Can not find a constructor for " +
                                                      "this argument list");
                                        return null;
                                }
                                
                                eclass = ExprClass.Value;
                                return this;
-                               
                        }
                }
 
-               public static byte [] MakeByteBlob (ArrayList ArrayData, Type underlying_type, Location loc)
+               public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
                {
                        int factor;
                        byte [] data;
                        byte [] element;
-                       int count = ArrayData.Count;
+                       int count = array_data.Count;
 
+                       if (underlying_type.IsEnum)
+                               underlying_type = TypeManager.EnumToUnderlying (underlying_type);
+                       
                        factor = GetTypeSize (underlying_type);
                        if (factor == 0)
-                               return null;
+                               throw new Exception ("unrecognized type in MakeByteBlob: " + underlying_type);
 
                        data = new byte [(count * factor + 4) & ~3];
                        int idx = 0;
                        
                        for (int i = 0; i < count; ++i) {
-                               object v = ArrayData [i];
+                               object v = array_data [i];
 
                                if (v is EnumConstant)
                                        v = ((EnumConstant) v).Child;
@@ -4592,8 +5249,20 @@ namespace Mono.CSharp {
                                                bool val = (bool) v;
                                                data [idx] = (byte) (val ? 1 : 0);
                                        }
+                               } else if (underlying_type == TypeManager.decimal_type){
+                                       if (!(v is Expression)){
+                                               int [] bits = Decimal.GetBits ((decimal) v);
+                                               int p = idx;
+                                               
+                                               for (int j = 0; j < 4; j++){
+                                                       data [p++] = (byte) (bits [j] & 0xff);
+                                                       data [p++] = (byte) ((bits [j] >> 8) & 0xff);
+                                                       data [p++] = (byte) ((bits [j] >> 16) & 0xff);
+                                                       data [p++] = (byte) (bits [j] >> 24);
+                                               }
+                                       }
                                } else
-                                       throw new Exception ("Unrecognized type in MakeByteBlob");
+                                       throw new Exception ("Unrecognized type in MakeByteBlob: " + underlying_type);
 
                                 idx += factor;
                        }
@@ -4612,17 +5281,15 @@ namespace Mono.CSharp {
                        FieldBuilder fb;
                        ILGenerator ig = ec.ig;
                        
-                       byte [] data = MakeByteBlob (ArrayData, underlying_type, loc);
-                       
-                       if (data != null) {
-                               fb = RootContext.MakeStaticData (data);
+                       byte [] data = MakeByteBlob (array_data, underlying_type, loc);
 
-                               if (is_expression)
-                                       ig.Emit (OpCodes.Dup);
-                               ig.Emit (OpCodes.Ldtoken, fb);
-                               ig.Emit (OpCodes.Call,
-                                        TypeManager.void_initializearray_array_fieldhandle);
-                       }
+                       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);
                }
                
                //
@@ -4634,9 +5301,9 @@ namespace Mono.CSharp {
                void EmitDynamicInitializers (EmitContext ec, bool is_expression)
                {
                        ILGenerator ig = ec.ig;
-                       int dims = Bounds.Count;
+                       int dims = bounds.Count;
                        int [] current_pos = new int [dims];
-                       int top = ArrayData.Count;
+                       int top = array_data.Count;
                        LocalBuilder temp = ig.DeclareLocal (type);
 
                        ig.Emit (OpCodes.Stloc, temp);
@@ -4665,8 +5332,8 @@ namespace Mono.CSharp {
 
                                Expression e = null;
 
-                               if (ArrayData [i] is Expression)
-                                       e = (Expression) ArrayData [i];
+                               if (array_data [i] is Expression)
+                                       e = (Expression) array_data [i];
 
                                if (e != null) {
                                        //
@@ -4679,17 +5346,17 @@ namespace Mono.CSharp {
                                                
                                                ig.Emit (OpCodes.Ldloc, temp);
 
-                                               for (int idx = dims; idx > 0; ) {
-                                                       idx--;
+                                               for (int idx = 0; idx < dims; idx++) 
                                                        IntConstant.EmitInt (ig, current_pos [idx]);
-                                               }
 
                                                //
                                                // If we are dealing with a struct, get the
                                                // address of it, so we can store it.
                                                //
-                                               if (etype.IsSubclassOf (TypeManager.value_type) &&
-                                                   !TypeManager.IsBuiltinType (etype)){
+                                               if ((dims == 1) &&
+                                                   etype.IsSubclassOf (TypeManager.value_type) &&
+                                                   (!TypeManager.IsBuiltinType (etype) ||
+                                                    etype == TypeManager.decimal_type)) {
                                                        if (e is New){
                                                                New n = (New) e;
 
@@ -4702,7 +5369,7 @@ namespace Mono.CSharp {
                                                                             
                                                        ig.Emit (OpCodes.Ldelema, etype);
                                                }
-                                                   
+
                                                e.Emit (ec);
                                                
                                                if (dims == 1)
@@ -4715,9 +5382,9 @@ namespace Mono.CSharp {
                                //
                                // Advance counter
                                //
-                               for (int j = 0; j < dims; j++){
+                               for (int j = dims - 1; j >= 0; j--){
                                        current_pos [j]++;
-                                       if (current_pos [j] < (int) Bounds [j])
+                                       if (current_pos [j] < (int) bounds [j])
                                                break;
                                        current_pos [j] = 0;
                                }
@@ -4729,8 +5396,17 @@ namespace Mono.CSharp {
 
                void EmitArrayArguments (EmitContext ec)
                {
-                       foreach (Argument a in Arguments)
+                       ILGenerator ig = ec.ig;
+                       
+                       foreach (Argument a in arguments) {
+                               Type atype = a.Type;
                                a.Emit (ec);
+
+                               if (atype == TypeManager.uint64_type)
+                                       ig.Emit (OpCodes.Conv_Ovf_U4);
+                               else if (atype == TypeManager.int64_type)
+                                       ig.Emit (OpCodes.Conv_Ovf_I4);
+                       }
                }
                
                void DoEmit (EmitContext ec, bool is_statement)
@@ -4738,16 +5414,16 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        EmitArrayArguments (ec);
-                       if (IsOneDimensional)
+                       if (is_one_dimensional)
                                ig.Emit (OpCodes.Newarr, array_element_type);
                        else {
-                               if (IsBuiltinType) 
-                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+                               if (is_builtin_type) 
+                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
                                else 
-                                       ig.Emit (OpCodes.Newobj, (MethodInfo) method);
+                                       ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
                        }
                        
-                       if (Initializers != null){
+                       if (initializers != null){
                                //
                                // FIXME: Set this variable correctly.
                                // 
@@ -4777,36 +5453,78 @@ namespace Mono.CSharp {
        }
        
        /// <summary>
-       ///   Represents the `this' construct
+       ///   Represents the 'this' construct
        /// </summary>
-       public class This : Expression, IAssignMethod, IMemoryLocation {
-               Location loc;
+       public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
+
+               Block block;
+               VariableInfo vi;
                
+               public This (Block block, Location loc)
+               {
+                       this.loc = loc;
+                       this.block = block;
+               }
+
                public This (Location loc)
                {
                        this.loc = loc;
                }
 
+               public bool IsAssigned (EmitContext ec, Location loc)
+               {
+                       if (vi == null)
+                               return true;
+
+                       return vi.IsAssigned (ec, loc);
+               }
+
+               public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
+               {
+                       if (vi == null)
+                               return true;
+
+                       return vi.IsFieldAssigned (ec, field_name, loc);
+               }
+
+               public void SetAssigned (EmitContext ec)
+               {
+                       if (vi != null)
+                               vi.SetAssigned (ec);
+               }
+
+               public void SetFieldAssigned (EmitContext ec, string field_name)
+               {       
+                       if (vi != null)
+                               vi.SetFieldAssigned (ec, field_name);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
                        type = ec.ContainerType;
 
                        if (ec.IsStatic){
-                               Report.Error (26, loc,
-                                             "Keyword this not valid in static code");
+                               Error (26, "Keyword this not valid in static code");
                                return null;
                        }
-                       
+
+                       if (block != null)
+                               vi = block.ThisVariable;
+
                        return this;
                }
 
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        DoResolve (ec);
+
+                       VariableInfo vi = ec.CurrentBlock.ThisVariable;
+                       if (vi != null)
+                               vi.SetAssigned (ec);
                        
                        if (ec.TypeContainer is Class){
-                               Report.Error (1604, loc, "Cannot assign to `this'");
+                               Error (1604, "Cannot assign to 'this'");
                                return null;
                        }
 
@@ -4815,13 +5533,25 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
+                       ILGenerator ig = ec.ig;
+                       
+                       ig.Emit (OpCodes.Ldarg_0);
+                       if (ec.TypeContainer is Struct)
+                               ig.Emit (OpCodes.Ldobj, type);
                }
 
                public void EmitAssign (EmitContext ec, Expression source)
                {
-                       source.Emit (ec);
-                       ec.ig.Emit (OpCodes.Starg, 0);
+                       ILGenerator ig = ec.ig;
+                       
+                       if (ec.TypeContainer is Struct){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               source.Emit (ec);
+                               ig.Emit (OpCodes.Stobj, type);
+                       } else {
+                               source.Emit (ec);
+                               ig.Emit (OpCodes.Starg, 0);
+                       }
                }
 
                public void AddressOf (EmitContext ec, AddressOp mode)
@@ -4833,7 +5563,7 @@ namespace Mono.CSharp {
                        //
                        // consider: struct X { int val; int P { set { val = value; }}}
                        //
-                       // Yes, this looks very bad. Look at `NOTAS' for
+                       // Yes, this looks very bad. Look at 'NOTAS' for
                        // an explanation.
                        // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
                }
@@ -4843,11 +5573,10 @@ namespace Mono.CSharp {
        ///   Implements the typeof operator
        /// </summary>
        public class TypeOf : Expression {
-               public readonly string QueriedType;
+               public readonly Expression QueriedType;
                Type typearg;
-               Location loc;
                
-               public TypeOf (string queried_type, Location l)
+               public TypeOf (Expression queried_type, Location l)
                {
                        QueriedType = queried_type;
                        loc = l;
@@ -4855,8 +5584,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       typearg = RootContext.LookupType (
-                               ec.DeclSpace, QueriedType, false, loc);
+                       typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
 
                        if (typearg == null)
                                return null;
@@ -4881,11 +5609,10 @@ namespace Mono.CSharp {
        ///   Implements the sizeof expression
        /// </summary>
        public class SizeOf : Expression {
-               public readonly string QueriedType;
+               public readonly Expression QueriedType;
                Type type_queried;
-               Location loc;
                
-               public SizeOf (string queried_type, Location l)
+               public SizeOf (Expression queried_type, Location l)
                {
                        this.QueriedType = queried_type;
                        loc = l;
@@ -4893,11 +5620,21 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       type_queried = RootContext.LookupType (
-                               ec.DeclSpace, QueriedType, false, loc);
+                       if (!ec.InUnsafe) {
+                               Error (233, "Sizeof may only be used in an unsafe context " +
+                                      "(consider using System.Runtime.InteropServices.Marshal.Sizeof");
+                               return null;
+                       }
+                               
+                       type_queried = ec.DeclSpace.ResolveType (QueriedType, false, loc);
                        if (type_queried == null)
                                return null;
 
+                       if (!TypeManager.IsUnmanagedType (type_queried)){
+                               Report.Error (208, "Cannot take the size of an unmanaged type (" + TypeManager.MonoBASIC_Name (type_queried) + ")");
+                               return null;
+                       }
+                       
                        type = TypeManager.int32_type;
                        eclass = ExprClass.Value;
                        return this;
@@ -4917,11 +5654,10 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the member access expression
        /// </summary>
-       public class MemberAccess : Expression {
+       public class MemberAccess : Expression, ITypeExpression {
                public readonly string Identifier;
                Expression expr;
                Expression member_lookup;
-               Location loc;
                
                public MemberAccess (Expression expr, string id, Location l)
                {
@@ -4938,7 +5674,7 @@ namespace Mono.CSharp {
 
                static void error176 (Location loc, string name)
                {
-                       Report.Error (176, loc, "Static member `" +
+                       Report.Error (176, loc, "Static member '" +
                                      name + "' cannot be accessed " +
                                      "with an instance reference, qualify with a " +
                                      "type name instead");
@@ -4965,57 +5701,20 @@ namespace Mono.CSharp {
                                                              Expression left, Location loc,
                                                              Expression left_original)
                {
-                       //
-                       // Method Groups
-                       //
-                       if (member_lookup is MethodGroupExpr){
-                               MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
+                       bool left_is_type, left_is_explicit;
 
-                               //
-                               // Type.MethodGroup
-                               //
-                               if (left is TypeExpr){
-                                       if (!mg.RemoveInstanceMethods ()){
-                                               SimpleName.Error120 (loc, mg.Methods [0].Name); 
-                                               return null;
-                                       }
+                       // If 'left' is null, then we're called from SimpleNameResolve and this is
+                       // a member in the currently defining class.
+                       if (left == null) {
+                               left_is_type = ec.IsStatic || ec.IsFieldInitializer;
+                               left_is_explicit = false;
 
-                                       return member_lookup;
-                               }
-
-                               //
-                               // 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 = left;
-                                       
-                               return member_lookup;
-#endif
+                               // Implicitly default to 'this' unless we're static.
+                               if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
+                                       left = ec.This;
+                       } else {
+                               left_is_type = left is TypeExpr;
+                               left_is_explicit = true;
                        }
 
                        if (member_lookup is FieldExpr){
@@ -5045,6 +5744,12 @@ namespace Mono.CSharp {
                                                o = fi.GetValue (fi);
                                        
                                        if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
+                                               if (left_is_explicit && !left_is_type &&
+                                                   !IdenticalNameAndTypeName (ec, left_original, loc)) {
+                                                       error176 (loc, fe.FieldInfo.Name);
+                                                       return null;
+                                               }                                       
+                                               
                                                Expression enum_member = MemberLookup (
                                                        ec, decl_type, "value__", MemberTypes.Field,
                                                        AllBindingFlags, loc); 
@@ -5052,69 +5757,31 @@ namespace Mono.CSharp {
                                                Enum en = TypeManager.LookupEnum (decl_type);
 
                                                Constant c;
-                                               if (en != null)
+                                               if (en != null) {
                                                        c = Constantify (o, en.UnderlyingType);
-                                               else 
+                                                       return new EnumConstant (c, en.UnderlyingType);
+                                               }
+                                               else {
                                                        c = Constantify (o, enum_member.Type);
+                                                       return new EnumConstant (c, enum_member.Type);
+                                               }
+                                               
                                                
-                                               return new EnumConstant (c, decl_type);
-                                       }
-                                       
-                                       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 (left is TypeExpr){
-                                       // and refers to a type name or an 
-                                       if (!fe.FieldInfo.IsStatic){
-                                               error176 (loc, fe.FieldInfo.Name);
-                                               return null;
                                        }
-                                       return member_lookup;
-                               } else {
-                                       if (fe.FieldInfo.IsStatic){
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
-                                                       return member_lookup;
+                                       
+                                       Expression exp = Constantify (o, t);
 
+                                       if (left_is_explicit && !left_is_type) {
                                                error176 (loc, fe.FieldInfo.Name);
                                                return null;
                                        }
-                                       fe.InstanceExpression = left;
-
-                                       return fe;
+                                       
+                                       return exp;
                                }
-                       }
 
-                       if (member_lookup is PropertyExpr){
-                               PropertyExpr pe = (PropertyExpr) member_lookup;
-
-                               if (left is TypeExpr){
-                                       if (!pe.IsStatic){
-                                               SimpleName.Error120 (loc, pe.PropertyInfo.Name);
-                                               return null;
-                                       }
-                                       return pe;
-                               } else {
-                                       if (pe.IsStatic){
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
-                                                       return member_lookup;
-                                               error176 (loc, pe.PropertyInfo.Name);
-                                               return null;
-                                       }
-                                       pe.InstanceExpression = left;
-                                       
-                                       return pe;
+                               if (fi.FieldType.IsPointer && !ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
                                }
                        }
 
@@ -5127,12 +5794,8 @@ namespace Mono.CSharp {
                                // a FieldExpr
                                //
 
-                               Expression ml = MemberLookup (
-                                       ec, ec.ContainerType,
-                                       ee.EventInfo.Name, MemberTypes.Event, AllBindingFlags, loc);
-
-                               if (ml != null) {
-                                       MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
+                               if (ee.EventInfo.DeclaringType == ec.ContainerType) {
+                                       MemberInfo mi = GetFieldFromEvent (ee);
 
                                        if (mi == null) {
                                                //
@@ -5144,40 +5807,73 @@ namespace Mono.CSharp {
                                                return null;
                                        }
 
-                                       ml = ExprClassFromMemberInfo (ec, mi, loc);
+                                       Expression 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 (member_lookup is IMemberExpr) {
+                               IMemberExpr me = (IMemberExpr) member_lookup;
+
+                               if (left_is_type){
+                                       MethodGroupExpr mg = me as MethodGroupExpr;
+                                       if ((mg != null) && left_is_explicit && left.Type.IsInterface)
+                                               mg.IsExplicitImpl = left_is_explicit;
+
+                                       if (!me.IsStatic){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
 
-                               if (left is TypeExpr) {
-                                       if (!ee.IsStatic) {
-                                               SimpleName.Error120 (loc, ee.EventInfo.Name);
+                                               SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
                                                return null;
                                        }
 
-                                       return ee;
-
                                } else {
-                                       if (ee.IsStatic) {
+                                       if (!me.IsInstance){
                                                if (IdenticalNameAndTypeName (ec, left_original, loc))
-                                                       return ee;
-                                                   
-                                               error176 (loc, ee.EventInfo.Name);
-                                               return null;
+                                                       return member_lookup;
+
+                                               /*if (left_is_explicit) {
+                                                       error176 (loc, me.Name);
+                                                       return null;
+                                               }*/
                                        }
 
-                                       ee.InstanceExpression = left;
+                                       //
+                                       // Since we can not check for instance objects in SimpleName,
+                                       // becaue of the rule that allows types and variables to share
+                                       // the name (as long as they can be de-ambiguated later, see 
+                                       // IdenticalNameAndTypeName), we have to check whether left 
+                                       // is an instance variable in a static context
+                                       //
+                                       // However, if the left-hand value is explicitly given, then
+                                       // it is already our instance expression, so we aren't in
+                                       // static context.
+                                       //
+
+                                       if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
+                                               IMemberExpr mexp = (IMemberExpr) left;
+
+                                               if (!mexp.IsStatic){
+                                                       SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name);
+                                                       return null;
+                                               }
+                                       }
 
-                                       return ee;
+                                       me.InstanceExpression = left;
                                }
+
+                               return member_lookup;
                        }
 
                        if (member_lookup is TypeExpr){
-                               member_lookup.Resolve (ec);
+                               member_lookup.Resolve (ec, ResolveFlags.Type);
                                return member_lookup;
                        }
                        
@@ -5187,85 +5883,158 @@ namespace Mono.CSharp {
                        return null;
                }
                
-               public override Expression DoResolve (EmitContext ec)
+               public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags)
                {
+                       if (type != null)
+                               throw new Exception ();
                        //
-                       // We are the sole users of ResolveWithSimpleName (ie, the only
-                       // ones that can cope with it
+                       // Resolve the expression with flow analysis turned off, we'll do the definite
+                       // assignment checks later.  This is because we don't know yet what the expression
+                       // will resolve to - it may resolve to a FieldExpr and in this case we must do the
+                       // definite assignment check on the actual field and not on the whole struct.
                        //
+
                        Expression original = expr;
-                       expr = expr.ResolveWithSimpleName (ec);
+                       expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
 
                        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);
+                               Expression new_expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
+
+                               if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
+                                       return new_expr.Resolve (ec, flags);
+                               else
+                                       return new_expr.Resolve (ec, flags | ResolveFlags.MethodGroup | ResolveFlags.VariableOrValue);
                        }
                                        
-                       //
-                       // 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
-                       //
-
+                       int errors = Report.Errors;
+                       
                        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) + ")");
+                               Error (23, "The '.' operator can not be applied to pointer operands (" +
+                                      TypeManager.MonoBASIC_Name (expr_type) + ")");
                                return null;
                        }
-                       
+
                        member_lookup = MemberLookup (ec, expr_type, Identifier, loc);
 
-                       if (member_lookup == null){
+                       if (member_lookup == null)
+                       {
+                               // Error has already been reported.
+                               if (errors < Report.Errors)
+                                       return null;
+                               
                                //
                                // Try looking the member up from the same type, if we find
                                // it, we know that the error was due to limited visibility
                                //
                                object lookup = TypeManager.MemberLookup (
-                                       expr_type, expr_type, AllMemberTypes, AllBindingFlags, Identifier);
+                                       expr_type, expr_type, AllMemberTypes, AllBindingFlags |
+                                       BindingFlags.NonPublic, Identifier);
+                                       
                                if (lookup == null)
-                                       Report.Error (117, loc, "`" + expr_type + "' does not contain a " +
-                                                     "definition for `" + Identifier + "'");
+                                       Error (30456, "'" + expr_type + "' does not contain a definition for '" + Identifier + "'");
                                else
-                                       Report.Error (122, loc, "`" + expr_type + "." + Identifier + "' " +
-                                                     "is inaccessible because of its protection level");
-                                             
+                               {
+                                       if ((expr_type != ec.ContainerType) &&
+                                                ec.ContainerType.IsSubclassOf (expr_type))
+                                       {
+
+                                               // Although a derived class can access protected members of
+                                               // its base class it cannot do so through an instance of the
+                                               // base class (CS1540).  If the expr_type is a parent of the
+                                               // ec.ContainerType and the lookup succeeds with the latter one,
+                                               // then we are in this situation.
+
+                                               lookup = TypeManager.MemberLookup(
+                                                                       ec.ContainerType, ec.ContainerType, AllMemberTypes, 
+                                                                       AllBindingFlags, Identifier);
+
+                                               if (lookup != null)
+                                                       Error (1540, "Cannot access protected member '" +
+                                                      expr_type + "." + Identifier + "' " +
+                                                      "via a qualifier of type '" + TypeManager.MonoBASIC_Name (expr_type) + "'; the " +
+                                                      "qualifier must be of type '" + TypeManager.MonoBASIC_Name (ec.ContainerType) + "' " +
+                                                      "(or derived from it)");
+                                               else
+                                                       Error (30390, "'" + expr_type + "." + Identifier + "' " +
+                                                      "is inaccessible because of its protection level");
+                                       } else
+                                               Error (30390, "'" + expr_type + "." + Identifier + "' " +
+                                              "is inaccessible because of its protection level");
+                               }  
                                return null;
                        }
 
-                       return ResolveMemberAccess (ec, member_lookup, expr, loc, original);
+                       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);
+                                       expr_type = TypeManager.int32_type;
+                                       if (value != null) {
+                                               Constant c = Constantify (value, en.UnderlyingType);
+                                               return new EnumConstant (c, en.UnderlyingType);
+                                       }
+                               }
+                       }
+
+                       if (member_lookup is TypeExpr){
+                               member_lookup.Resolve (ec, ResolveFlags.Type);
+
+                               return member_lookup;
+                       } else if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
+                               return null;
+                       
+                       member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
+                       if (member_lookup == null)
+                               return null;
+
+                       // The following DoResolve/DoResolveLValue will do the definite assignment
+                       // check.
+                       if (right_side != null)
+                               member_lookup = member_lookup.DoResolveLValue (ec, right_side);
+                       else
+                               member_lookup = member_lookup.DoResolve (ec);
+
+                       return member_lookup;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolve (ec, null, ResolveFlags.VariableOrValue |
+                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
+                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+               }
+
+               public Expression DoResolveType (EmitContext ec)
+               {
+                       return DoResolve (ec, null, ResolveFlags.Type);
                }
 
                public override void Emit (EmitContext ec)
                {
                        throw new Exception ("Should not happen");
                }
+
+               public override string ToString ()
+               {
+                       return expr + "." + Identifier;
+               }
        }
 
+       
+       
        /// <summary>
        ///   Implements checked expressions
        /// </summary>
@@ -5273,9 +6042,10 @@ namespace Mono.CSharp {
 
                public Expression Expr;
 
-               public CheckedExpr (Expression e)
+               public CheckedExpr (Expression e, Location l)
                {
                        Expr = e;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -5289,6 +6059,9 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
+                       if (Expr is Constant)
+                               return Expr;
+                       
                        eclass = Expr.eclass;
                        type = Expr.Type;
                        return this;
@@ -5315,9 +6088,10 @@ namespace Mono.CSharp {
 
                public Expression Expr;
 
-               public UnCheckedExpr (Expression e)
+               public UnCheckedExpr (Expression e, Location l)
                {
                        Expr = e;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -5331,6 +6105,9 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
+                       if (Expr is Constant)
+                               return Expr;
+                       
                        eclass = Expr.eclass;
                        type = Expr.Type;
                        return this;
@@ -5359,7 +6136,6 @@ namespace Mono.CSharp {
        public class ElementAccess : Expression {
                public ArrayList  Arguments;
                public Expression Expr;
-               public Location   loc;
                
                public ElementAccess (Expression e, ArrayList e_list, Location l)
                {
@@ -5399,19 +6175,20 @@ namespace Mono.CSharp {
                        Type t = Expr.Type;
 
                        if (t == TypeManager.void_ptr_type){
-                               Report.Error (
-                                       242, loc,
+                               Error (
+                                       242,
                                        "The array index operation is not valid for void pointers");
                                return null;
                        }
                        if (Arguments.Count != 1){
-                               Report.Error (
-                                       196, loc,
+                               Error (
+                                       196,
                                        "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);
+                       Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr,
+                                                             t, loc);
+                       return new Indirection (p, loc);
                }
                
                public override Expression DoResolve (EmitContext ec)
@@ -5427,12 +6204,12 @@ namespace Mono.CSharp {
                        //
                        Type t = Expr.Type;
 
-                       if (t.IsSubclassOf (TypeManager.array_type))
-                               return (new ArrayAccess (this)).Resolve (ec);
+                       if (t.IsArray)
+                               return (new ArrayAccess (this, loc)).Resolve (ec);
                        else if (t.IsPointer)
                                return MakePointerAccess ();
                        else
-                               return (new IndexerAccess (this)).Resolve (ec);
+                               return (new IndexerAccess (this, loc)).Resolve (ec);
                }
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
@@ -5441,12 +6218,12 @@ namespace Mono.CSharp {
                                return null;
 
                        Type t = Expr.Type;
-                       if (t.IsSubclassOf (TypeManager.array_type))
-                               return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
+                       if (t.IsArray)
+                               return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
                        else if (t.IsPointer)
                                return MakePointerAccess ();
                        else
-                               return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
+                               return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
                }
                
                public override void Emit (EmitContext ec)
@@ -5465,11 +6242,12 @@ namespace Mono.CSharp {
                ElementAccess ea;
 
                LocalTemporary [] cached_locations;
-               
-               public ArrayAccess (ElementAccess ea_data)
+
+               public ArrayAccess (ElementAccess ea_data, Location l)
                {
                        ea = ea_data;
                        eclass = ExprClass.Variable;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -5480,24 +6258,73 @@ namespace Mono.CSharp {
                        // As long as the type is valid
                        if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
                              eclass == ExprClass.Value)) {
-                               report118 (ea.loc, ea.Expr, "variable or value");
+                               ea.Expr.Error118 ("variable or value");
                                return null;
                        }
 #endif
 
                        Type t = ea.Expr.Type;
+/*
+                       if (t == typeof (System.Object))
+                       {
+                               // We can't resolve now, but we
+                               // have to try to access the array with a call
+                               // to LateIndexGet in the runtime
+
+                               Expression lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexGet", Location.Null);
+                               Expression obj_type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", Location.Null);
+                               ArrayList adims = new ArrayList();
+
+                               ArrayList ainit = new ArrayList();
+                               foreach (Argument a in ea.Arguments)
+                                       ainit.Add ((Expression) a.Expr);
+
+                               adims.Add ((Expression) new IntLiteral (ea.Arguments.Count));
+
+                               Expression oace = new ArrayCreation (obj_type, adims, "", ainit, Location.Null);
+
+                               ArrayList args = new ArrayList();
+                               args.Add (new Argument(ea.Expr, Argument.AType.Expression));
+                               args.Add (new Argument(oace, Argument.AType.Expression));
+                               args.Add (new Argument(NullLiteral.Null, Argument.AType.Expression));
+
+                               Expression lig_call = new Invocation (lig_call_expr, args, Location.Null);
+                               lig_call = lig_call.Resolve(ec);
+                               return lig_call;
+                       }
+*/
                        if (t.GetArrayRank () != ea.Arguments.Count){
-                               Report.Error (22, ea.loc,
-                                             "Incorrect number of indexes for array " +
-                                             " expected: " + t.GetArrayRank () + " got: " +
-                                             ea.Arguments.Count);
+                               ea.Error (22,
+                                         "Incorrect number of indexes for array " +
+                                         " expected: " + t.GetArrayRank () + " got: " +
+                                         ea.Arguments.Count);
                                return null;
                        }
-                       type = t.GetElementType ();
+                       type = TypeManager.TypeToCoreType (t.GetElementType ());
                        if (type.IsPointer && !ec.InUnsafe){
-                               UnsafeError (ea.loc);
+                               UnsafeError (ea.Location);
                                return null;
                        }
+
+                       foreach (Argument a in ea.Arguments){
+                               Type argtype = a.Type;
+
+                               if (argtype == TypeManager.int32_type ||
+                                   argtype == TypeManager.uint32_type ||
+                                   argtype == TypeManager.int64_type ||
+                                   argtype == TypeManager.uint64_type)
+                                       continue;
+
+                               //
+                               // Mhm.  This is strage, because the Argument.Type is not the same as
+                               // Argument.Expr.Type: the value changes depending on the ref/out setting.
+                               //
+                               // Wonder if I will run into trouble for this.
+                               //
+                               a.Expr = ExpressionToArrayArgument (ec, a.Expr, ea.Location);
+                               if (a.Expr == null)
+                                       return null;
+                       }
                        
                        eclass = ExprClass.Variable;
 
@@ -5505,18 +6332,18 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///    Emits the right opcode to load an object of Type `t'
+               ///    Emits the right opcode to load an object of Type 't'
                ///    from an array of T
                /// </summary>
                static public void EmitLoadOpcode (ILGenerator ig, Type 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);
+                       else if (type == TypeManager.sbyte_type)
+                               ig.Emit (OpCodes.Ldelem_I1);
                        else if (type == TypeManager.short_type)
                                ig.Emit (OpCodes.Ldelem_I2);
-                       else if (type == TypeManager.ushort_type)
+                       else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
                                ig.Emit (OpCodes.Ldelem_U2);
                        else if (type == TypeManager.int32_type)
                                ig.Emit (OpCodes.Ldelem_I4);
@@ -5540,11 +6367,14 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///    Emits the right opcode to store an object of Type `t'
+               ///    Emits the right opcode to store an object of Type 't'
                ///    from an array of T.  
                /// </summary>
                static public void EmitStoreOpcode (ILGenerator ig, Type t)
                {
+                       t = TypeManager.TypeToCoreType (t);
+                       if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type)
+                               t = TypeManager.EnumToUnderlying (t);
                        if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
                            t == TypeManager.bool_type)
                                ig.Emit (OpCodes.Stelem_I1);
@@ -5560,9 +6390,9 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Stelem_R8);
                        else if (t == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Stelem_I);
-                       else if (t.IsValueType)
+                       else if (t.IsValueType){
                                ig.Emit (OpCodes.Stobj, t);
-                       else
+                       else
                                ig.Emit (OpCodes.Stelem_Ref);
                }
 
@@ -5629,15 +6459,23 @@ namespace Mono.CSharp {
                //
                void LoadArrayAndArguments (EmitContext ec)
                {
+                       ILGenerator ig = ec.ig;
+                       
                        if (cached_locations == null){
                                ea.Expr.Emit (ec);
-                               foreach (Argument a in ea.Arguments)
+                               foreach (Argument a in ea.Arguments){
+                                       Type argtype = a.Expr.Type;
+                                       
                                        a.Expr.Emit (ec);
+                                       
+                                       if (argtype == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I);
+                                       else if (argtype == TypeManager.uint64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I_Un);
+                               }
                                return;
                        }
 
-                       ILGenerator ig = ec.ig;
-                       
                        if (cached_locations [0] == null){
                                cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
                                ea.Expr.Emit (ec);
@@ -5647,8 +6485,15 @@ namespace Mono.CSharp {
                                int j = 1;
                                
                                foreach (Argument a in ea.Arguments){
-                                       cached_locations [j] = new LocalTemporary (ec, a.Expr.Type);
+                                       Type argtype = a.Expr.Type;
+                                       
+                                       cached_locations [j] = new LocalTemporary (ec, TypeManager.intptr_type /* a.Expr.Type */);
                                        a.Expr.Emit (ec);
+                                       if (argtype == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I);
+                                       else if (argtype == TypeManager.uint64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I_Un);
+
                                        ig.Emit (OpCodes.Dup);
                                        cached_locations [j].Store (ec);
                                        j++;
@@ -5696,7 +6541,8 @@ namespace Mono.CSharp {
                        // pair
                        //
                        if (rank == 1){
-                               if (t.IsValueType && !TypeManager.IsBuiltinType (t))
+                               if (t == TypeManager.enum_type || t == TypeManager.decimal_type ||
+                                   (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t)))
                                        ig.Emit (OpCodes.Ldelema, t);
                        }
                        
@@ -5774,8 +6620,8 @@ namespace Mono.CSharp {
                                }
                        }
                }
-               
-               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
+
+               static private Indexers GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
                {
                        Indexers ix = (Indexers) map [lookup_type];
                        
@@ -5788,18 +6634,40 @@ namespace Mono.CSharp {
                                caller_type, lookup_type, MemberTypes.Property,
                                BindingFlags.Public | BindingFlags.Instance, p_name);
 
-                       if (mi == null || mi.Length == 0){
-                               Report.Error (21, loc,
-                                             "Type `" + TypeManager.CSharpName (lookup_type) +
-                                             "' does not have any indexers defined");
+                       if (mi == null || mi.Length == 0)
                                return null;
-                       }
-                       
+
                        ix = new Indexers (mi);
                        map [lookup_type] = ix;
 
                        return ix;
                }
+               
+               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
+               {
+                       Indexers ix = (Indexers) map [lookup_type];
+                       
+                       if (ix != null)
+                               return ix;
+
+                       ix = GetIndexersForTypeOrInterface (caller_type, lookup_type);
+                       if (ix != null)
+                               return ix;
+
+                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+                       if (ifaces != null) {
+                               foreach (Type itype in ifaces) {
+                                       ix = GetIndexersForTypeOrInterface (caller_type, itype);
+                                       if (ix != null)
+                                               return ix;
+                               }
+                       }
+
+                       Report.Error (21, loc,
+                                     "Type '" + TypeManager.MonoBASIC_Name (lookup_type) +
+                                     "' does not have any indexers defined");
+                       return null;
+               }
        }
 
        /// <summary>
@@ -5809,52 +6677,70 @@ namespace Mono.CSharp {
                //
                // Points to our "data" repository
                //
-               ElementAccess ea;
                MethodInfo get, set;
                Indexers ilist;
                ArrayList set_arguments;
+               bool is_base_indexer;
+
+               protected Type indexer_type;
+               protected Type current_type;
+               protected Expression instance_expr;
+               protected ArrayList arguments;
                
-               public IndexerAccess (ElementAccess ea_data)
+               public IndexerAccess (ElementAccess ea, Location loc)
+                       : this (ea.Expr, false, loc)
                {
-                       ea = ea_data;
-                       eclass = ExprClass.Value;
+                       this.arguments = ea.Arguments;
+               }
+
+               protected IndexerAccess (Expression instance_expr, bool is_base_indexer,
+                                        Location loc)
+               {
+                       this.instance_expr = instance_expr;
+                       this.is_base_indexer = is_base_indexer;
+                       this.eclass = ExprClass.Value;
+                       this.loc = loc;
+               }
+
+               protected virtual bool CommonResolve (EmitContext ec)
+               {
+                       indexer_type = instance_expr.Type;
+                       current_type = ec.ContainerType;
+
+                       return true;
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       Type indexer_type = ea.Expr.Type;
-                       
+                       if (!CommonResolve (ec))
+                               return null;
+
                        //
-                       // Step 1: Query for all `Item' *properties*.  Notice
+                       // Step 1: Query for all 'Item' *properties*.  Notice
                        // that the actual methods are pointed from here.
                        //
                        // This is a group of properties, piles of them.  
 
                        if (ilist == null)
                                ilist = Indexers.GetIndexersForType (
-                                       ec.ContainerType, indexer_type, ea.loc);
-
+                                       current_type, indexer_type, loc);
 
                        //
                        // Step 2: find the proper match
                        //
-                       if (ilist != null && ilist.getters != null && ilist.getters.Count > 0){
-                               Location loc = ea.loc;
-                               
+                       if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)
                                get = (MethodInfo) Invocation.OverloadResolve (
-                                       ec, new MethodGroupExpr (ilist.getters, loc), ea.Arguments, loc);
-                       }
+                                       ec, new MethodGroupExpr (ilist.getters, loc), arguments, loc);
 
                        if (get == null){
-                               Report.Error (154, ea.loc,
-                                             "indexer can not be used in this context, because " +
-                                             "it lacks a `get' accessor");
+                               Error (154, "indexer can not be used in this context, because " +
+                                      "it lacks a 'get' accessor");
                                return null;
                        }
 
                        type = get.ReturnType;
                        if (type.IsPointer && !ec.InUnsafe){
-                               UnsafeError (ea.loc);
+                               UnsafeError (loc);
                                return null;
                        }
                        
@@ -5864,17 +6750,17 @@ namespace Mono.CSharp {
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       Type indexer_type = ea.Expr.Type;
+                       if (!CommonResolve (ec))
+                               return null;
+
                        Type right_type = right_side.Type;
 
                        if (ilist == null)
                                ilist = Indexers.GetIndexersForType (
-                                       ec.ContainerType, indexer_type, ea.loc);
+                                       current_type, indexer_type, loc);
 
                        if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
-                               Location loc = ea.loc;
-                               
-                               set_arguments = (ArrayList) ea.Arguments.Clone ();
+                               set_arguments = (ArrayList) arguments.Clone ();
                                set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
 
                                set = (MethodInfo) Invocation.OverloadResolve (
@@ -5882,10 +6768,9 @@ namespace Mono.CSharp {
                        }
                        
                        if (set == null){
-                               Report.Error (200, ea.loc,
-                                             "indexer X.this [" + TypeManager.CSharpName (right_type) +
-                                             "] lacks a `set' accessor");
-                                       return null;
+                               Error (200, "indexer X.this [" + TypeManager.MonoBASIC_Name (right_type) +
+                                      "] lacks a 'set' accessor");
+                               return null;
                        }
 
                        type = TypeManager.void_type;
@@ -5895,7 +6780,7 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
-                       Invocation.EmitCall (ec, false, false, ea.Expr, get, ea.Arguments);
+                       Invocation.EmitCall (ec, false, false, instance_expr, get, arguments, loc);
                }
 
                //
@@ -5905,7 +6790,7 @@ namespace Mono.CSharp {
                //
                public void EmitAssign (EmitContext ec, Expression source)
                {
-                       Invocation.EmitCall (ec, false, false, ea.Expr, set, set_arguments);
+                       Invocation.EmitCall (ec, false, false, instance_expr, set, set_arguments, loc);
                }
        }
 
@@ -5913,8 +6798,7 @@ namespace Mono.CSharp {
        ///   The base operator for method names
        /// </summary>
        public class BaseAccess : Expression {
-               string member;
-               Location loc;
+               public string member;
                
                public BaseAccess (string member, Location l)
                {
@@ -5930,23 +6814,32 @@ namespace Mono.CSharp {
                        Expression e;
 
                        if (ec.IsStatic){
-                               Report.Error (1511, loc,
-                                             "Keyword base is not allowed in static method");
+                               Error (1511, "Keyword MyBase is not allowed in static method");
                                return null;
                        }
                        
-                       member_lookup = MemberLookup (ec, base_type, member, loc);
-                       if (member_lookup == null)
+                       if (member == "New")
+                               member = ".ctor";
+                       
+                       member_lookup = MemberLookup (ec, base_type, base_type, member,
+                                                     AllMemberTypes, AllBindingFlags, loc);
+
+                       if (member_lookup == null) {
+                               Error (30456,
+                                             TypeManager.MonoBASIC_Name (base_type) + " does not " +
+                                             "contain a definition for '" + member + "'");
                                return null;
+                       }
 
                        Expression left;
                        
                        if (ec.IsStatic)
-                               left = new TypeExpr (base_type);
+                               left = new TypeExpr (base_type, loc);
                        else
                                left = ec.This;
                        
                        e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
+
                        if (e is PropertyExpr){
                                PropertyExpr pe = (PropertyExpr) e;
 
@@ -5965,38 +6858,28 @@ namespace Mono.CSharp {
        /// <summary>
        ///   The base indexer operator
        /// </summary>
-       public class BaseIndexerAccess : Expression {
-               ArrayList Arguments;
-               Location loc;
-               
-               public BaseIndexerAccess (ArrayList args, Location l)
+       public class BaseIndexerAccess : IndexerAccess {
+               public BaseIndexerAccess (ArrayList args, Location loc)
+                       : base (null, true, loc)
                {
-                       Arguments = args;
-                       loc = l;
+                       arguments = new ArrayList ();
+                       foreach (Expression tmp in args)
+                               arguments.Add (new Argument (tmp, Argument.AType.Expression));
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               protected override bool CommonResolve (EmitContext ec)
                {
-                       Type current_type = ec.ContainerType;
-                       Type base_type = current_type.BaseType;
-                       Expression member_lookup;
+                       instance_expr = ec.This;
 
-                       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;
+                       current_type = ec.ContainerType.BaseType;
+                       indexer_type = current_type;
 
-                       return MemberAccess.ResolveMemberAccess (ec, member_lookup, ec.This, loc, null);
-               }
+                       foreach (Argument a in arguments){
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                       }
 
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Should never be called");
+                       return true;
                }
        }
        
@@ -6008,19 +6891,21 @@ namespace Mono.CSharp {
        ///   we only care about the side effect conversions to be performed
        ///
        ///   This is also now used as a placeholder where a no-action expression
-       ///   is needed (the `New' class).
+       ///   is needed (the 'New' class).
        /// </summary>
        public class EmptyExpression : Expression {
                public EmptyExpression ()
                {
                        type = TypeManager.object_type;
                        eclass = ExprClass.Value;
+                       loc = Location.Null;
                }
 
                public EmptyExpression (Type t)
                {
                        type = t;
                        eclass = ExprClass.Value;
+                       loc = Location.Null;
                }
                
                public override Expression DoResolve (EmitContext ec)
@@ -6048,12 +6933,13 @@ namespace Mono.CSharp {
                MethodBase method;
                Expression source;
                
-               public UserCast (MethodInfo method, Expression source)
+               public UserCast (MethodInfo method, Expression source, Location l)
                {
                        this.method = method;
                        this.source = source;
                        type = method.ReturnType;
                        eclass = ExprClass.Value;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -6084,10 +6970,9 @@ namespace Mono.CSharp {
        //   the type specification, we just use this to construct the type
        //   one bit at a time.
        // </summary>
-       public class ComposedCast : Expression {
+       public class ComposedCast : Expression, ITypeExpression {
                Expression left;
                string dim;
-               Location loc;
                
                public ComposedCast (Expression left, string dim, Location l)
                {
@@ -6096,35 +6981,61 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               public Expression DoResolveType (EmitContext ec)
                {
-                       left = left.Resolve (ec);
-                       if (left == null)
+                       Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
+                       if (ltype == null)
                                return null;
 
-                       if (left.eclass != ExprClass.Type){
-                               report118 (loc, left, "type");
-                               return null;
+                       //
+                       // ltype.Fullname is already fully qualified, so we can skip
+                       // a lot of probes, and go directly to TypeManager.LookupType
+                       //
+                       string cname = ltype.FullName + dim;
+                       type = TypeManager.LookupTypeDirect (cname);
+                       if (type == null){
+                               //
+                               // For arrays of enumerations we are having a problem
+                               // with the direct lookup.  Need to investigate.
+                               //
+                               // For now, fall back to the full lookup in that case.
+                               //
+                               type = RootContext.LookupType (
+                                       ec.DeclSpace, cname, false, loc);
+
+                               if (type == null)
+                                       return null;
                        }
-                       
-                       type = RootContext.LookupType (
-                               ec.DeclSpace, left.Type.FullName + dim, false, loc);
-                       if (type == null)
-                               return null;
 
+                       if (!ec.ResolvingTypeTree){
+                               //
+                               // If the above flag is set, this is being invoked from the ResolveType function.
+                               // Upper layers take care of the type validity in this context.
+                               //
                        if (!ec.InUnsafe && type.IsPointer){
                                UnsafeError (loc);
                                return null;
                        }
+                       }
                        
                        eclass = ExprClass.Type;
                        return this;
                }
 
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolveType (ec);
+               }
+
                public override void Emit (EmitContext ec)
                {
                        throw new Exception ("This should never be called");
                }
+
+               public override string ToString ()
+               {
+                       return left + dim;
+               }
        }
 
        //
@@ -6134,7 +7045,7 @@ namespace Mono.CSharp {
        public class ArrayPtr : Expression {
                Expression array;
                
-               public ArrayPtr (Expression array)
+               public ArrayPtr (Expression array, Location l)
                {
                        Type array_type = array.Type.GetElementType ();
 
@@ -6150,6 +7061,7 @@ namespace Mono.CSharp {
                        }
 
                        eclass = ExprClass.Value;
+                       loc = l;
                }
 
                public override void Emit (EmitContext ec)
@@ -6176,11 +7088,12 @@ namespace Mono.CSharp {
        public class StringPtr : Expression {
                LocalBuilder b;
                
-               public StringPtr (LocalBuilder b)
+               public StringPtr (LocalBuilder b, Location l)
                {
                        this.b = b;
                        eclass = ExprClass.Value;
                        type = TypeManager.char_ptr_type;
+                       loc = l;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -6203,15 +7116,14 @@ namespace Mono.CSharp {
        }
        
        //
-       // Implements the `stackalloc' keyword
+       // Implements the 'stackalloc' keyword
        //
        public class StackAlloc : Expression {
                Type otype;
-               string t;
+               Expression t;
                Expression count;
-               Location loc;
                
-               public StackAlloc (string type, Expression count, Location l)
+               public StackAlloc (Expression type, Expression count, Location l)
                {
                        t = type;
                        this.count = count;
@@ -6231,12 +7143,12 @@ namespace Mono.CSharp {
                        }
 
                        if (ec.InCatch || ec.InFinally){
-                               Report.Error (255, loc,
+                               Error (255,
                                              "stackalloc can not be used in a catch or finally block");
                                return null;
                        }
-                       
-                       otype = RootContext.LookupType (ec.DeclSpace, t, false, loc);
+
+                       otype = ec.DeclSpace.ResolveType (t, false, loc);
 
                        if (otype == null)
                                return null;