svn path=/trunk/mcs/; revision=38482
[mono.git] / mcs / mbas / expression.cs
index 9975296dfc0768e4e2f092b2be7c84fc10b3de12..52608a3189be02bc72501119a388b25e2f65d3b3 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;
                        
@@ -187,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) ||
@@ -214,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)
@@ -276,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;
@@ -287,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) ||
@@ -322,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;
                                }
@@ -376,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.
                                        //
@@ -389,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;
@@ -514,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)
@@ -542,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)
@@ -633,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 {
@@ -641,7 +666,6 @@ namespace Mono.CSharp {
                }
                
                Mode mode;
-               Location loc;
                Expression expr;
                LocalTemporary temp_storage;
 
@@ -665,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)
@@ -752,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;
                }
 
@@ -924,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;
@@ -952,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;
@@ -964,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)
                {
                }
@@ -995,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);
@@ -1010,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;
@@ -1048,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) + "'");
                                }
                        }
 
@@ -1066,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)
                {
                }
@@ -1089,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)
@@ -1104,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){
@@ -1131,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 {
@@ -1155,6 +1186,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsRuntimeCast
+               {
+                       get {
+                               return runtime_cast;
+                       }
+                       set{
+                               runtime_cast = value;
+                       }
+               }
+
                /// <summary>
                ///   Attempts to do a compile-time folding of a constant cast.
                /// </summary>
@@ -1183,6 +1224,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1207,6 +1250,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1231,6 +1276,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1255,6 +1302,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1279,6 +1328,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1303,6 +1354,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1327,6 +1380,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1351,6 +1406,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1375,6 +1432,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1399,6 +1458,8 @@ namespace Mono.CSharp {
                                        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;
@@ -1410,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);
 
@@ -1438,7 +1487,7 @@ namespace Mono.CSharp {
                                        return e;
                        }
                        
-                       expr = ConvertExplicit (ec, expr, type, loc);
+                       expr = ConvertExplicit (ec, expr, type, runtime_cast, loc);
                        return expr;
                }
 
@@ -1479,8 +1528,6 @@ namespace Mono.CSharp {
                protected MethodBase method;
                ArrayList  Arguments;
 
-               Location   loc;
-
                bool DelegateOperation;
 
                // This must be kept in sync with Operator!!!
@@ -1604,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)
                                + "'");
                }
 
@@ -1705,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){
                                //
@@ -1761,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;
+                               left = ForceConversion (ec, left, TypeManager.int32_type);
+                               right = ForceConversion (ec, right, TypeManager.int32_type);
 
-                               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 = 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 ()
@@ -1803,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)
                {
@@ -1904,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;
 
@@ -1923,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));
@@ -1997,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:
@@ -2014,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;
@@ -2044,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);
                        }
                        
                        //
@@ -2061,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);
@@ -2088,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){
@@ -2109,6 +2187,7 @@ namespace Mono.CSharp {
                                        type = l;
                                        return this;
                                }
+                               Error_OperatorCannotBeApplied ();
                                return null;
                        }
                        
@@ -2159,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
                        //
@@ -2229,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)
@@ -2516,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;
@@ -2580,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)
                {
@@ -2616,14 +2723,17 @@ namespace Mono.CSharp {
                {
                        expr = expr.Resolve (ec);
 
-                       if (expr.Type != TypeManager.bool_type)
+                       if (expr == null)
+                               return null;
+                       
+                       if (expr.Type != TypeManager.bool_type)
                                expr = Expression.ConvertImplicitRequired (
                                        ec, expr, TypeManager.bool_type, loc);
                        
                        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;
@@ -2652,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;
@@ -2666,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;
                                }
                        }
@@ -2692,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);
@@ -2706,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)
                {
@@ -2720,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)
                {
@@ -2739,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;
                }
@@ -2792,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);
                }
        }
@@ -2805,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.
@@ -2833,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
@@ -2852,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)
@@ -2866,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;
@@ -2890,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);
 
@@ -2908,7 +3118,6 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (OpCodes.Starg, arg_idx);
                        }
-                       
                }
 
                public void AddressOf (EmitContext ec, AddressOp mode)
@@ -2918,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 ()
                {
@@ -3066,6 +3172,7 @@ namespace Mono.CSharp {
                        this.expr = expr;
                        Arguments = arguments;
                        loc = l;
+                       CompareName = new MemberFilter (compare_name_filter);
                }
 
                public Expression Expr {
@@ -3076,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)
                {
@@ -3094,6 +3201,7 @@ namespace Mono.CSharp {
                                return (ParameterData) ip;
                        } else {
                                ParameterInfo [] pi = mb.GetParameters ();
+
                                ReflectionParameters rp = new ReflectionParameters (pi);
                                method_parameter_cache [mb] = rp;
 
@@ -3101,123 +3209,8 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///  Determines "better conversion" as specified in 7.4.2.3
-               ///  Returns : 1 if a->p is better
-               ///            0 if a->q or neither is better 
-               /// </summary>
-               static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
-               {
-                       Type argument_type = a.Type;
-                       Expression argument_expr = a.Expr;
-
-                       if (argument_type == null)
-                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
-
-                       if (p == q)
-                               return 0;
-                       
-                       if (argument_type == p)
-                               return 1;
-
-                       if (argument_type == q)
-                               return 0;
+               enum Applicability { Same, Better, Worse };
 
-                       //
-                       // Now probe whether an implicit constant expression conversion
-                       // can be used.
-                       //
-                       // An implicit constant expression conversion permits the following
-                       // conversions:
-                       //
-                       //    * 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.
-                       //
-                       //    * A constant-expression of type long can be converted to type
-                       //      ulong, provided the value of the constant expression is not negative
-                       //
-                       // FIXME: Note that this assumes that constant folding has
-                       // taken place.  We dont do constant folding yet.
-                       //
-
-                       if (argument_expr is IntConstant){
-                               IntConstant ei = (IntConstant) argument_expr;
-                               int value = ei.Value;
-                               
-                               if (p == TypeManager.sbyte_type){
-                                       if (value >= SByte.MinValue && value <= SByte.MaxValue)
-                                               return 1;
-                               } else if (p == TypeManager.byte_type){
-                                       if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
-                                               return 1;
-                               } else if (p == TypeManager.short_type){
-                                       if (value >= Int16.MinValue && value <= Int16.MaxValue)
-                                               return 1;
-                               } else if (p == TypeManager.ushort_type){
-                                       if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
-                                               return 1;
-                               } else if (p == TypeManager.uint32_type){
-                                       //
-                                       // we can optimize this case: a positive int32
-                                       // always fits on a uint32
-                                       //
-                                       if (value >= 0)
-                                               return 1;
-                               } else if (p == TypeManager.uint64_type){
-                                       //
-                                       // we can optimize this case: a positive int32
-                                       // always fits on a uint64
-                                       //
-                                       if (value >= 0)
-                                               return 1;
-                               }
-                       } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){
-                               LongConstant lc = (LongConstant) argument_expr;
-                               
-                               if (p == TypeManager.uint64_type){
-                                       if (lc.Value > 0)
-                                               return 1;
-                               }
-                       }
-
-                       if (q == null) {
-                               Expression tmp = ConvertImplicit (ec, argument_expr, p, loc);
-                               
-                               if (tmp != null)
-                                       return 1;
-                               else
-                                       return 0;
-                       }
-
-                       Expression p_tmp = new EmptyExpression (p);
-                       Expression q_tmp = new EmptyExpression (q);
-                       
-                       if (StandardConversionExists (p_tmp, q) == true &&
-                           StandardConversionExists (q_tmp, p) == false)
-                               return 1;
-
-                       if (p == TypeManager.sbyte_type)
-                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
-                                   q == TypeManager.uint32_type || q == TypeManager.uint64_type)
-                                       return 1;
-
-                       if (p == TypeManager.short_type)
-                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
-                                   q == TypeManager.uint64_type)
-                                       return 1;
-
-                       if (p == TypeManager.int32_type)
-                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
-                                       return 1;
-
-                       if (p == TypeManager.int64_type)
-                               if (q == TypeManager.uint64_type)
-                                       return 1;
-
-                       return 0;
-               }
-               
                /// <summary>
                ///  Determines "Better function"
                /// </summary>
@@ -3226,14 +3219,14 @@ namespace Mono.CSharp {
                ///    0 if candidate ain't better
                ///    1 if candidate is better than the current best match
                /// </remarks>
-               static int BetterFunction (EmitContext ec, ArrayList args,
-                                          MethodBase candidate, MethodBase best,
-                                          bool expanded_form, Location loc)
+               static Applicability BetterFunction (EmitContext ec, ArrayList args,
+                                           MethodBase candidate, MethodBase best,
+                                           bool expanded_form, Location loc)
                {
                        ParameterData candidate_pd = GetParameterData (candidate);
                        ParameterData best_pd;
                        int argument_count;
-               
+
                        if (args == null)
                                argument_count = 0;
                        else
@@ -3242,45 +3235,16 @@ namespace Mono.CSharp {
                        int cand_count = candidate_pd.Count;
 
                        if (cand_count == 0 && argument_count == 0)
-                               return 1;
+                               return Applicability.Same;
 
                        if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
                                if (cand_count != argument_count)
-                                       return 0;
+                                       return Applicability.Worse;
                        
-                       if (best == null) {
-                               int x = 0;
-
-                               if (argument_count == 0 && cand_count == 1 &&
-                                   candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
-                                       return 1;
-                               
-                               for (int j = argument_count; j > 0;) {
-                                       j--;
-
-                                       Argument a = (Argument) args [j];
-                                       Type t = candidate_pd.ParameterType (j);
-
-                                       if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                               if (expanded_form)
-                                                       t = t.GetElementType ();
-
-                                       x = BetterConversion (ec, a, t, null, loc);
-                                       
-                                       if (x <= 0)
-                                               break;
-                               }
-                               
-                               if (x > 0)
-                                       return 1;
-                               else
-                                       return 0;
-                       }
-
                        best_pd = GetParameterData (best);
 
-                       int rating1 = 0, rating2 = 0;
-                       
+                       Applicability res = Applicability.Same;
+
                        for (int j = 0; j < argument_count; ++j) {
                                int x, y;
                                
@@ -3297,20 +3261,20 @@ namespace Mono.CSharp {
                                        if (expanded_form)
                                                bt = bt.GetElementType ();
                                
-                               x = BetterConversion (ec, a, ct, bt, loc);
-                               y = BetterConversion (ec, a, bt, ct, loc);
-
-                               if (x < y)
-                                       return 0;
-                               
-                               rating1 += x;
-                               rating2 += y;
+                               if (ct != bt) {
+                                       if (!WideningConversionExists (ct, bt))
+                                               return Applicability.Worse;
+                                       res = Applicability.Better;
+                               }
                        }
 
-                       if (rating1 > rating2)
-                               return 1;
-                       else
-                               return 0;
+                       if (res == Applicability.Same)
+                               if (candidate_pd.Count < best_pd.Count)
+                                       res = Applicability.Better;
+                               else if (candidate_pd.Count > best_pd.Count)
+                                       res = Applicability.Worse;
+
+                       return res;
                }
 
                public static string FullMethodDesc (MethodBase mb)
@@ -3318,9 +3282,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;
@@ -3424,8 +3388,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) {
 
@@ -3433,8 +3399,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)
@@ -3460,59 +3425,255 @@ namespace Mono.CSharp {
                        return true;
                }
 
+
+               protected enum ConversionType { None, Widening, Narrowing };
+
+               static ConversionType 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 | Parameter.Modifier.OPTIONAL);
+
+                       if (a_mod == p_mod ||
+                               (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
+                               if (a_mod == Parameter.Modifier.NONE) {
+                                       if (! WideningConversionExists (a.Expr, ptype) ) {
+                                               if (! NarrowingConversionExists (ec, a.Expr, ptype) )
+                                                       return ConversionType.None;
+                                               else
+                                                       return ConversionType.Narrowing;
+                                       } else
+                                                       return ConversionType.Widening;
+                               }
+                               
+                               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 ConversionType.None;
+                               }
+                               return ConversionType.Widening;
+                       } else
+                               return ConversionType.None;                                     
+               }
+
+               static bool HasArrayParameter (ParameterData pd)
+               {
+                       int c = pd.Count;
+                       return c > 0 && (pd.ParameterModifier (c - 1) & Parameter.Modifier.PARAMS) != 0;
+               }
+
+               static int CountStandardParams (ParameterData pd) 
+               {
+                       int count = pd.Count;
+                       for (int i = 0; i < count; i++) {
+                               Parameter.Modifier pm = pd.ParameterModifier (i);
+                               if ((pm & (Parameter.Modifier.OPTIONAL | Parameter.Modifier.PARAMS)) != 0)
+                                       return i;
+                       }
+                       return count;
+               }
+
                /// <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 ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate, out bool expanded)
                {
-                       int arg_count;
+                       int arg_count, po_count;
+                       Type param_type;
 
+                       expanded = false;
+                       
                        if (arguments == null)
                                arg_count = 0;
                        else
                                arg_count = arguments.Count;
 
                        ParameterData pd = GetParameterData (candidate);
-
+                       int ps_count = CountStandardParams (pd);                        
                        int pd_count = pd.Count;
 
-                       if (arg_count != pd.Count)
-                               return false;
-                       
-                       for (int i = arg_count; i > 0; ) {
-                               i--;
+                       // Validate argument count
+                       if (ps_count == pd_count) {
+                               if (arg_count != pd_count)
+                                       return ConversionType.None;
+                       }
+                       else {
+                               if (arg_count < ps_count)
+                                       return ConversionType.None;
+                               if (!HasArrayParameter (pd) && arg_count > pd_count)
+                                       return ConversionType.None;
+                       }       
+                       ConversionType result = ConversionType.Widening;
+                       ArrayList newarglist = new ArrayList();
+                       if (arg_count > 0) {
+                               result = ConversionType.None;
+                               int array_param_index = -1;
+                               for (int i = 0; i < arg_count; ++i) {
+                                       Argument a = (Argument) arguments [i];
+                                       param_type = pd.ParameterType (i);
+                                       Parameter.Modifier mod = pd.ParameterModifier (i);
+                                       if (array_param_index < 0 && (mod & Parameter.Modifier.PARAMS) != 0)
+                                               array_param_index = 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 ConversionType.None;
+
+                                                       a = new Argument (del_temp, Argument.AType.Expression);
+                                                       if (!a.Resolve(ec, Location.Null))
+                                                               return ConversionType.None;
+                                               }
+                                       }
+                                       else {
+                                               if (a.ArgType == Argument.AType.AddressOf)
+                                                       return ConversionType.None;
+                                       }
 
+                                       if ((mod & Parameter.Modifier.REF) != 0) {
+                                               a = new Argument (a.Expr, Argument.AType.Ref);
+                                               if (!a.Resolve(ec,Location.Null))
+                                                       return ConversionType.None;
+                                       }
+
+                                       ConversionType match = ConversionType.None;
+                                       if (i == array_param_index) 
+                                               match = CheckParameterAgainstArgument (ec, pd, i, a, param_type);
+                                       if (match == ConversionType.None && array_param_index >= 0 && i >= array_param_index) {
+                                               expanded = true;
+                                               param_type = param_type.GetElementType ();
+                                       }
+                                       if (match == ConversionType.None)
+                                               match = CheckParameterAgainstArgument (ec, pd, i, a, param_type);
+                                       newarglist.Add (a);
+                                       if (match == ConversionType.None)
+                                               return ConversionType.None;
+                                       if (result == ConversionType.None)
+                                               result = match;
+                                       else if (match == ConversionType.Narrowing)
+                                               result = ConversionType.Narrowing;                                      
+                               }
+                       }
+
+#if false
+                       // 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 ConversionType.None;
+
+                                       a = new Argument (del_temp, Argument.AType.Expression);
+                                       if (!a.Resolve(ec, Location.Null))
+                                               return ConversionType.None;
+                               }
+
+                               if ((p != null) && ((p.ModFlags & Parameter.Modifier.REF) != 0)) {
+                                       a.ArgType = Argument.AType.Ref;
+                                       a.Resolve(ec, Location.Null);
+                               } else if ((pd.ParameterModifier (i) & 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;
+                               }
                        }
-
-                       return true;
+#endif
+                       return result;
                }
                
-               
+               static bool compare_name_filter (MemberInfo m, object filterCriteria)
+               {
+                       return (m.Name == ((string) filterCriteria));
+               }
+
+               // 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);    
+               }
 
+               static string ToString(MethodBase mbase)
+               {
+                       if (mbase == null)
+                               return "NULL";
+
+                       if (mbase is MethodBuilder)
+                       {
+                               MethodBuilder mb = (MethodBuilder) mbase;
+                               String res = mb.ReturnType + " (";
+                               ParameterInfo [] parms = mb.GetParameters();
+                               for (int i = 0; i < parms.Length; i++) {
+                                       if (i != 0)
+                                               res += " ";
+                                       res += parms[i].ParameterType;
+                               }
+                               res += ")";
+                               return res;
+                       }
+
+                       return mbase.ToString();
+               }
+               
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -3530,122 +3691,218 @@ 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 ();
-                       
+                       Hashtable expanded_candidates = new Hashtable();
+                       int narrow_count = 0;
+                       bool narrowing_candidate = false;
 
                        foreach (MethodBase candidate in me.Methods){
-                               int x;
-
-                               // Check if candidate is applicable (section 14.4.2.1)
-                               if (!IsApplicable (ec, Arguments, candidate))
+                               bool candidate_expanded;
+                               ConversionType m = IsApplicable (ec, Arguments, candidate, out candidate_expanded);
+                               if (candidate_expanded)
+                                       expanded_candidates [candidate] = candidate;
+                               if (m == ConversionType.None)
                                        continue;
-
-                               candidates.Add (candidate);
-                               x = BetterFunction (ec, Arguments, candidate, method, false, loc);
-                               
-                               if (x == 0)
-                                       continue;
-
-                               method = candidate;
+                               else if (m == ConversionType.Narrowing) {
+                                       if (method == null) {
+                                               method = candidate;
+                                               narrowing_candidate = true;
+                                       } 
+                                       narrow_count++;
+                               } else if (m == ConversionType.Widening) {
+                                       if (method == null || narrowing_candidate) {
+                                               method = candidate;
+                                               narrowing_candidate = false;
+                                       } else {
+                                               Applicability res = BetterFunction (ec, Arguments, candidate, method, true, loc);
+                                               if (res == Applicability.Same)
+                                                       continue; // should check it overrides?
+                                               if (res == Applicability.Better)
+                                                       method = candidate;
+                                       }
+                                       candidates.Add (candidate);
+                               }
                        }
 
+                       if (candidates.Count == 0) {
+                               if (narrow_count > 1)
+                                       method = null;
+                               else if (narrow_count == 1)
+                                       candidates = null;
+                       } else if (candidates.Count == 1) {
+                               method = (MethodBase)candidates [0];
+                               candidates = null;
+                       } else
+                               narrow_count = 0;
+
                        if (Arguments == null)
                                argument_count = 0;
                        else
                                argument_count = Arguments.Count;
-                       
-                       //
-                       // Now we see if we can find params functions, applicable in their expanded form
-                       // since if they were applicable in their normal form, they would have been selected
-                       // above anyways
-                       //
-                       bool chose_params_expanded = false;
+
                        
                        if (method == null) {
-                               candidates = new ArrayList ();
-                               foreach (MethodBase candidate in me.Methods){
-                                       if (!IsParamsMethodApplicable (ec, Arguments, candidate))
-                                               continue;
+                               //
+                               // 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) {
 
-                                       candidates.Add (candidate);
+                                       MethodBase c = (MethodBase) me.Methods [i];
+                                       ParameterData pd = GetParameterData (c);
 
-                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
-                                       if (x == 0)
+                                       if (pd.Count != argument_count)
                                                continue;
 
-                                       method = candidate; 
-                                       chose_params_expanded = true;
-                               }
-                       }
+                                       bool dummy;
+                                       if (narrow_count != 0) {
+                                               if (IsApplicable (ec, Arguments, c, out dummy) == ConversionType.None)
+                                                       continue;
+                                               Report.Error (1502, loc,
+                                                       "Overloaded match for method '" +
+                                                       FullMethodDesc (c) +
+                                                       "' requires narrowing conversionss");
+                                       }
 
-                       if (method == null)
+                                       VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
+                                                              null, loc);
+                               }
+                               
                                return null;
+                       }
 
                        //
                        // Now check that there are no ambiguities i.e the selected method
                        // should be better than all the others
                        //
 
-                       foreach (MethodBase candidate in candidates){
-                               if (candidate == method)
-                                       continue;
-
-                               //
-                               // If a normal method is applicable in the sense that it has the same
-                               // number of arguments, then the expanded params method is never applicable
-                               // so we debar the params method.
-                               //
-                               if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                   IsApplicable (ec, Arguments, method))
-                                       continue;
-                                       
-                               int x = BetterFunction (ec, Arguments, method, candidate,
-                                                       chose_params_expanded, loc);
+                       if (candidates != null) {
+                               foreach (MethodBase candidate in candidates){
+                                       if (candidate == method)
+                                               continue;
 
-                               if (x != 1) {
-                                       Report.Error (
-                                               121, loc,
-                                               "Ambiguous call when selecting function due to implicit casts");
-                                       return null;
-                               }
+                                       if (BetterFunction (ec, Arguments, candidate, method,
+                                                               false, loc) == Applicability.Better) {
+                                               Report.Error (
+                                                       121, loc,
+                                                       "Ambiguous call of '" + me.Name + "' when selecting function due to implicit casts");
+                                               return null;
+                                       }
+                               }
                        }
 
                        //
                        // And now check if the arguments are all compatible, perform conversions
                        // if necessary etc. and return if everything is all right
                        //
+                       if (method == null)
+                               return null;
 
+                       bool chose_params_expanded = expanded_candidates.Contains (method);
+
+                       Arguments = ConstructArgumentList(ec, Arguments, method);
                        if (VerifyArgumentsCompat (ec, Arguments, argument_count, method,
                                                   chose_params_expanded, null, loc))
+                       {
                                return method;
+                       }
                        else
                                return null;
                }
 
+               public static ArrayList ConstructArgumentList (EmitContext ec, ArrayList Arguments,     MethodBase method)
+               {
+                       ArrayList newarglist = new ArrayList();
+                       int arg_count = Arguments == null ? 0 : Arguments.Count;
+
+                       ParameterData pd = GetParameterData (method);
+                       
+
+                       for (int i = 0; i < arg_count; i++) {
+                               Argument a = (Argument) Arguments [i];
+                               Type param_type = pd.ParameterType (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);
+                                               a = new Argument (del_temp, Argument.AType.Expression);
+                                               a.Resolve(ec, Location.Null);
+                                       }
+                               }
+                               if ((pd.ParameterModifier (i) & Parameter.Modifier.REF) != 0) {
+                                       a.ArgType = Argument.AType.Ref;
+                                       a.Resolve(ec, Location.Null);
+                               }       
+
+                               newarglist.Add (a);
+                       }
+
+                       if (HasArrayParameter (pd) && arg_count == pd.Count - 1)
+                               return newarglist;
+
+                       for (int i = arg_count; i < pd.Count; i++) {
+                               Expression e = pd.DefaultValue (i);
+                               Argument a = new Argument (e, Argument.AType.Expression);
+                               if ((pd.ParameterModifier (i) & Parameter.Modifier.REF) != 0)
+                                       a.ArgType = Argument.AType.Ref;
+                               e.Resolve (ec);
+                               a.Resolve (ec, Location.Null);
+                               newarglist.Add (a);
+                       }
+
+                       return newarglist;
+               }
+
                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;
                                        
@@ -3654,15 +3911,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) + "'");
@@ -3677,17 +3940,19 @@ namespace Mono.CSharp {
                                        if (a_expr != conv)
                                                a.Expr = conv;
                                }
-                               
-                               if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
+
+                               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 | Parameter.Modifier.OPTIONAL);
+
+                               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) + "'");
@@ -3699,24 +3964,55 @@ namespace Mono.CSharp {
 
                        return true;
                }
-               
+       
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       this.is_left_hand = true;
+                       Expression expr_to_return = DoResolve (ec);
+
+                       if (expr_to_return is IndexerAccess) {
+                               IndexerAccess ia = expr_to_return as IndexerAccess;
+                               expr_to_return = ia.DoResolveLValue (ec, right_side);
+                       }
+
+                       return expr_to_return;
+               }
+
                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 (
@@ -3724,43 +4020,155 @@ 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 {
+                                       //
+                                       // check whether this is a indexer
+                                       //
+                                       ArrayList idxs = new ArrayList();
+                                       foreach (Argument a in Arguments) {
+                                               idxs.Add (a.Expr);
+                                       }
+                                       ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
+                                       IndexerAccess ia = new IndexerAccess (ea, expr.Location);
+                                       if (!is_left_hand)
+                        expr_to_return = ia.DoResolve(ec);
+                                       else
+                                               expr_to_return = ia.DoResolve(ec);
+                                       //
+                                       // Since all the above are failed we need to do
+                                       // late binding
+                                       //
+                                       if (expr_to_return == null) {
 
-                       if (type.IsPointer){
-                               if (!ec.InUnsafe){
-                                       UnsafeError (loc);
-                                       return null;
+                                               // 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();
+
+                                               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>
@@ -3769,13 +4177,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;
@@ -3794,32 +4202,22 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Emits a list of resolved Arguments that are in the arguments
                ///   ArrayList.
-               /// 
-               ///   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
                /// </summary>
                public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
                {
-                       ParameterData pd;
-                       if (mb != null)
-                               pd = GetParameterData (mb);
-                       else
-                               pd = null;
+                       ParameterData pd = GetParameterData (mb);
 
                        //
                        // If we are calling a params method with no arguments, special case it
                        //
                        if (arguments == null){
-                               if (pd != null && pd.Count > 0 &&
+                               if (pd.Count > 0 &&
                                    pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){
                                        ILGenerator ig = ec.ig;
 
                                        IntConstant.EmitInt (ig, 0);
                                        ig.Emit (OpCodes.Newarr, pd.ParameterType (0).GetElementType ());
                                }
-
                                return;
                        }
 
@@ -3828,26 +4226,41 @@ namespace Mono.CSharp {
                        for (int i = 0; i < top; i++){
                                Argument a = (Argument) arguments [i];
 
-                               if (pd != null){
-                                       if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
-                                               //
-                                               // Special case if we are passing the same data as the
-                                               // params argument, do not put it in an array.
-                                               //
-                                               if (pd.ParameterType (i) == a.Type)
-                                                       a.Emit (ec);
-                                               else
-                                                       EmitParams (ec, i, arguments);
-                                               return;
-                                       }
+                               if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
+                                       //
+                                       // Special case if we are passing the same data as the
+                                       // params argument, do not put it in an array.
+                                       //
+                                       if (pd.ParameterType (i) == a.Type)
+                                               a.Emit (ec);
+                                       else
+                                               EmitParams (ec, i, arguments);
+                                       return;
+                               }
+
+                               if ((a.ArgType == Argument.AType.Ref || a.ArgType == Argument.AType.Out) &&
+                                       !(a.Expr is IMemoryLocation)) {
+                                       LocalTemporary tmp = new LocalTemporary (ec, pd.ParameterType (i));
+                                       
+                                       a.Expr.Emit (ec);
+                                       tmp.Store (ec);
+                                       a = new Argument (tmp, a.ArgType);
                                }
                                            
                                a.Emit (ec);
                        }
+
+                       if (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.
@@ -3863,38 +4276,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;
 
                        Type decl_type = method.DeclaringType;
-                       
-                       if (RootContext.DisableTrace && decl_type == TypeManager.trace_type)
+
+                       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 (RootContext.DisableDebug && decl_type == TypeManager.debug_type)
+                       if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
                                return;
                        
-                       if (!is_static){
+                       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 (decl_type.IsValueType){
+                                               if (decl_type.IsValueType)
+                                               {
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -3902,11 +4353,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);
@@ -3914,23 +4367,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
@@ -3938,11 +4411,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)
@@ -3953,7 +4438,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);
                        }
                }
@@ -3975,9 +4461,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;
 
                //
@@ -3985,8 +4470,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;
@@ -4000,6 +4487,7 @@ namespace Mono.CSharp {
 
                        set {
                                value_target = value;
+                               value_target_set = true;
                        }
                }
 
@@ -4025,14 +4513,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;
@@ -4043,14 +4540,14 @@ namespace Mono.CSharp {
                                return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
 
                        if (type.IsInterface || type.IsAbstract){
-                               Report.Error (
-                                       144, loc, "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;
 
                        //
@@ -4063,14 +4560,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;
                                }
                        }
@@ -4087,12 +4584,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;
                }
@@ -4123,13 +4622,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;
@@ -4168,7 +4670,7 @@ namespace Mono.CSharp {
        }
 
        /// <summary>
-       ///   Represents an array creation expression.
+       ///   14.5.10.2: Represents an array creation expression.
        /// </summary>
        ///
        /// <remarks>
@@ -4178,29 +4680,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
@@ -4208,105 +4713,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)
+               public Expression FormArrayType (Expression 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)
-               {
-                       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 (
@@ -4316,12 +4820,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);
                                }
                        }
 
@@ -4331,160 +4835,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);
                                }
@@ -4496,37 +5070,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;
@@ -4624,8 +5200,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;
                        }
@@ -4644,17 +5232,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);
                }
                
                //
@@ -4666,9 +5252,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);
@@ -4697,8 +5283,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) {
                                        //
@@ -4711,17 +5297,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;
 
@@ -4734,7 +5320,7 @@ namespace Mono.CSharp {
                                                                             
                                                        ig.Emit (OpCodes.Ldelema, etype);
                                                }
-                                                   
+
                                                e.Emit (ec);
                                                
                                                if (dims == 1)
@@ -4747,9 +5333,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;
                                }
@@ -4761,8 +5347,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)
@@ -4770,16 +5365,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.
                                // 
@@ -4809,36 +5404,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;
                        }
 
@@ -4847,13 +5484,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)
@@ -4865,7 +5514,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);
                }
@@ -4875,11 +5524,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;
@@ -4887,8 +5535,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;
@@ -4913,11 +5560,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;
@@ -4925,11 +5571,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;
@@ -4949,11 +5605,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)
                {
@@ -4970,7 +5625,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");
@@ -4997,57 +5652,20 @@ namespace Mono.CSharp {
                                                              Expression left, Location loc,
                                                              Expression left_original)
                {
-                       //
-                       // Method Groups
-                       //
-                       if (member_lookup is MethodGroupExpr){
-                               MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
-
-                               //
-                               // Type.MethodGroup
-                               //
-                               if (left is TypeExpr){
-                                       if (!mg.RemoveInstanceMethods ()){
-                                               SimpleName.Error120 (loc, mg.Methods [0].Name); 
-                                               return null;
-                                       }
+                       bool left_is_type, left_is_explicit;
 
-                                       return member_lookup;
-                               }
+                       // 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;
 
-                               //
-                               // 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){
@@ -5077,6 +5695,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); 
@@ -5086,15 +5710,15 @@ namespace Mono.CSharp {
                                                Constant c;
                                                if (en != null)
                                                        c = Constantify (o, en.UnderlyingType);
-                                               else 
+                                               else
                                                        c = Constantify (o, enum_member.Type);
-                                               
+
                                                return new EnumConstant (c, decl_type);
                                        }
                                        
                                        Expression exp = Constantify (o, t);
 
-                                       if (!(left is TypeExpr)) {
+                                       if (left_is_explicit && !left_is_type) {
                                                error176 (loc, fe.FieldInfo.Name);
                                                return null;
                                        }
@@ -5106,110 +5730,65 @@ namespace Mono.CSharp {
                                        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;
-
-                                               error176 (loc, fe.FieldInfo.Name);
-                                               return null;
-                                       }
-                                       fe.InstanceExpression = left;
-
-                                       return fe;
-                               }
-                       }
-
-                       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 (member_lookup is EventExpr) {
-
-                               EventExpr ee = (EventExpr) member_lookup;
-                               
-                               //
-                               // If the event is local to this class, we transform ourselves into
-                               // a FieldExpr
-                               //
+                       
+                       if (member_lookup is IMemberExpr) {
+                               IMemberExpr me = (IMemberExpr) member_lookup;
 
-                               Expression ml = MemberLookup (
-                                       ec, ec.ContainerType,
-                                       ee.EventInfo.Name, MemberTypes.Event, AllBindingFlags, loc);
+                               if (left_is_type){
+                                       MethodGroupExpr mg = me as MethodGroupExpr;
+                                       if ((mg != null) && left_is_explicit && left.Type.IsInterface)
+                                               mg.IsExplicitImpl = left_is_explicit;
 
-                               if (ml != null) {
-                                       MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
+                                       if (!me.IsStatic){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
 
-                                       if (mi == null) {
-                                               //
-                                               // If this happens, then we have an event with its own
-                                               // accessors and private field etc so there's no need
-                                               // to transform ourselves : we should instead flag an error
-                                               //
-                                               Assign.error70 (ee.EventInfo, loc);
+                                               SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
                                                return null;
                                        }
 
-                                       ml = ExprClassFromMemberInfo (ec, mi, loc);
-                                       
-                                       if (ml == null) {
-                                               Report.Error (-200, loc, "Internal error!!");
-                                               return null;
-                                       }
-                                       return ResolveMemberAccess (ec, ml, left, loc, left_original);
-                               }
+                               } else {
+                                       if (!me.IsInstance){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
 
-                               if (left is TypeExpr) {
-                                       if (!ee.IsStatic) {
-                                               SimpleName.Error120 (loc, ee.EventInfo.Name);
-                                               return null;
+                                               /*if (left_is_explicit) {
+                                                       error176 (loc, me.Name);
+                                                       return null;
+                                               }*/
                                        }
 
-                                       return ee;
+                                       //
+                                       // 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.
+                                       //
 
-                               } else {
-                                       if (ee.IsStatic) {
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
-                                                       return ee;
-                                                   
-                                               error176 (loc, ee.EventInfo.Name);
-                                               return null;
-                                       }
+                                       if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
+                                               IMemberExpr mexp = (IMemberExpr) left;
 
-                                       ee.InstanceExpression = 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;
                        }
                        
@@ -5219,85 +5798,186 @@ 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);
 
+                       Expression original = expr;
+                       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 is TypeExpr){
+                               //FIXME: add access level check
+                               //if (!ec.DeclSpace.CheckAccessLevel (expr_type)) {
+                               //              Error (30390, "'" + TypeManager.MonoBASIC_Name (expr_type) + "' " +
+                               //                     "is inaccessible because of its protection level");
+                               //      return null;
+                               //}
+
+                               if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
+                                       Enum en = TypeManager.LookupEnum (expr_type);
+
+                                       if (en != null) {
+                                               object value = en.LookupEnumValue (Identifier);
+                                               
+                                               if (value != null){
+                                                       Constant c = Constantify (value, en.UnderlyingType);
+                                                       return new EnumConstant (c, expr_type);
+                                               } else {
+                                                       Report.Error (30456, loc,
+                                                               Identifier + " is not found in member list of enum " + en.Name);
+                                               }
                                        }
                                }
                        }
-
+                       
                        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 (Identifier);
+                                       expr_type = TypeManager.int32_type;
+                                       if (value != null) {
+                                               Constant c = Constantify (value, en.UnderlyingType);
+                                               return new EnumConstant (c, en.UnderlyingType);
+                                       } else {
+                                               Report.Error (30456, loc,
+                                                       Identifier + " is not found in member list of enum " + en.Name);
+                                       }
+                               }
+                       }
+
+                       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>
@@ -5305,9 +5985,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)
@@ -5321,6 +6002,9 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
+                       if (Expr is Constant)
+                               return Expr;
+                       
                        eclass = Expr.eclass;
                        type = Expr.Type;
                        return this;
@@ -5347,9 +6031,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)
@@ -5363,6 +6048,9 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
+                       if (Expr is Constant)
+                               return Expr;
+                       
                        eclass = Expr.eclass;
                        type = Expr.Type;
                        return this;
@@ -5391,7 +6079,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)
                {
@@ -5431,19 +6118,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)
@@ -5459,12 +6147,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)
@@ -5473,12 +6161,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)
@@ -5497,11 +6185,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)
@@ -5512,24 +6201,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;
 
@@ -5537,18 +6275,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);
@@ -5572,11 +6310,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);
@@ -5592,9 +6333,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);
                }
 
@@ -5661,15 +6402,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);
@@ -5679,8 +6428,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++;
@@ -5728,7 +6484,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);
                        }
                        
@@ -5850,7 +6607,7 @@ namespace Mono.CSharp {
                        }
 
                        Report.Error (21, loc,
-                                     "Type `" + TypeManager.CSharpName (lookup_type) +
+                                     "Type '" + TypeManager.MonoBASIC_Name (lookup_type) +
                                      "' does not have any indexers defined");
                        return null;
                }
@@ -5863,52 +6620,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;
                        }
                        
@@ -5918,17 +6693,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 (
@@ -5936,10 +6711,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;
@@ -5949,7 +6723,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);
                }
 
                //
@@ -5959,7 +6733,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);
                }
        }
 
@@ -5967,8 +6741,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)
                {
@@ -5984,24 +6757,33 @@ 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, current_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){
+
+                       if (e is PropertyExpr) {
                                PropertyExpr pe = (PropertyExpr) e;
 
                                pe.IsBase = true;
@@ -6019,38 +6801,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;
                }
        }
        
@@ -6062,19 +6834,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)
@@ -6102,12 +6876,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)
@@ -6138,10 +6913,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)
                {
@@ -6150,35 +6924,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;
+               }
        }
 
        //
@@ -6188,7 +6988,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 ();
 
@@ -6204,6 +7004,7 @@ namespace Mono.CSharp {
                        }
 
                        eclass = ExprClass.Value;
+                       loc = l;
                }
 
                public override void Emit (EmitContext ec)
@@ -6230,11 +7031,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)
@@ -6257,15 +7059,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;
@@ -6285,12 +7086,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;
@@ -6324,4 +7125,54 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Localloc);
                }
        }
+       public class Preserve : ExpressionStatement {
+               ArrayList args = null;
+               MethodInfo mi = null;
+               Expression target = null;
+               ExpressionStatement source = null;
+
+
+               public Preserve (Expression RedimTarget, ExpressionStatement acExpr, Location l)
+               {
+                       Type type = typeof(Microsoft.VisualBasic.CompilerServices.Utils);
+                       mi = type.GetMethod("CopyArray");
+
+                       target = RedimTarget;
+                       source = acExpr;
+
+                       eclass = ExprClass.Value;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       type = mi.ReturnType;
+
+                       source.Resolve (ec);
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       args = new ArrayList (2);
+
+                       args.Add (new Argument (target, Argument.AType.Expression));
+                       args.Add (new Argument (source, Argument.AType.Expression));
+
+                       Invocation.EmitArguments (ec, mi, args);
+
+                       ec.ig.Emit (OpCodes.Call, mi);
+                       return;
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+               }
+
+       }
 }