2004-08-03 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mbas / expression.cs
index d7b795eb435056eccaef26aab2b89d83a8e4c6a3..ceed21db3885a84b2039a265a8b3ad9f82db3eef 100644 (file)
-//\r
-// expression.cs: Expression representation for the IL tree.\r
-//\r
-// Author:\r
-//   Miguel de Icaza (miguel@ximian.com)\r
-//\r
-// (C) 2001 Ximian, Inc.\r
-//\r
-//\r
-#define USE_OLD\r
-\r
-namespace Mono.CSharp {\r
-       using System;\r
-       using System.Collections;\r
-       using System.Diagnostics;\r
-       using System.Reflection;\r
-       using System.Reflection.Emit;\r
-       using System.Text;\r
-\r
-       /// <summary>\r
-       ///   This is just a helper class, it is generated by Unary, UnaryMutator\r
-       ///   when an overloaded method has been found.  It just emits the code for a\r
-       ///   static call.\r
-       /// </summary>\r
-       public class StaticCallExpr : ExpressionStatement {\r
-               ArrayList args;\r
-               MethodInfo mi;\r
-\r
-               StaticCallExpr (MethodInfo m, ArrayList a)\r
-               {\r
-                       mi = m;\r
-                       args = a;\r
-\r
-                       type = m.ReturnType;\r
-                       eclass = ExprClass.Value;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // We are born fully resolved\r
-                       //\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       if (args != null) \r
-                               Invocation.EmitArguments (ec, mi, args);\r
-\r
-                       ec.ig.Emit (OpCodes.Call, mi);\r
-                       return;\r
-               }\r
-               \r
-               static public Expression MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,\r
-                                                        Expression e, Location loc)\r
-               {\r
-                       ArrayList args;\r
-                       MethodBase method;\r
-                       \r
-                       args = new ArrayList (1);\r
-                       args.Add (new Argument (e, Argument.AType.Expression));\r
-                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc);\r
-\r
-                       if (method == null)\r
-                               return null;\r
-\r
-                       return new StaticCallExpr ((MethodInfo) method, args);\r
-               }\r
-\r
-               public override void EmitStatement (EmitContext ec)\r
-               {\r
-                       Emit (ec);\r
-                       if (type != TypeManager.void_type)\r
-                               ec.ig.Emit (OpCodes.Pop);\r
-               }\r
-       }\r
-       \r
-       /// <summary>\r
-       ///   Unary expressions.  \r
-       /// </summary>\r
-       ///\r
-       /// <remarks>\r
-       ///   Unary implements unary expressions.   It derives from\r
-       ///   ExpressionStatement becuase the pre/post increment/decrement\r
-       ///   operators can be used in a statement context.\r
-       /// </remarks>\r
-       public class Unary : Expression {\r
-               public enum Operator : byte {\r
-                       UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,\r
-                       Indirection, AddressOf,  TOP\r
-               }\r
-\r
-               Operator   oper;\r
-               Expression expr;\r
-               Location   loc;\r
-               \r
-               public Unary (Operator op, Expression expr, Location loc)\r
-               {\r
-                       this.oper = op;\r
-                       this.expr = expr;\r
-                       this.loc = loc;\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-\r
-                       set {\r
-                               expr = value;\r
-                       }\r
-               }\r
-\r
-               public Operator Oper {\r
-                       get {\r
-                               return oper;\r
-                       }\r
-\r
-                       set {\r
-                               oper = value;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               ///   Returns a stringified representation of the Operator\r
-               /// </summary>\r
-               static public string OperName (Operator oper)\r
-               {\r
-                       switch (oper){\r
-                       case Operator.UnaryPlus:\r
-                               return "+";\r
-                       case Operator.UnaryNegation:\r
-                               return "-";\r
-                       case Operator.LogicalNot:\r
-                               return "!";\r
-                       case Operator.OnesComplement:\r
-                               return "~";\r
-                       case Operator.AddressOf:\r
-                               return "&";\r
-                       case Operator.Indirection:\r
-                               return "*";\r
-                       }\r
-\r
-                       return oper.ToString ();\r
-               }\r
-\r
-               static string [] oper_names;\r
-\r
-               static Unary ()\r
-               {\r
-                       oper_names = new string [(int)Operator.TOP];\r
-\r
-                       oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";\r
-                       oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";\r
-                       oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";\r
-                       oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";\r
-                       oper_names [(int) Operator.Indirection] = "op_Indirection";\r
-                       oper_names [(int) Operator.AddressOf] = "op_AddressOf";\r
-               }\r
-\r
-               void Error23 (Type t)\r
-               {\r
-                       Report.Error (\r
-                               23, loc, "Operator " + OperName (oper) +\r
-                               " cannot be applied to operand of type `" +\r
-                               TypeManager.CSharpName (t) + "'");\r
-               }\r
-\r
-               /// <remarks>\r
-               ///   The result has been already resolved:\r
-               ///\r
-               ///   FIXME: a minus constant -128 sbyte cant be turned into a\r
-               ///   constant byte.\r
-               /// </remarks>\r
-               static Expression TryReduceNegative (Expression expr)\r
-               {\r
-                       Expression e = null;\r
-                       \r
-                       if (expr is IntConstant)\r
-                               e = new IntConstant (-((IntConstant) expr).Value);\r
-                       else if (expr is UIntConstant)\r
-                               e = new LongConstant (-((UIntConstant) expr).Value);\r
-                       else if (expr is LongConstant)\r
-                               e = new LongConstant (-((LongConstant) expr).Value);\r
-                       else if (expr is FloatConstant)\r
-                               e = new FloatConstant (-((FloatConstant) expr).Value);\r
-                       else if (expr is DoubleConstant)\r
-                               e = new DoubleConstant (-((DoubleConstant) expr).Value);\r
-                       else if (expr is DecimalConstant)\r
-                               e = new DecimalConstant (-((DecimalConstant) expr).Value);\r
-                       else if (expr is ShortConstant)\r
-                               e = new IntConstant (-((ShortConstant) expr).Value);\r
-                       else if (expr is UShortConstant)\r
-                               e = new IntConstant (-((UShortConstant) expr).Value);\r
-\r
-                       return e;\r
-               }\r
-               \r
-               Expression Reduce (EmitContext ec, Expression e)\r
-               {\r
-                       Type expr_type = e.Type;\r
-                       \r
-                       switch (oper){\r
-                       case Operator.UnaryPlus:\r
-                               return e;\r
-                               \r
-                       case Operator.UnaryNegation:\r
-                               return TryReduceNegative (e);\r
-                               \r
-                       case Operator.LogicalNot:\r
-                               if (expr_type != TypeManager.bool_type) {\r
-                                       Error23 (expr_type);\r
-                                       return null;\r
-                               }\r
-                               \r
-                               BoolConstant b = (BoolConstant) e;\r
-                               return new BoolConstant (!(b.Value));\r
-                               \r
-                       case Operator.OnesComplement:\r
-                               if (!((expr_type == TypeManager.int32_type) ||\r
-                                     (expr_type == TypeManager.uint32_type) ||\r
-                                     (expr_type == TypeManager.int64_type) ||\r
-                                     (expr_type == TypeManager.uint64_type) ||\r
-                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){\r
-                                       Error23 (expr_type);\r
-                                       return null;\r
-                               }\r
-\r
-                               if (e is EnumConstant){\r
-                                       EnumConstant enum_constant = (EnumConstant) e;\r
-                                       \r
-                                       Expression reduced = Reduce (ec, enum_constant.Child);\r
-\r
-                                       return new EnumConstant ((Constant) reduced, enum_constant.Type);\r
-                               }\r
-\r
-                               if (expr_type == TypeManager.int32_type)\r
-                                       return new IntConstant (~ ((IntConstant) e).Value);\r
-                               if (expr_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant (~ ((UIntConstant) e).Value);\r
-                               if (expr_type == TypeManager.int64_type)\r
-                                       return new LongConstant (~ ((LongConstant) e).Value);\r
-                               if (expr_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant (~ ((ULongConstant) e).Value);\r
-\r
-                               Error23 (expr_type);\r
-                               return null;\r
-                       }\r
-                       throw new Exception ("Can not constant fold");\r
-               }\r
-\r
-               Expression ResolveOperator (EmitContext ec)\r
-               {\r
-                       Type expr_type = expr.Type;\r
-\r
-                       //\r
-                       // Step 1: Perform Operator Overload location\r
-                       //\r
-                       Expression mg;\r
-                       string op_name;\r
-                       \r
-                       op_name = oper_names [(int) oper];\r
-\r
-                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);\r
-                       \r
-                       if (mg != null) {\r
-                               Expression e = StaticCallExpr.MakeSimpleCall (\r
-                                       ec, (MethodGroupExpr) mg, expr, loc);\r
-\r
-                               if (e == null){\r
-                                       Error23 (expr_type);\r
-                                       return null;\r
-                               }\r
-                               \r
-                               return e;\r
-                       }\r
-\r
-                       // Only perform numeric promotions on:\r
-                       // +, - \r
-\r
-                       if (expr_type == null)\r
-                               return null;\r
-                       \r
-                       //\r
-                       // Step 2: Default operations on CLI native types.\r
-                       //\r
-                       if (expr is Constant)\r
-                               return Reduce (ec, expr);\r
-\r
-                       if (oper == Operator.LogicalNot){\r
-                               if (expr_type != TypeManager.bool_type) {\r
-                                       Error23 (expr.Type);\r
-                                       return null;\r
-                               }\r
-                               \r
-                               type = TypeManager.bool_type;\r
-                               return this;\r
-                       }\r
-\r
-                       if (oper == Operator.OnesComplement) {\r
-                               if (!((expr_type == TypeManager.int32_type) ||\r
-                                     (expr_type == TypeManager.uint32_type) ||\r
-                                     (expr_type == TypeManager.int64_type) ||\r
-                                     (expr_type == TypeManager.uint64_type) ||\r
-                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){\r
-                                       Error23 (expr.Type);\r
-                                       return null;\r
-                               }\r
-                               type = expr_type;\r
-                               return this;\r
-                       }\r
-\r
-                       if (oper == Operator.UnaryPlus) {\r
-                               //\r
-                               // A plus in front of something is just a no-op, so return the child.\r
-                               //\r
-                               return expr;\r
-                       }\r
-\r
-                       //\r
-                       // Deals with -literals\r
-                       // int     operator- (int x)\r
-                       // long    operator- (long x)\r
-                       // float   operator- (float f)\r
-                       // double  operator- (double d)\r
-                       // decimal operator- (decimal d)\r
-                       //\r
-                       if (oper == Operator.UnaryNegation){\r
-                               Expression e = null;\r
-\r
-                               //\r
-                               // perform numeric promotions to int,\r
-                               // long, double.\r
-                               //\r
-                               //\r
-                               // The following is inneficient, because we call\r
-                               // ConvertImplicit too many times.\r
-                               //\r
-                               // It is also not clear if we should convert to Float\r
-                               // or Double initially.\r
-                               //\r
-                               if (expr_type == TypeManager.uint32_type){\r
-                                       //\r
-                                       // FIXME: handle exception to this rule that\r
-                                       // permits the int value -2147483648 (-2^31) to\r
-                                       // bt wrote as a decimal interger literal\r
-                                       //\r
-                                       type = TypeManager.int64_type;\r
-                                       expr = ConvertImplicit (ec, expr, type, loc);\r
-                                       return this;\r
-                               }\r
-\r
-                               if (expr_type == TypeManager.uint64_type){\r
-                                       //\r
-                                       // FIXME: Handle exception of `long value'\r
-                                       // -92233720368547758087 (-2^63) to be wrote as\r
-                                       // decimal integer literal.\r
-                                       //\r
-                                       Error23 (expr_type);\r
-                                       return null;\r
-                               }\r
-\r
-                               if (expr_type == TypeManager.float_type){\r
-                                       type = expr_type;\r
-                                       return this;\r
-                               }\r
-                               \r
-                               e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);\r
-                               if (e != null){\r
-                                       expr = e;\r
-                                       type = e.Type;\r
-                                       return this;\r
-                               } \r
-\r
-                               e = ConvertImplicit (ec, expr, TypeManager.int64_type, loc);\r
-                               if (e != null){\r
-                                       expr = e;\r
-                                       type = e.Type;\r
-                                       return this;\r
-                               }\r
-\r
-                               e = ConvertImplicit (ec, expr, TypeManager.double_type, loc);\r
-                               if (e != null){\r
-                                       expr = e;\r
-                                       type = e.Type;\r
-                                       return this;\r
-                               }\r
-\r
-                               Error23 (expr_type);\r
-                               return null;\r
-                       }\r
-\r
-                       if (oper == Operator.AddressOf){\r
-                               if (expr.eclass != ExprClass.Variable){\r
-                                       Error (211, loc, "Cannot take the address of non-variables");\r
-                                       return null;\r
-                               }\r
-\r
-                               if (!ec.InUnsafe) {\r
-                                       UnsafeError (loc); \r
-                                       return null;\r
-                               }\r
-\r
-                               if (!TypeManager.VerifyUnManaged (expr.Type, loc)){\r
-                                       return null;\r
-                               }\r
-                               \r
-                               //\r
-                               // This construct is needed because dynamic types\r
-                               // are not known by Type.GetType, so we have to try then to use\r
-                               // ModuleBuilder.GetType.\r
-                               //\r
-                               string ptr_type_name = expr.Type.FullName + "*";\r
-                               type = Type.GetType (ptr_type_name);\r
-                               if (type == null)\r
-                                       type = RootContext.ModuleBuilder.GetType (ptr_type_name);\r
-                               \r
-                               return this;\r
-                       }\r
-\r
-                       if (oper == Operator.Indirection){\r
-                               if (!ec.InUnsafe){\r
-                                       UnsafeError (loc);\r
-                                       return null;\r
-                               }\r
-\r
-                               if (!expr_type.IsPointer){\r
-                                       Report.Error (\r
-                                               193, loc,\r
-                                               "The * or -> operator can only be applied to pointers");\r
-                                       return null;\r
-                               }\r
-\r
-                               //\r
-                               // We create an Indirection expression, because\r
-                               // it can implement the IMemoryLocation.\r
-                               // \r
-                               return new Indirection (expr);\r
-                       }\r
-                       \r
-                       Error (187, loc, "No such operator '" + OperName (oper) + "' defined for type '" +\r
-                              TypeManager.CSharpName (expr_type) + "'");\r
-                       return null;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       expr = expr.Resolve (ec);\r
-                       \r
-                       if (expr == null)\r
-                               return null;\r
-\r
-                       eclass = ExprClass.Value;\r
-                       return ResolveOperator (ec);\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       Type expr_type = expr.Type;\r
-                       \r
-                       switch (oper) {\r
-                       case Operator.UnaryPlus:\r
-                               throw new Exception ("This should be caught by Resolve");\r
-                               \r
-                       case Operator.UnaryNegation:\r
-                               expr.Emit (ec);\r
-                               ig.Emit (OpCodes.Neg);\r
-                               break;\r
-                               \r
-                       case Operator.LogicalNot:\r
-                               expr.Emit (ec);\r
-                               ig.Emit (OpCodes.Ldc_I4_0);\r
-                               ig.Emit (OpCodes.Ceq);\r
-                               break;\r
-                               \r
-                       case Operator.OnesComplement:\r
-                               expr.Emit (ec);\r
-                               ig.Emit (OpCodes.Not);\r
-                               break;\r
-                               \r
-                       case Operator.AddressOf:\r
-                               ((IMemoryLocation)expr).AddressOf (ec, AddressOp.LoadStore);\r
-                               break;\r
-                               \r
-                       default:\r
-                               throw new Exception ("This should not happen: Operator = "\r
-                                                    + oper.ToString ());\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               ///   This will emit the child expression for `ec' avoiding the logical\r
-               ///   not.  The parent will take care of changing brfalse/brtrue\r
-               /// </summary>\r
-               public void EmitLogicalNot (EmitContext ec)\r
-               {\r
-                       if (oper != Operator.LogicalNot)\r
-                               throw new Exception ("EmitLogicalNot can only be called with !expr");\r
-\r
-                       expr.Emit (ec);\r
-               }\r
-\r
-               public override string ToString ()\r
-               {\r
-                       return "Unary (" + oper + ", " + expr + ")";\r
-               }\r
-               \r
-       }\r
-\r
-       //\r
-       // Unary operators are turned into Indirection expressions\r
-       // after semantic analysis (this is so we can take the address\r
-       // of an indirection).\r
-       //\r
-       public class Indirection : Expression, IMemoryLocation, IAssignMethod {\r
-               Expression expr;\r
-               \r
-               public Indirection (Expression expr)\r
-               {\r
-                       this.expr = expr;\r
-                       this.type = expr.Type.GetElementType ();\r
-                       eclass = ExprClass.Variable;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       expr.Emit (ec);\r
-                       LoadFromPtr (ec.ig, Type, false);\r
-               }\r
-\r
-               public void EmitAssign (EmitContext ec, Expression source)\r
-               {\r
-                       expr.Emit (ec);\r
-                       source.Emit (ec);\r
-                       StoreFromPtr (ec.ig, type);\r
-               }\r
-               \r
-               public void AddressOf (EmitContext ec, AddressOp Mode)\r
-               {\r
-                       expr.Emit (ec);\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // Born fully resolved\r
-                       //\r
-                       return this;\r
-               }\r
-       }\r
-       \r
-       /// <summary>\r
-       ///   Unary Mutator expressions (pre and post ++ and --)\r
-       /// </summary>\r
-       ///\r
-       /// <remarks>\r
-       ///   UnaryMutator implements ++ and -- expressions.   It derives from\r
-       ///   ExpressionStatement becuase the pre/post increment/decrement\r
-       ///   operators can be used in a statement context.\r
-       ///\r
-       /// FIXME: Idea, we could split this up in two classes, one simpler\r
-       /// for the common case, and one with the extra fields for more complex\r
-       /// classes (indexers require temporary access;  overloaded require method)\r
-       ///\r
-       /// Maybe we should have classes PreIncrement, PostIncrement, PreDecrement,\r
-       /// PostDecrement, that way we could save the `Mode' byte as well.  \r
-       /// </remarks>\r
-       public class UnaryMutator : ExpressionStatement {\r
-               public enum Mode : byte {\r
-                       PreIncrement, PreDecrement, PostIncrement, PostDecrement\r
-               }\r
-               \r
-               Mode mode;\r
-               Location loc;\r
-               Expression expr;\r
-               LocalTemporary temp_storage;\r
-\r
-               //\r
-               // This is expensive for the simplest case.\r
-               //\r
-               Expression method;\r
-                       \r
-               public UnaryMutator (Mode m, Expression e, Location l)\r
-               {\r
-                       mode = m;\r
-                       loc = l;\r
-                       expr = e;\r
-               }\r
-\r
-               static string OperName (Mode mode)\r
-               {\r
-                       return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?\r
-                               "++" : "--";\r
-               }\r
-               \r
-               void Error23 (Type t)\r
-               {\r
-                       Report.Error (\r
-                               23, loc, "Operator " + OperName (mode) + \r
-                               " cannot be applied to operand of type `" +\r
-                               TypeManager.CSharpName (t) + "'");\r
-               }\r
-\r
-               /// <summary>\r
-               ///   Returns whether an object of type `t' can be incremented\r
-               ///   or decremented with add/sub (ie, basically whether we can\r
-               ///   use pre-post incr-decr operations on it, but it is not a\r
-               ///   System.Decimal, which we require operator overloading to catch)\r
-               /// </summary>\r
-               static bool IsIncrementableNumber (Type t)\r
-               {\r
-                       return (t == TypeManager.sbyte_type) ||\r
-                               (t == TypeManager.byte_type) ||\r
-                               (t == TypeManager.short_type) ||\r
-                               (t == TypeManager.ushort_type) ||\r
-                               (t == TypeManager.int32_type) ||\r
-                               (t == TypeManager.uint32_type) ||\r
-                               (t == TypeManager.int64_type) ||\r
-                               (t == TypeManager.uint64_type) ||\r
-                               (t == TypeManager.char_type) ||\r
-                               (t.IsSubclassOf (TypeManager.enum_type)) ||\r
-                               (t == TypeManager.float_type) ||\r
-                               (t == TypeManager.double_type) ||\r
-                               (t.IsPointer && t != TypeManager.void_ptr_type);\r
-               }\r
-\r
-               Expression ResolveOperator (EmitContext ec)\r
-               {\r
-                       Type expr_type = expr.Type;\r
-\r
-                       //\r
-                       // Step 1: Perform Operator Overload location\r
-                       //\r
-                       Expression mg;\r
-                       string op_name;\r
-                       \r
-                       if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)\r
-                               op_name = "op_Increment";\r
-                       else \r
-                               op_name = "op_Decrement";\r
-\r
-                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);\r
-\r
-                       if (mg == null && expr_type.BaseType != null)\r
-                               mg = MemberLookup (ec, expr_type.BaseType, op_name,\r
-                                                  MemberTypes.Method, AllBindingFlags, loc);\r
-                       \r
-                       if (mg != null) {\r
-                               method = StaticCallExpr.MakeSimpleCall (\r
-                                       ec, (MethodGroupExpr) mg, expr, loc);\r
-\r
-                               type = method.Type;\r
-                               return this;\r
-                       }\r
-\r
-                       //\r
-                       // The operand of the prefix/postfix increment decrement operators\r
-                       // should be an expression that is classified as a variable,\r
-                       // a property access or an indexer access\r
-                       //\r
-                       type = expr_type;\r
-                       if (expr.eclass == ExprClass.Variable){\r
-                               if (IsIncrementableNumber (expr_type) ||\r
-                                   expr_type == TypeManager.decimal_type){\r
-                                       return this;\r
-                               }\r
-                       } else if (expr.eclass == ExprClass.IndexerAccess){\r
-                               IndexerAccess ia = (IndexerAccess) expr;\r
-                               \r
-                               temp_storage = new LocalTemporary (ec, expr.Type);\r
-                               \r
-                               expr = ia.ResolveLValue (ec, temp_storage);\r
-                               if (expr == null)\r
-                                       return null;\r
-\r
-                               return this;\r
-                       } else if (expr.eclass == ExprClass.PropertyAccess){\r
-                               PropertyExpr pe = (PropertyExpr) expr;\r
-\r
-                               if (pe.VerifyAssignable ())\r
-                                       return this;\r
-\r
-                               return null;\r
-                       } else {\r
-                               report118 (loc, expr, "variable, indexer or property access");\r
-                               return null;\r
-                       }\r
-\r
-                       Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +\r
-                              TypeManager.CSharpName (expr_type) + "'");\r
-                       return null;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       expr = expr.Resolve (ec);\r
-                       \r
-                       if (expr == null)\r
-                               return null;\r
-\r
-                       eclass = ExprClass.Value;\r
-                       return ResolveOperator (ec);\r
-               }\r
-\r
-               static int PtrTypeSize (Type t)\r
-               {\r
-                       return GetTypeSize (t.GetElementType ());\r
-               }\r
-               \r
-               //\r
-               // FIXME: We need some way of avoiding the use of temp_storage\r
-               // for some types of storage (parameters, local variables,\r
-               // static fields) and single-dimension array access.\r
-               //\r
-               void EmitCode (EmitContext ec, bool is_expr)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       IAssignMethod ia = (IAssignMethod) expr;\r
-                       Type expr_type = expr.Type;\r
-                       \r
-                       if (temp_storage == null)\r
-                               temp_storage = new LocalTemporary (ec, expr_type);\r
-\r
-                       switch (mode){\r
-                       case Mode.PreIncrement:\r
-                       case Mode.PreDecrement:\r
-                               if (method == null){\r
-                                       expr.Emit (ec);\r
-\r
-                                       if (expr_type == TypeManager.uint64_type ||\r
-                                           expr_type == TypeManager.int64_type)\r
-                                               ig.Emit (OpCodes.Ldc_I8, 1L);\r
-                                       else if (expr_type == TypeManager.double_type)\r
-                                               ig.Emit (OpCodes.Ldc_R8, 1.0);\r
-                                       else if (expr_type == TypeManager.float_type)\r
-                                               ig.Emit (OpCodes.Ldc_R4, 1.0F);\r
-                                       else if (expr_type.IsPointer){\r
-                                               int n = PtrTypeSize (expr_type);\r
-\r
-                                               if (n == 0)\r
-                                                       ig.Emit (OpCodes.Sizeof, expr_type);\r
-                                               else\r
-                                                       IntConstant.EmitInt (ig, n);\r
-                                       } else \r
-                                               ig.Emit (OpCodes.Ldc_I4_1);\r
-\r
-                                       //\r
-                                       // Select the opcode based on the check state (then the type)\r
-                                       // and the actual operation\r
-                                       //\r
-                                       if (ec.CheckState){\r
-                                               if (expr_type == TypeManager.int32_type ||\r
-                                                   expr_type == TypeManager.int64_type){\r
-                                                       if (mode == Mode.PreDecrement)\r
-                                                               ig.Emit (OpCodes.Sub_Ovf);\r
-                                                       else\r
-                                                               ig.Emit (OpCodes.Add_Ovf);\r
-                                               } else if (expr_type == TypeManager.uint32_type ||\r
-                                                          expr_type == TypeManager.uint64_type){\r
-                                                       if (mode == Mode.PreDecrement)\r
-                                                               ig.Emit (OpCodes.Sub_Ovf_Un);\r
-                                                       else\r
-                                                               ig.Emit (OpCodes.Add_Ovf_Un);\r
-                                               } else {\r
-                                                       if (mode == Mode.PreDecrement)\r
-                                                               ig.Emit (OpCodes.Sub_Ovf);\r
-                                                       else\r
-                                                               ig.Emit (OpCodes.Add_Ovf);\r
-                                               }\r
-                                       } else {\r
-                                               if (mode == Mode.PreDecrement)\r
-                                                       ig.Emit (OpCodes.Sub);\r
-                                               else\r
-                                                       ig.Emit (OpCodes.Add);\r
-                                       }\r
-                               } else\r
-                                       method.Emit (ec);\r
-                               \r
-                               temp_storage.Store (ec);\r
-                               ia.EmitAssign (ec, temp_storage);\r
-                               if (is_expr)\r
-                                       temp_storage.Emit (ec);\r
-                               break;\r
-                               \r
-                       case Mode.PostIncrement:\r
-                       case Mode.PostDecrement:\r
-                               if (is_expr)\r
-                                       expr.Emit (ec);\r
-                               \r
-                               if (method == null){\r
-                                       if (!is_expr)\r
-                                               expr.Emit (ec);\r
-                                       else\r
-                                               ig.Emit (OpCodes.Dup);\r
-\r
-                                       if (expr_type == TypeManager.uint64_type ||\r
-                                           expr_type == TypeManager.int64_type)\r
-                                               ig.Emit (OpCodes.Ldc_I8, 1L);\r
-                                       else if (expr_type == TypeManager.double_type)\r
-                                               ig.Emit (OpCodes.Ldc_R8, 1.0);\r
-                                       else if (expr_type == TypeManager.float_type)\r
-                                               ig.Emit (OpCodes.Ldc_R4, 1.0F);\r
-                                       else if (expr_type.IsPointer){\r
-                                               int n = PtrTypeSize (expr_type);\r
-\r
-                                               if (n == 0)\r
-                                                       ig.Emit (OpCodes.Sizeof, expr_type);\r
-                                               else\r
-                                                       IntConstant.EmitInt (ig, n);\r
-                                       } else\r
-                                               ig.Emit (OpCodes.Ldc_I4_1);\r
-\r
-                                       if (ec.CheckState){\r
-                                               if (expr_type == TypeManager.int32_type ||\r
-                                                   expr_type == TypeManager.int64_type){\r
-                                                       if (mode == Mode.PostDecrement)\r
-                                                               ig.Emit (OpCodes.Sub_Ovf);\r
-                                                       else\r
-                                                               ig.Emit (OpCodes.Add_Ovf);\r
-                                               } else if (expr_type == TypeManager.uint32_type ||\r
-                                                          expr_type == TypeManager.uint64_type){\r
-                                                       if (mode == Mode.PostDecrement)\r
-                                                               ig.Emit (OpCodes.Sub_Ovf_Un);\r
-                                                       else\r
-                                                               ig.Emit (OpCodes.Add_Ovf_Un);\r
-                                               } else {\r
-                                                       if (mode == Mode.PostDecrement)\r
-                                                               ig.Emit (OpCodes.Sub_Ovf);\r
-                                                       else\r
-                                                               ig.Emit (OpCodes.Add_Ovf);\r
-                                               }\r
-                                       } else {\r
-                                               if (mode == Mode.PostDecrement)\r
-                                                       ig.Emit (OpCodes.Sub);\r
-                                               else\r
-                                                       ig.Emit (OpCodes.Add);\r
-                                       }\r
-                               } else {\r
-                                       method.Emit (ec);\r
-                               }\r
-                               \r
-                               temp_storage.Store (ec);\r
-                               ia.EmitAssign (ec, temp_storage);\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       EmitCode (ec, true);\r
-                       \r
-               }\r
-               \r
-               public override void EmitStatement (EmitContext ec)\r
-               {\r
-                       EmitCode (ec, false);\r
-               }\r
-\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Base class for the `Is' and `As' classes. \r
-       /// </summary>\r
-       ///\r
-       /// <remarks>\r
-       ///   FIXME: Split this in two, and we get to save the `Operator' Oper\r
-       ///   size. \r
-       /// </remarks>\r
-       public abstract class Probe : Expression {\r
-               public readonly string ProbeType;\r
-               protected Expression expr;\r
-               protected Type probe_type;\r
-               protected Location loc;\r
-               \r
-               public Probe (Expression expr, string probe_type, Location l)\r
-               {\r
-                       ProbeType = probe_type;\r
-                       loc = l;\r
-                       this.expr = expr;\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       probe_type = RootContext.LookupType (ec.DeclSpace, ProbeType, false, loc);\r
-\r
-                       if (probe_type == null)\r
-                               return null;\r
-\r
-                       expr = expr.Resolve (ec);\r
-                       \r
-                       return this;\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implementation of the `is' operator.\r
-       /// </summary>\r
-       public class Is : Probe {\r
-               public Is (Expression expr, string probe_type, Location l)\r
-                       : base (expr, probe_type, l)\r
-               {\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       \r
-                       expr.Emit (ec);\r
-                       \r
-                       ig.Emit (OpCodes.Isinst, probe_type);\r
-                       ig.Emit (OpCodes.Ldnull);\r
-                       ig.Emit (OpCodes.Cgt_Un);\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       Expression e = base.DoResolve (ec);\r
-\r
-                       if (e == null)\r
-                               return null;\r
-\r
-                       if (RootContext.WarningLevel >= 1){\r
-                               if (expr.Type == probe_type || expr.Type.IsSubclassOf (probe_type)){\r
-                                       Report.Warning (\r
-                                               183, loc,\r
-                                               "The expression is always of type `" +\r
-                                               TypeManager.CSharpName (probe_type) + "'");\r
-                               }\r
-\r
-                               if (expr.Type != probe_type && !probe_type.IsSubclassOf (expr.Type)){\r
-                                       if (!(probe_type.IsInterface || expr.Type.IsInterface))\r
-                                               Report.Warning (\r
-                                                       184, loc,\r
-                                                       "The expression is never of type `" +\r
-                                                       TypeManager.CSharpName (probe_type) + "'");\r
-                               }\r
-                       }\r
-                       \r
-                       type = TypeManager.bool_type;\r
-                       eclass = ExprClass.Value;\r
-\r
-                       return this;\r
-               }                               \r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implementation of the `as' operator.\r
-       /// </summary>\r
-       public class As : Probe {\r
-               public As (Expression expr, string probe_type, Location l)\r
-                       : base (expr, probe_type, l)\r
-               {\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-\r
-                       expr.Emit (ec);\r
-                       ig.Emit (OpCodes.Isinst, probe_type);\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       Expression e = base.DoResolve (ec);\r
-\r
-                       if (e == null)\r
-                               return null;\r
-\r
-                       type = probe_type;\r
-                       eclass = ExprClass.Value;\r
-\r
-                       return this;\r
-               }                               \r
-       }\r
-       \r
-       /// <summary>\r
-       ///   This represents a typecast in the source language.\r
-       ///\r
-       ///   FIXME: Cast expressions have an unusual set of parsing\r
-       ///   rules, we need to figure those out.\r
-       /// </summary>\r
-       public class Cast : Expression {\r
-               Expression target_type;\r
-               Expression expr;\r
-               Location   loc;\r
-                       \r
-               public Cast (Expression cast_type, Expression expr, Location loc)\r
-               {\r
-                       this.target_type = cast_type;\r
-                       this.expr = expr;\r
-                       this.loc = loc;\r
-               }\r
-\r
-               public Expression TargetType {\r
-                       get {\r
-                               return target_type;\r
-                       }\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-                       set {\r
-                               expr = value;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               ///   Attempts to do a compile-time folding of a constant cast.\r
-               /// </summary>\r
-               Expression TryReduce (EmitContext ec, Type target_type)\r
-               {\r
-                       if (expr is ByteConstant){\r
-                               byte v = ((ByteConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is SByteConstant){\r
-                               sbyte v = ((SByteConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is ShortConstant){\r
-                               short v = ((ShortConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is UShortConstant){\r
-                               ushort v = ((UShortConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is IntConstant){\r
-                               int v = ((IntConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is UIntConstant){\r
-                               uint v = ((UIntConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is LongConstant){\r
-                               long v = ((LongConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is ULongConstant){\r
-                               ulong v = ((ULongConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is FloatConstant){\r
-                               float v = ((FloatConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.double_type)\r
-                                       return new DoubleConstant ((double) v);\r
-                       }\r
-                       if (expr is DoubleConstant){\r
-                               double v = ((DoubleConstant) expr).Value;\r
-       \r
-                               if (target_type == TypeManager.byte_type)\r
-                                       return new ByteConstant ((byte) v);\r
-                               if (target_type == TypeManager.sbyte_type)\r
-                                       return new SByteConstant ((sbyte) v);\r
-                               if (target_type == TypeManager.short_type)\r
-                                       return new ShortConstant ((short) v);\r
-                               if (target_type == TypeManager.ushort_type)\r
-                                       return new UShortConstant ((ushort) v);\r
-                               if (target_type == TypeManager.int32_type)\r
-                                       return new IntConstant ((int) v);\r
-                               if (target_type == TypeManager.uint32_type)\r
-                                       return new UIntConstant ((uint) v);\r
-                               if (target_type == TypeManager.int64_type)\r
-                                       return new LongConstant ((long) v);\r
-                               if (target_type == TypeManager.uint64_type)\r
-                                       return new ULongConstant ((ulong) v);\r
-                               if (target_type == TypeManager.float_type)\r
-                                       return new FloatConstant ((float) v);\r
-                       }\r
-\r
-                       return null;\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       expr = expr.Resolve (ec);\r
-                       if (expr == null)\r
-                               return null;\r
-\r
-                       bool old_state = ec.OnlyLookupTypes;\r
-                       ec.OnlyLookupTypes = true;\r
-                       target_type = target_type.Resolve (ec);\r
-                       ec.OnlyLookupTypes = old_state;\r
-                       \r
-                       if (target_type == null){\r
-                               Report.Error (-10, loc, "Can not resolve type");\r
-                               return null;\r
-                       }\r
-\r
-                       if (target_type.eclass != ExprClass.Type){\r
-                               report118 (loc, target_type, "class");\r
-                               return null;\r
-                       }\r
-                       \r
-                       type = target_type.Type;\r
-                       eclass = ExprClass.Value;\r
-                       \r
-                       if (type == null)\r
-                               return null;\r
-\r
-                       if (expr is Constant){\r
-                               Expression e = TryReduce (ec, type);\r
-\r
-                               if (e != null)\r
-                                       return e;\r
-                       }\r
-                       \r
-                       expr = ConvertExplicit (ec, expr, type, loc);\r
-                       return expr;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       //\r
-                       // This one will never happen\r
-                       //\r
-                       throw new Exception ("Should not happen");\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Binary operators\r
-       /// </summary>\r
-       public class Binary : Expression {\r
-               public enum Operator : byte {\r
-                       Multiply, Division, Modulus,\r
-                       Addition, Subtraction,\r
-                       LeftShift, RightShift,\r
-                       LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, \r
-                       Equality, Inequality,\r
-                       BitwiseAnd,\r
-                       ExclusiveOr,\r
-                       BitwiseOr,\r
-                       LogicalAnd,\r
-                       LogicalOr\r
-               }\r
-\r
-               Operator oper;\r
-               Expression left, right;\r
-               MethodBase method;\r
-               ArrayList  Arguments;\r
-               Location   loc;\r
-\r
-               bool DelegateOperation;\r
-\r
-               public Binary (Operator oper, Expression left, Expression right, Location loc)\r
-               {\r
-                       this.oper = oper;\r
-                       this.left = left;\r
-                       this.right = right;\r
-                       this.loc = loc;\r
-               }\r
-\r
-               public Operator Oper {\r
-                       get {\r
-                               return oper;\r
-                       }\r
-                       set {\r
-                               oper = value;\r
-                       }\r
-               }\r
-               \r
-               public Expression Left {\r
-                       get {\r
-                               return left;\r
-                       }\r
-                       set {\r
-                               left = value;\r
-                       }\r
-               }\r
-\r
-               public Expression Right {\r
-                       get {\r
-                               return right;\r
-                       }\r
-                       set {\r
-                               right = value;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               ///   Returns a stringified representation of the Operator\r
-               /// </summary>\r
-               static string OperName (Operator oper)\r
-               {\r
-                       switch (oper){\r
-                       case Operator.Multiply:\r
-                               return "*";\r
-                       case Operator.Division:\r
-                               return "/";\r
-                       case Operator.Modulus:\r
-                               return "%";\r
-                       case Operator.Addition:\r
-                               return "+";\r
-                       case Operator.Subtraction:\r
-                               return "-";\r
-                       case Operator.LeftShift:\r
-                               return "<<";\r
-                       case Operator.RightShift:\r
-                               return ">>";\r
-                       case Operator.LessThan:\r
-                               return "<";\r
-                       case Operator.GreaterThan:\r
-                               return ">";\r
-                       case Operator.LessThanOrEqual:\r
-                               return "<=";\r
-                       case Operator.GreaterThanOrEqual:\r
-                               return ">=";\r
-                       case Operator.Equality:\r
-                               return "==";\r
-                       case Operator.Inequality:\r
-                               return "!=";\r
-                       case Operator.BitwiseAnd:\r
-                               return "&";\r
-                       case Operator.BitwiseOr:\r
-                               return "|";\r
-                       case Operator.ExclusiveOr:\r
-                               return "^";\r
-                       case Operator.LogicalOr:\r
-                               return "||";\r
-                       case Operator.LogicalAnd:\r
-                               return "&&";\r
-                       }\r
-\r
-                       return oper.ToString ();\r
-               }\r
-\r
-               Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)\r
-               {\r
-                       if (expr.Type == target_type)\r
-                               return expr;\r
-\r
-                       return ConvertImplicit (ec, expr, target_type, new Location (-1));\r
-               }\r
-\r
-               public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)\r
-               {\r
-                       Report.Error (\r
-                               34, loc, "Operator `" + OperName (oper) \r
-                               + "' is ambiguous on operands of type `"\r
-                               + TypeManager.CSharpName (l) + "' "\r
-                               + "and `" + TypeManager.CSharpName (r)\r
-                               + "'");\r
-               }\r
-\r
-               //\r
-               // Note that handling the case l == Decimal || r == Decimal\r
-               // is taken care of by the Step 1 Operator Overload resolution.\r
-               //\r
-               bool DoNumericPromotions (EmitContext ec, Type l, Type r)\r
-               {\r
-                       if (l == TypeManager.double_type || r == TypeManager.double_type){\r
-                               //\r
-                               // If either operand is of type double, the other operand is\r
-                               // conveted to type double.\r
-                               //\r
-                               if (r != TypeManager.double_type)\r
-                                       right = ConvertImplicit (ec, right, TypeManager.double_type, loc);\r
-                               if (l != TypeManager.double_type)\r
-                                       left = ConvertImplicit (ec, left, TypeManager.double_type, loc);\r
-                               \r
-                               type = TypeManager.double_type;\r
-                       } else if (l == TypeManager.float_type || r == TypeManager.float_type){\r
-                               //\r
-                               // if either operand is of type float, the other operand is\r
-                               // converted to type float.\r
-                               //\r
-                               if (r != TypeManager.double_type)\r
-                                       right = ConvertImplicit (ec, right, TypeManager.float_type, loc);\r
-                               if (l != TypeManager.double_type)\r
-                                       left = ConvertImplicit (ec, left, TypeManager.float_type, loc);\r
-                               type = TypeManager.float_type;\r
-                       } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){\r
-                               Expression e;\r
-                               Type other;\r
-                               //\r
-                               // If either operand is of type ulong, the other operand is\r
-                               // converted to type ulong.  or an error ocurrs if the other\r
-                               // operand is of type sbyte, short, int or long\r
-                               //\r
-                               if (l == TypeManager.uint64_type){\r
-                                       if (r != TypeManager.uint64_type){\r
-                                               if (right is IntConstant){\r
-                                                       IntConstant ic = (IntConstant) right;\r
-                                                       \r
-                                                       e = TryImplicitIntConversion (l, ic);\r
-                                                       if (e != null)\r
-                                                               right = e;\r
-                                               } else if (right is LongConstant){\r
-                                                       long ll = ((LongConstant) right).Value;\r
-\r
-                                                       if (ll > 0)\r
-                                                               right = new ULongConstant ((ulong) ll);\r
-                                               } else {\r
-                                                       e = ImplicitNumericConversion (ec, right, l, loc);\r
-                                                       if (e != null)\r
-                                                               right = e;\r
-                                               }\r
-                                       }\r
-                                       other = right.Type;\r
-                               } else {\r
-                                       if (left is IntConstant){\r
-                                               e = TryImplicitIntConversion (r, (IntConstant) left);\r
-                                               if (e != null)\r
-                                                       left = e;\r
-                                       } else if (left is LongConstant){\r
-                                               long ll = ((LongConstant) left).Value;\r
-                                               \r
-                                               if (ll > 0)\r
-                                                       left = new ULongConstant ((ulong) ll);\r
-                                       } else {\r
-                                               e = ImplicitNumericConversion (ec, left, r, loc);\r
-                                               if (e != null)\r
-                                                       left = e;\r
-                                       }\r
-                                       other = left.Type;\r
-                               }\r
-\r
-                               if ((other == TypeManager.sbyte_type) ||\r
-                                   (other == TypeManager.short_type) ||\r
-                                   (other == TypeManager.int32_type) ||\r
-                                   (other == TypeManager.int64_type))\r
-                                       Error_OperatorAmbiguous (loc, oper, l, r);\r
-                               type = TypeManager.uint64_type;\r
-                       } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){\r
-                               //\r
-                               // If either operand is of type long, the other operand is converted\r
-                               // to type long.\r
-                               //\r
-                               if (l != TypeManager.int64_type)\r
-                                       left = ConvertImplicit (ec, left, TypeManager.int64_type, loc);\r
-                               if (r != TypeManager.int64_type)\r
-                                       right = ConvertImplicit (ec, right, TypeManager.int64_type, loc);\r
-\r
-                               type = TypeManager.int64_type;\r
-                       } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){\r
-                               //\r
-                               // If either operand is of type uint, and the other\r
-                               // operand is of type sbyte, short or int, othe operands are\r
-                               // converted to type long.\r
-                               //\r
-                               Type other = null;\r
-                               \r
-                               if (l == TypeManager.uint32_type){\r
-                                       if (right is IntConstant){\r
-                                               IntConstant ic = (IntConstant) right;\r
-                                               int val = ic.Value;\r
-                                               \r
-                                               if (val >= 0)\r
-                                                       right = new UIntConstant ((uint) val);\r
-\r
-                                               type = l;\r
-                                               return true;\r
-                                       }\r
-                                       other = r;\r
-                               } \r
-                               else if (r == TypeManager.uint32_type){\r
-                                       if (left is IntConstant){\r
-                                               IntConstant ic = (IntConstant) left;\r
-                                               int val = ic.Value;\r
-                                               \r
-                                               if (val >= 0)\r
-                                                       left = new UIntConstant ((uint) val);\r
-\r
-                                               type = r;\r
-                                               return true;\r
-                                       }\r
-                                       \r
-                                       other = l;\r
-                               }\r
-\r
-                               if ((other == TypeManager.sbyte_type) ||\r
-                                   (other == TypeManager.short_type) ||\r
-                                   (other == TypeManager.int32_type)){\r
-                                       left = ForceConversion (ec, left, TypeManager.int64_type);\r
-                                       right = ForceConversion (ec, right, TypeManager.int64_type);\r
-                                       type = TypeManager.int64_type;\r
-                               } else {\r
-                                       //\r
-                                       // if either operand is of type uint, the other\r
-                                       // operand is converd to type uint\r
-                                       //\r
-                                       left = ForceConversion (ec, left, TypeManager.uint32_type);\r
-                                       right = ForceConversion (ec, right, TypeManager.uint32_type);\r
-                                       type = TypeManager.uint32_type;\r
-                               } \r
-                       } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){\r
-                               if (l != TypeManager.decimal_type)\r
-                                       left = ConvertImplicit (ec, left, TypeManager.decimal_type, loc);\r
-                               if (r != TypeManager.decimal_type)\r
-                                       right = ConvertImplicit (ec, right, TypeManager.decimal_type, loc);\r
-\r
-                               type = TypeManager.decimal_type;\r
-                       } else {\r
-                               Expression l_tmp, r_tmp;\r
-\r
-                               l_tmp = ForceConversion (ec, left, TypeManager.int32_type);\r
-                               if (l_tmp == null)\r
-                                       return false;\r
-                               \r
-                               r_tmp = ForceConversion (ec, right, TypeManager.int32_type);\r
-                               if (r_tmp == null)\r
-                                       return false;\r
-\r
-                               left = l_tmp;\r
-                               right = r_tmp;\r
-                               \r
-                               type = TypeManager.int32_type;\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-               static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)\r
-               {\r
-                       Error (19, loc,\r
-                              "Operator " + name + " cannot be applied to operands of type `" +\r
-                              TypeManager.CSharpName (l) + "' and `" +\r
-                              TypeManager.CSharpName (r) + "'");\r
-               }\r
-               \r
-               void error19 ()\r
-               {\r
-                       Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);\r
-               }\r
-\r
-               static bool is_32_or_64 (Type t)\r
-               {\r
-                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||\r
-                               t == TypeManager.int64_type || t == TypeManager.uint64_type);\r
-               }\r
-                                       \r
-               Expression CheckShiftArguments (EmitContext ec)\r
-               {\r
-                       Expression e;\r
-                       Type l = left.Type;\r
-                       Type r = right.Type;\r
-\r
-                       e = ForceConversion (ec, right, TypeManager.int32_type);\r
-                       if (e == null){\r
-                               error19 ();\r
-                               return null;\r
-                       }\r
-                       right = e;\r
-\r
-                       if (((e = ConvertImplicit (ec, left, TypeManager.int32_type, loc)) != null) ||\r
-                           ((e = ConvertImplicit (ec, left, TypeManager.uint32_type, loc)) != null) ||\r
-                           ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) ||\r
-                           ((e = ConvertImplicit (ec, left, TypeManager.uint64_type, loc)) != null)){\r
-                               left = e;\r
-                               type = e.Type;\r
-\r
-                               return this;\r
-                       }\r
-                       error19 ();\r
-                       return null;\r
-               }\r
-               \r
-               Expression ResolveOperator (EmitContext ec)\r
-               {\r
-                       Type l = left.Type;\r
-                       Type r = right.Type;\r
-\r
-                       //\r
-                       // Step 1: Perform Operator Overload location\r
-                       //\r
-                       Expression left_expr, right_expr;\r
-                       \r
-                       string op = "op_" + oper;\r
-\r
-                       MethodGroupExpr union;\r
-                       left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);\r
-                       if (r != l){\r
-                               right_expr = MemberLookup (\r
-                                       ec, r, op, MemberTypes.Method, AllBindingFlags, loc);\r
-                               union = Invocation.MakeUnionSet (left_expr, right_expr);\r
-                       } else\r
-                               union = (MethodGroupExpr) left_expr;\r
-                       \r
-                       if (union != null) {\r
-                               Arguments = new ArrayList ();\r
-                               Arguments.Add (new Argument (left, Argument.AType.Expression));\r
-                               Arguments.Add (new Argument (right, Argument.AType.Expression));\r
-\r
-                               method = Invocation.OverloadResolve (ec, union, Arguments, loc);\r
-                               if (method != null) {\r
-                                       MethodInfo mi = (MethodInfo) method;\r
-\r
-                                       type = mi.ReturnType;\r
-                                       return this;\r
-                               } else {\r
-                                       error19 ();\r
-                                       return null;\r
-                               }\r
-                       }       \r
-\r
-                       //\r
-                       // Step 2: Default operations on CLI native types.\r
-                       //\r
-\r
-                       // Only perform numeric promotions on:\r
-                       // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=\r
-                       //\r
-                       if (oper == Operator.Addition){\r
-                               //\r
-                               // If any of the arguments is a string, cast to string\r
-                               //\r
-                               if (l == TypeManager.string_type){\r
-                                       \r
-                                       if (r == TypeManager.void_type) {\r
-                                               error19 ();\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       if (r == TypeManager.string_type){\r
-                                               if (left is Constant && right is Constant){\r
-                                                       StringConstant ls = (StringConstant) left;\r
-                                                       StringConstant rs = (StringConstant) right;\r
-                                                       \r
-                                                       return new StringConstant (\r
-                                                               ls.Value + rs.Value);\r
-                                               }\r
-                                               \r
-                                               // string + string\r
-                                               method = TypeManager.string_concat_string_string;\r
-                                       } else {\r
-                                               // string + object\r
-                                               method = TypeManager.string_concat_object_object;\r
-                                               right = ConvertImplicit (ec, right,\r
-                                                                        TypeManager.object_type, loc);\r
-                                       }\r
-                                       type = TypeManager.string_type;\r
-\r
-                                       Arguments = new ArrayList ();\r
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));\r
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));\r
-\r
-                                       return this;\r
-                                       \r
-                               } else if (r == TypeManager.string_type){\r
-                                       // object + string\r
-\r
-                                       if (l == TypeManager.void_type) {\r
-                                               error19 ();\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       method = TypeManager.string_concat_object_object;\r
-                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);\r
-                                       Arguments = new ArrayList ();\r
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));\r
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));\r
-\r
-                                       type = TypeManager.string_type;\r
-\r
-                                       return this;\r
-                               }\r
-                       }\r
-\r
-                       if (oper == Operator.Addition || oper == Operator.Subtraction) {\r
-                               if (l.IsSubclassOf (TypeManager.delegate_type) &&\r
-                                   r.IsSubclassOf (TypeManager.delegate_type)) {\r
-                                       \r
-                                       Arguments = new ArrayList ();\r
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));\r
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));\r
-                                       \r
-                                       if (oper == Operator.Addition)\r
-                                               method = TypeManager.delegate_combine_delegate_delegate;\r
-                                       else\r
-                                               method = TypeManager.delegate_remove_delegate_delegate;\r
-                                       \r
-                                       DelegateOperation = true;\r
-                                       type = l;\r
-                                       return this;\r
-                               }\r
-\r
-                               //\r
-                               // Pointer arithmetic:\r
-                               //\r
-                               // T* operator + (T* x, int y);\r
-                               // T* operator + (T* x, uint y);\r
-                               // T* operator + (T* x, long y);\r
-                               // T* operator + (T* x, ulong y);\r
-                               //\r
-                               // T* operator + (int y,   T* x);\r
-                               // T* operator + (uint y,  T *x);\r
-                               // T* operator + (long y,  T *x);\r
-                               // T* operator + (ulong y, T *x);\r
-                               //\r
-                               // T* operator - (T* x, int y);\r
-                               // T* operator - (T* x, uint y);\r
-                               // T* operator - (T* x, long y);\r
-                               // T* operator - (T* x, ulong y);\r
-                               //\r
-                               // long operator - (T* x, T *y)\r
-                               //\r
-                               if (l.IsPointer){\r
-                                       if (r.IsPointer && oper == Operator.Subtraction){\r
-                                               if (r == l)\r
-                                                       return new PointerArithmetic (\r
-                                                               false, left, right, TypeManager.int64_type);\r
-                                       } else if (is_32_or_64 (r))\r
-                                               return new PointerArithmetic (\r
-                                                       oper == Operator.Addition, left, right, l);\r
-                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)\r
-                                       return new PointerArithmetic (\r
-                                               true, right, left, r);\r
-                       }\r
-                       \r
-                       //\r
-                       // Enumeration operators\r
-                       //\r
-                       bool lie = TypeManager.IsEnumType (l);\r
-                       bool rie = TypeManager.IsEnumType (r);\r
-                       if (lie || rie){\r
-                               Expression temp;\r
-\r
-                               if (!rie){\r
-                                       temp = ConvertImplicit (ec, right, l, loc);\r
-                                       if (temp != null)\r
-                                               right = temp;\r
-                               } if (!lie){\r
-                                       temp = ConvertImplicit (ec, left, r, loc);\r
-                                       if (temp != null){\r
-                                               left = temp;\r
-                                               l = r;\r
-                                       }\r
-                               }\r
-                               \r
-                               if (oper == Operator.Equality || oper == Operator.Inequality ||\r
-                                   oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||\r
-                                   oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){\r
-                                       type = TypeManager.bool_type;\r
-                                       return this;\r
-                               }\r
-\r
-                               if (oper == Operator.BitwiseAnd ||\r
-                                   oper == Operator.BitwiseOr ||\r
-                                   oper == Operator.ExclusiveOr){\r
-                                       type = l;\r
-                                       return this;\r
-                               }\r
-                       }\r
-                       \r
-                       if (oper == Operator.LeftShift || oper == Operator.RightShift)\r
-                               return CheckShiftArguments (ec);\r
-\r
-                       if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){\r
-                               if (l != TypeManager.bool_type || r != TypeManager.bool_type){\r
-                                       error19 ();\r
-                                       return null;\r
-                               }\r
-\r
-                               type = TypeManager.bool_type;\r
-                               return this;\r
-                       } \r
-\r
-                       if (oper == Operator.Equality || oper == Operator.Inequality){\r
-                               if (l == TypeManager.bool_type || r == TypeManager.bool_type){\r
-                                       if (r != TypeManager.bool_type || l != TypeManager.bool_type){\r
-                                               error19 ();\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       type = TypeManager.bool_type;\r
-                                       return this;\r
-                               }\r
-\r
-                               //\r
-                               // operator != (object a, object b)\r
-                               // operator == (object a, object b)\r
-                               //\r
-                               // For this to be used, both arguments have to be reference-types.\r
-                               // Read the rationale on the spec (14.9.6)\r
-                               //\r
-                               // Also, if at compile time we know that the classes do not inherit\r
-                               // one from the other, then we catch the error there.\r
-                               //\r
-                               if (!(l.IsValueType || r.IsValueType)){\r
-                                       type = TypeManager.bool_type;\r
-\r
-                                       if (l == r)\r
-                                               return this;\r
-                                       \r
-                                       if (l.IsSubclassOf (r) || r.IsSubclassOf (l))\r
-                                               return this;\r
-\r
-                                       //\r
-                                       // We are going to have to convert to an object to compare\r
-                                       //\r
-                                       if (l != TypeManager.object_type)\r
-                                               left = new EmptyCast (left, TypeManager.object_type);\r
-                                       if (r != TypeManager.object_type)\r
-                                               right = new EmptyCast (right, TypeManager.object_type);\r
-\r
-                                       return this;\r
-                               }\r
-                       }\r
-\r
-                       //\r
-                       // Pointer comparison\r
-                       //\r
-                       if (l.IsPointer && r.IsPointer){\r
-                               if (oper == Operator.Equality || oper == Operator.Inequality ||\r
-                                   oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||\r
-                                   oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){\r
-                                       type = TypeManager.bool_type;\r
-                                       return this;\r
-                               }\r
-                       }\r
-                       \r
-                       //\r
-                       // We are dealing with numbers\r
-                       //\r
-\r
-                       if (!DoNumericPromotions (ec, l, r)){\r
-                               error19 ();\r
-                               return null;\r
-                       }\r
-\r
-                       if (left == null || right == null)\r
-                               return null;\r
-\r
-                       //\r
-                       // reload our cached types if required\r
-                       //\r
-                       l = left.Type;\r
-                       r = right.Type;\r
-                       \r
-                       if (oper == Operator.BitwiseAnd ||\r
-                           oper == Operator.BitwiseOr ||\r
-                           oper == Operator.ExclusiveOr){\r
-                               if (l == r){\r
-                                       if (!((l == TypeManager.int32_type) ||\r
-                                             (l == TypeManager.uint32_type) ||\r
-                                             (l == TypeManager.int64_type) ||\r
-                                             (l == TypeManager.uint64_type)))\r
-                                               type = l;\r
-                               } else {\r
-                                       error19 ();\r
-                                       return null;\r
-                               }\r
-                       }\r
-\r
-                       if (oper == Operator.Equality ||\r
-                           oper == Operator.Inequality ||\r
-                           oper == Operator.LessThanOrEqual ||\r
-                           oper == Operator.LessThan ||\r
-                           oper == Operator.GreaterThanOrEqual ||\r
-                           oper == Operator.GreaterThan){\r
-                               type = TypeManager.bool_type;\r
-                       }\r
-\r
-                       return this;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       left = left.Resolve (ec);\r
-                       right = right.Resolve (ec);\r
-\r
-                       if (left == null || right == null)\r
-                               return null;\r
-\r
-                       if (left.Type == null)\r
-                               throw new Exception (\r
-                                       "Resolve returned non null, but did not set the type! (" +\r
-                                       left + ") at Line: " + loc.Row);\r
-                       if (right.Type == null)\r
-                               throw new Exception (\r
-                                       "Resolve returned non null, but did not set the type! (" +\r
-                                       right + ") at Line: "+ loc.Row);\r
-\r
-                       eclass = ExprClass.Value;\r
-\r
-                       if (left is Constant && right is Constant){\r
-                               Expression e = ConstantFold.BinaryFold (\r
-                                       ec, oper, (Constant) left, (Constant) right, loc);\r
-                               if (e != null)\r
-                                       return e;\r
-                       }\r
-\r
-                       return ResolveOperator (ec);\r
-               }\r
-\r
-               public bool IsBranchable ()\r
-               {\r
-                       if (oper == Operator.Equality ||\r
-                           oper == Operator.Inequality ||\r
-                           oper == Operator.LessThan ||\r
-                           oper == Operator.GreaterThan ||\r
-                           oper == Operator.LessThanOrEqual ||\r
-                           oper == Operator.GreaterThanOrEqual){\r
-                               return true;\r
-                       } else\r
-                               return false;\r
-               }\r
-\r
-               /// <summary>\r
-               ///   This entry point is used by routines that might want\r
-               ///   to emit a brfalse/brtrue after an expression, and instead\r
-               ///   they could use a more compact notation.\r
-               ///\r
-               ///   Typically the code would generate l.emit/r.emit, followed\r
-               ///   by the comparission and then a brtrue/brfalse.  The comparissions\r
-               ///   are sometimes inneficient (there are not as complete as the branches\r
-               ///   look for the hacks in Emit using double ceqs).\r
-               ///\r
-               ///   So for those cases we provide EmitBranchable that can emit the\r
-               ///   branch with the test\r
-               /// </summary>\r
-               public void EmitBranchable (EmitContext ec, int target)\r
-               {\r
-                       OpCode opcode;\r
-                       bool close_target = false;\r
-                       ILGenerator ig = ec.ig;\r
-                               \r
-                       //\r
-                       // short-circuit operators\r
-                       //\r
-                       if (oper == Operator.LogicalAnd){\r
-                               left.Emit (ec);\r
-                               ig.Emit (OpCodes.Brfalse, target);\r
-                               right.Emit (ec);\r
-                               ig.Emit (OpCodes.Brfalse, target);\r
-                       } else if (oper == Operator.LogicalOr){\r
-                               left.Emit (ec);\r
-                               ig.Emit (OpCodes.Brtrue, target);\r
-                               right.Emit (ec);\r
-                               ig.Emit (OpCodes.Brfalse, target);\r
-                       }\r
-                               \r
-                       left.Emit (ec);\r
-                       right.Emit (ec);\r
-                       \r
-                       switch (oper){\r
-                       case Operator.Equality:\r
-                               if (close_target)\r
-                                       opcode = OpCodes.Beq_S;\r
-                               else\r
-                                       opcode = OpCodes.Beq;\r
-                               break;\r
-\r
-                       case Operator.Inequality:\r
-                               if (close_target)\r
-                                       opcode = OpCodes.Bne_Un_S;\r
-                               else\r
-                                       opcode = OpCodes.Bne_Un;\r
-                               break;\r
-\r
-                       case Operator.LessThan:\r
-                               if (close_target)\r
-                                       opcode = OpCodes.Blt_S;\r
-                               else\r
-                                       opcode = OpCodes.Blt;\r
-                               break;\r
-\r
-                       case Operator.GreaterThan:\r
-                               if (close_target)\r
-                                       opcode = OpCodes.Bgt_S;\r
-                               else\r
-                                       opcode = OpCodes.Bgt;\r
-                               break;\r
-\r
-                       case Operator.LessThanOrEqual:\r
-                               if (close_target)\r
-                                       opcode = OpCodes.Ble_S;\r
-                               else\r
-                                       opcode = OpCodes.Ble;\r
-                               break;\r
-\r
-                       case Operator.GreaterThanOrEqual:\r
-                               if (close_target)\r
-                                       opcode = OpCodes.Bge_S;\r
-                               else\r
-                                       opcode = OpCodes.Ble;\r
-                               break;\r
-\r
-                       default:\r
-                               throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "\r
-                                                    + oper.ToString ());\r
-                       }\r
-\r
-                       ig.Emit (opcode, target);\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       Type l = left.Type;\r
-                       Type r = right.Type;\r
-                       OpCode opcode;\r
-\r
-                       if (method != null) {\r
-\r
-                               // Note that operators are static anyway\r
-                               \r
-                               if (Arguments != null) \r
-                                       Invocation.EmitArguments (ec, method, Arguments);\r
-                               \r
-                               if (method is MethodInfo)\r
-                                       ig.Emit (OpCodes.Call, (MethodInfo) method);\r
-                               else\r
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);\r
-\r
-                               if (DelegateOperation)\r
-                                       ig.Emit (OpCodes.Castclass, type);\r
-                                       \r
-                               return;\r
-                       }\r
-\r
-                       //\r
-                       // Handle short-circuit operators differently\r
-                       // than the rest\r
-                       //\r
-                       if (oper == Operator.LogicalAnd){\r
-                               Label load_zero = ig.DefineLabel ();\r
-                               Label end = ig.DefineLabel ();\r
-                               \r
-                               left.Emit (ec);\r
-                               ig.Emit (OpCodes.Brfalse, load_zero);\r
-                               right.Emit (ec);\r
-                               ig.Emit (OpCodes.Br, end);\r
-                               ig.MarkLabel (load_zero);\r
-                               ig.Emit (OpCodes.Ldc_I4_0);\r
-                               ig.MarkLabel (end);\r
-                               return;\r
-                       } else if (oper == Operator.LogicalOr){\r
-                               Label load_one = ig.DefineLabel ();\r
-                               Label end = ig.DefineLabel ();\r
-                               \r
-                               left.Emit (ec);\r
-                               ig.Emit (OpCodes.Brtrue, load_one);\r
-                               right.Emit (ec);\r
-                               ig.Emit (OpCodes.Br, end);\r
-                               ig.MarkLabel (load_one);\r
-                               ig.Emit (OpCodes.Ldc_I4_1);\r
-                               ig.MarkLabel (end);\r
-                               return;\r
-                       }\r
-                       \r
-                       left.Emit (ec);\r
-                       right.Emit (ec);\r
-\r
-                       switch (oper){\r
-                       case Operator.Multiply:\r
-                               if (ec.CheckState){\r
-                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)\r
-                                               opcode = OpCodes.Mul_Ovf;\r
-                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)\r
-                                               opcode = OpCodes.Mul_Ovf_Un;\r
-                                       else\r
-                                               opcode = OpCodes.Mul;\r
-                               } else\r
-                                       opcode = OpCodes.Mul;\r
-\r
-                               break;\r
-\r
-                       case Operator.Division:\r
-                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)\r
-                                       opcode = OpCodes.Div_Un;\r
-                               else\r
-                                       opcode = OpCodes.Div;\r
-                               break;\r
-\r
-                       case Operator.Modulus:\r
-                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)\r
-                                       opcode = OpCodes.Rem_Un;\r
-                               else\r
-                                       opcode = OpCodes.Rem;\r
-                               break;\r
-\r
-                       case Operator.Addition:\r
-                               if (ec.CheckState){\r
-                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)\r
-                                               opcode = OpCodes.Add_Ovf;\r
-                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)\r
-                                               opcode = OpCodes.Add_Ovf_Un;\r
-                                       else\r
-                                               opcode = OpCodes.Add;\r
-                               } else\r
-                                       opcode = OpCodes.Add;\r
-                               break;\r
-\r
-                       case Operator.Subtraction:\r
-                               if (ec.CheckState){\r
-                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)\r
-                                               opcode = OpCodes.Sub_Ovf;\r
-                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)\r
-                                               opcode = OpCodes.Sub_Ovf_Un;\r
-                                       else\r
-                                               opcode = OpCodes.Sub;\r
-                               } else\r
-                                       opcode = OpCodes.Sub;\r
-                               break;\r
-\r
-                       case Operator.RightShift:\r
-                               opcode = OpCodes.Shr;\r
-                               break;\r
-                               \r
-                       case Operator.LeftShift:\r
-                               opcode = OpCodes.Shl;\r
-                               break;\r
-\r
-                       case Operator.Equality:\r
-                               opcode = OpCodes.Ceq;\r
-                               break;\r
-\r
-                       case Operator.Inequality:\r
-                               ec.ig.Emit (OpCodes.Ceq);\r
-                               ec.ig.Emit (OpCodes.Ldc_I4_0);\r
-                               \r
-                               opcode = OpCodes.Ceq;\r
-                               break;\r
-\r
-                       case Operator.LessThan:\r
-                               opcode = OpCodes.Clt;\r
-                               break;\r
-\r
-                       case Operator.GreaterThan:\r
-                               opcode = OpCodes.Cgt;\r
-                               break;\r
-\r
-                       case Operator.LessThanOrEqual:\r
-                               ec.ig.Emit (OpCodes.Cgt);\r
-                               ec.ig.Emit (OpCodes.Ldc_I4_0);\r
-                               \r
-                               opcode = OpCodes.Ceq;\r
-                               break;\r
-\r
-                       case Operator.GreaterThanOrEqual:\r
-                               ec.ig.Emit (OpCodes.Clt);\r
-                               ec.ig.Emit (OpCodes.Ldc_I4_1);\r
-                               \r
-                               opcode = OpCodes.Sub;\r
-                               break;\r
-\r
-                       case Operator.BitwiseOr:\r
-                               opcode = OpCodes.Or;\r
-                               break;\r
-\r
-                       case Operator.BitwiseAnd:\r
-                               opcode = OpCodes.And;\r
-                               break;\r
-\r
-                       case Operator.ExclusiveOr:\r
-                               opcode = OpCodes.Xor;\r
-                               break;\r
-\r
-                       default:\r
-                               throw new Exception ("This should not happen: Operator = "\r
-                                                    + oper.ToString ());\r
-                       }\r
-\r
-                       ig.Emit (opcode);\r
-               }\r
-       }\r
-\r
-       public class PointerArithmetic : Expression {\r
-               Expression left, right;\r
-               bool is_add;\r
-\r
-               //\r
-               // We assume that `l' is always a pointer\r
-               //\r
-               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t)\r
-               {\r
-                       type = t;\r
-                       eclass = ExprClass.Variable;\r
-                       left = l;\r
-                       right = r;\r
-                       is_add = is_addition;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // We are born fully resolved\r
-                       //\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       Type op_type = left.Type;\r
-                       ILGenerator ig = ec.ig;\r
-                       int size = GetTypeSize (op_type.GetElementType ());\r
-                       \r
-                       if (right.Type.IsPointer){\r
-                               //\r
-                               // handle (pointer - pointer)\r
-                               //\r
-                               left.Emit (ec);\r
-                               right.Emit (ec);\r
-                               ig.Emit (OpCodes.Sub);\r
-\r
-                               if (size != 1){\r
-                                       if (size == 0)\r
-                                               ig.Emit (OpCodes.Sizeof, op_type);\r
-                                       else \r
-                                               IntLiteral.EmitInt (ig, size);\r
-                                       ig.Emit (OpCodes.Div);\r
-                               }\r
-                               ig.Emit (OpCodes.Conv_I8);\r
-                       } else {\r
-                               //\r
-                               // handle + and - on (pointer op int)\r
-                               //\r
-                               left.Emit (ec);\r
-                               ig.Emit (OpCodes.Conv_I);\r
-                               right.Emit (ec);\r
-                               if (size != 1){\r
-                                       if (size == 0)\r
-                                               ig.Emit (OpCodes.Sizeof, op_type);\r
-                                       else \r
-                                               IntLiteral.EmitInt (ig, size);\r
-                                       ig.Emit (OpCodes.Mul);\r
-                               }\r
-                               if (is_add)\r
-                                       ig.Emit (OpCodes.Add);\r
-                               else\r
-                                       ig.Emit (OpCodes.Sub);\r
-                       }\r
-               }\r
-       }\r
-       \r
-       /// <summary>\r
-       ///   Implements the ternary conditiona operator (?:)\r
-       /// </summary>\r
-       public class Conditional : Expression {\r
-               Expression expr, trueExpr, falseExpr;\r
-               Location loc;\r
-               \r
-               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)\r
-               {\r
-                       this.expr = expr;\r
-                       this.trueExpr = trueExpr;\r
-                       this.falseExpr = falseExpr;\r
-                       this.loc = l;\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-               }\r
-\r
-               public Expression TrueExpr {\r
-                       get {\r
-                               return trueExpr;\r
-                       }\r
-               }\r
-\r
-               public Expression FalseExpr {\r
-                       get {\r
-                               return falseExpr;\r
-                       }\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       expr = expr.Resolve (ec);\r
-\r
-                       if (expr.Type != TypeManager.bool_type)\r
-                               expr = Expression.ConvertImplicitRequired (\r
-                                       ec, expr, TypeManager.bool_type, loc);\r
-                       \r
-                       trueExpr = trueExpr.Resolve (ec);\r
-                       falseExpr = falseExpr.Resolve (ec);\r
-\r
-                       if (expr == null || trueExpr == null || falseExpr == null)\r
-                               return null;\r
-\r
-                       eclass = ExprClass.Value;\r
-                       if (trueExpr.Type == falseExpr.Type)\r
-                               type = trueExpr.Type;\r
-                       else {\r
-                               Expression conv;\r
-                               Type true_type = trueExpr.Type;\r
-                               Type false_type = falseExpr.Type;\r
-\r
-                               if (trueExpr is NullLiteral){\r
-                                       type = false_type;\r
-                                       return this;\r
-                               } else if (falseExpr is NullLiteral){\r
-                                       type = true_type;\r
-                                       return this;\r
-                               }\r
-                               \r
-                               //\r
-                               // First, if an implicit conversion exists from trueExpr\r
-                               // to falseExpr, then the result type is of type falseExpr.Type\r
-                               //\r
-                               conv = ConvertImplicit (ec, trueExpr, false_type, loc);\r
-                               if (conv != null){\r
-                                       //\r
-                                       // Check if both can convert implicitl to each other's type\r
-                                       //\r
-                                       if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){\r
-                                               Report.Error (\r
-                                                       172, loc,\r
-                                                       "Can not compute type of conditional expression " +\r
-                                                       "as `" + TypeManager.CSharpName (trueExpr.Type) +\r
-                                                       "' and `" + TypeManager.CSharpName (falseExpr.Type) +\r
-                                                       "' convert implicitly to each other");\r
-                                               return null;\r
-                                       }\r
-                                       type = false_type;\r
-                                       trueExpr = conv;\r
-                               } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){\r
-                                       type = true_type;\r
-                                       falseExpr = conv;\r
-                               } else {\r
-                                       Error (173, loc, "The type of the conditional expression can " +\r
-                                              "not be computed because there is no implicit conversion" +\r
-                                              " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +\r
-                                              " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");\r
-                                       return null;\r
-                               }\r
-                       }\r
-\r
-                       if (expr is BoolConstant){\r
-                               BoolConstant bc = (BoolConstant) expr;\r
-\r
-                               if (bc.Value)\r
-                                       return trueExpr;\r
-                               else\r
-                                       return falseExpr;\r
-                       }\r
-\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       Label false_target = ig.DefineLabel ();\r
-                       Label end_target = ig.DefineLabel ();\r
-\r
-                       expr.Emit (ec);\r
-                       ig.Emit (OpCodes.Brfalse, false_target);\r
-                       trueExpr.Emit (ec);\r
-                       ig.Emit (OpCodes.Br, end_target);\r
-                       ig.MarkLabel (false_target);\r
-                       falseExpr.Emit (ec);\r
-                       ig.MarkLabel (end_target);\r
-               }\r
-\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Local variables\r
-       /// </summary>\r
-       public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation {\r
-               public readonly string Name;\r
-               public readonly Block Block;\r
-               Location loc;\r
-               VariableInfo variable_info;\r
-               \r
-               public LocalVariableReference (Block block, string name, Location l)\r
-               {\r
-                       Block = block;\r
-                       Name = name;\r
-                       loc = l;\r
-                       eclass = ExprClass.Variable;\r
-               }\r
-\r
-               public VariableInfo VariableInfo {\r
-                       get {\r
-                               if (variable_info == null)\r
-                                       variable_info = Block.GetVariableInfo (Name);\r
-                               return variable_info;\r
-                       }\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       VariableInfo vi = VariableInfo;\r
-\r
-                       if (Block.IsConstant (Name)) {\r
-                               Expression e = Block.GetConstantExpression (Name);\r
-\r
-                               vi.Used = true;\r
-                               return e;\r
-                       }\r
-\r
-                       type = vi.VariableType;\r
-                       return this;\r
-               }\r
-\r
-               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)\r
-               {\r
-                       Expression e = DoResolve (ec);\r
-\r
-                       if (e == null)\r
-                               return null;\r
-\r
-                       VariableInfo vi = VariableInfo;\r
-                       \r
-                       if (vi.ReadOnly){\r
-                               if (vi.Assigned){\r
-                                       Report.Error (\r
-                                               1604, loc,\r
-                                               "cannot assign to `" + Name + "' because it is readonly");\r
-                                       return null;\r
-                               }\r
-                       }\r
-                       \r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       VariableInfo vi = VariableInfo;\r
-                       ILGenerator ig = ec.ig;\r
-\r
-                       ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);\r
-                       vi.Used = true;\r
-               }\r
-               \r
-               public void EmitAssign (EmitContext ec, Expression source)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       VariableInfo vi = VariableInfo;\r
-\r
-                       vi.Assigned = true;\r
-\r
-                       source.Emit (ec);\r
-                       \r
-                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);\r
-               }\r
-               \r
-               public void AddressOf (EmitContext ec, AddressOp mode)\r
-               {\r
-                       VariableInfo vi = VariableInfo;\r
-\r
-                       if ((mode & AddressOp.Load) != 0)\r
-                               vi.Used = true;\r
-                       if ((mode & AddressOp.Store) != 0)\r
-                               vi.Assigned = true;\r
-\r
-                       ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   This represents a reference to a parameter in the intermediate\r
-       ///   representation.\r
-       /// </summary>\r
-       public class ParameterReference : Expression, IAssignMethod, IMemoryLocation {\r
-               Parameters pars;\r
-               String name;\r
-               int idx;\r
-               public bool is_ref;\r
-               \r
-               public ParameterReference (Parameters pars, int idx, string name)\r
-               {\r
-                       this.pars = pars;\r
-                       this.idx  = idx;\r
-                       this.name = name;\r
-                       eclass = ExprClass.Variable;\r
-               }\r
-\r
-               //\r
-               // Notice that for ref/out parameters, the type exposed is not the\r
-               // same type exposed externally.\r
-               //\r
-               // for "ref int a":\r
-               //   externally we expose "int&"\r
-               //   here we expose       "int".\r
-               //\r
-               // We record this in "is_ref".  This means that the type system can treat\r
-               // the type as it is expected, but when we generate the code, we generate\r
-               // the alternate kind of code.\r
-               //\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       type = pars.GetParameterInfo (ec.DeclSpace, idx, out is_ref);\r
-                       eclass = ExprClass.Variable;\r
-\r
-                       return this;\r
-               }\r
-\r
-               //\r
-               // This method is used by parameters that are references, that are\r
-               // being passed as references:  we only want to pass the pointer (that\r
-               // is already stored in the parameter, not the address of the pointer,\r
-               // and not the value of the variable).\r
-               //\r
-               public void EmitLoad (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       int arg_idx = idx;\r
-\r
-                       if (!ec.IsStatic)\r
-                               arg_idx++;\r
-                       \r
-                       if (arg_idx <= 255)\r
-                               ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);\r
-                       else\r
-                               ig.Emit (OpCodes.Ldarg, arg_idx);\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       int arg_idx = idx;\r
-\r
-                       if (!ec.IsStatic)\r
-                               arg_idx++;\r
-                       \r
-                       if (arg_idx <= 255)\r
-                               ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);\r
-                       else\r
-                               ig.Emit (OpCodes.Ldarg, arg_idx);\r
-\r
-                       if (!is_ref)\r
-                               return;\r
-\r
-                       //\r
-                       // If we are a reference, we loaded on the stack a pointer\r
-                       // Now lets load the real value\r
-                       //\r
-                       LoadFromPtr (ig, type, true);\r
-               }\r
-\r
-               public void EmitAssign (EmitContext ec, Expression source)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       int arg_idx = idx;\r
-\r
-                       if (!ec.IsStatic)\r
-                               arg_idx++;\r
-\r
-                       if (is_ref){\r
-                               // Load the pointer\r
-                               if (arg_idx <= 255)\r
-                                       ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);\r
-                               else\r
-                                       ig.Emit (OpCodes.Ldarg, arg_idx);\r
-                       }\r
-                       \r
-                       source.Emit (ec);\r
-\r
-                       if (is_ref)\r
-                               StoreFromPtr (ig, type);\r
-                       else {\r
-                               if (arg_idx <= 255)\r
-                                       ig.Emit (OpCodes.Starg_S, (byte) arg_idx);\r
-                               else\r
-                                       ig.Emit (OpCodes.Starg, arg_idx);\r
-                       }\r
-                       \r
-               }\r
-\r
-               public void AddressOf (EmitContext ec, AddressOp mode)\r
-               {\r
-                       int arg_idx = idx;\r
-\r
-                       if (!ec.IsStatic)\r
-                               arg_idx++;\r
-\r
-                       if (arg_idx <= 255)\r
-                               ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);\r
-                       else\r
-                               ec.ig.Emit (OpCodes.Ldarga, arg_idx);\r
-               }\r
-       }\r
-       \r
-       /// <summary>\r
-       ///   Used for arguments to New(), Invocation()\r
-       /// </summary>\r
-       public class Argument {\r
-               public enum AType : byte {\r
-                       Expression,\r
-                       Ref,\r
-                       Out\r
-               };\r
-\r
-               public readonly AType ArgType;\r
-               public Expression expr;\r
-               \r
-               public Argument (Expression expr, AType type)\r
-               {\r
-                       this.expr = expr;\r
-                       this.ArgType = type;\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-\r
-                       set {\r
-                               expr = value;\r
-                       }\r
-               }\r
-\r
-               public Type Type {\r
-                       get {\r
-                               return expr.Type;\r
-                       }\r
-               }\r
-\r
-               public Parameter.Modifier GetParameterModifier ()\r
-               {\r
-                       if (ArgType == AType.Ref || ArgType == AType.Out)\r
-                               return Parameter.Modifier.OUT;\r
-\r
-                       return Parameter.Modifier.NONE;\r
-               }\r
-\r
-               public static string FullDesc (Argument a)\r
-               {\r
-                       return (a.ArgType == AType.Ref ? "ref " :\r
-                               (a.ArgType == AType.Out ? "out " : "")) +\r
-                               TypeManager.CSharpName (a.Expr.Type);\r
-               }\r
-               \r
-               public bool Resolve (EmitContext ec, Location loc)\r
-               {\r
-                       expr = expr.Resolve (ec);\r
-\r
-                       if (ArgType == AType.Expression)\r
-                               return expr != null;\r
-\r
-                       if (expr.eclass != ExprClass.Variable){\r
-                               //\r
-                               // We just probe to match the CSC output\r
-                               //\r
-                               if (expr.eclass == ExprClass.PropertyAccess ||\r
-                                   expr.eclass == ExprClass.IndexerAccess){\r
-                                       Report.Error (\r
-                                               206, loc,\r
-                                               "A property or indexer can not be passed as an out or ref " +\r
-                                               "parameter");\r
-                               } else {\r
-                                       Report.Error (\r
-                                               1510, loc,\r
-                                               "An lvalue is required as an argument to out or ref");\r
-                               }\r
-                               return false;\r
-                       }\r
-                               \r
-                       return expr != null;\r
-               }\r
-\r
-               public void Emit (EmitContext ec)\r
-               {\r
-                       //\r
-                       // Ref and Out parameters need to have their addresses taken.\r
-                       //\r
-                       // ParameterReferences might already be references, so we want\r
-                       // to pass just the value\r
-                       //\r
-                       if (ArgType == AType.Ref || ArgType == AType.Out){\r
-                               AddressOp mode = AddressOp.Store;\r
-\r
-                               if (ArgType == AType.Ref)\r
-                                       mode |= AddressOp.Load;\r
-                               \r
-                               if (expr is ParameterReference){\r
-                                       ParameterReference pr = (ParameterReference) expr;\r
-\r
-                                       if (pr.is_ref)\r
-                                               pr.EmitLoad (ec);\r
-                                       else {\r
-                                               \r
-                                               pr.AddressOf (ec, mode);\r
-                                       }\r
-                               } else\r
-                                       ((IMemoryLocation)expr).AddressOf (ec, mode);\r
-                       } else\r
-                               expr.Emit (ec);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Invocation of methods or delegates.\r
-       /// </summary>\r
-       public class Invocation : ExpressionStatement {\r
-               public readonly ArrayList Arguments;\r
-               Location loc;\r
-\r
-               Expression expr;\r
-               MethodBase method = null;\r
-               bool is_base;\r
-               \r
-               static Hashtable method_parameter_cache;\r
-\r
-               static Invocation ()\r
-               {\r
-                       method_parameter_cache = new PtrHashtable ();\r
-               }\r
-                       \r
-               //\r
-               // arguments is an ArrayList, but we do not want to typecast,\r
-               // as it might be null.\r
-               //\r
-               // FIXME: only allow expr to be a method invocation or a\r
-               // delegate invocation (7.5.5)\r
-               //\r
-               public Invocation (Expression expr, ArrayList arguments, Location l)\r
-               {\r
-                       this.expr = expr;\r
-                       Arguments = arguments;\r
-                       loc = l;\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               ///   Returns the Parameters (a ParameterData interface) for the\r
-               ///   Method `mb'\r
-               /// </summary>\r
-               public static ParameterData GetParameterData (MethodBase mb)\r
-               {\r
-                       object pd = method_parameter_cache [mb];\r
-                       object ip;\r
-                       \r
-                       if (pd != null)\r
-                               return (ParameterData) pd;\r
-\r
-                       \r
-                       ip = TypeManager.LookupParametersByBuilder (mb);\r
-                       if (ip != null){\r
-                               method_parameter_cache [mb] = ip;\r
-\r
-                               return (ParameterData) ip;\r
-                       } else {\r
-                               ParameterInfo [] pi = mb.GetParameters ();\r
-                               ReflectionParameters rp = new ReflectionParameters (pi);\r
-                               method_parameter_cache [mb] = rp;\r
-\r
-                               return (ParameterData) rp;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               ///  Determines "better conversion" as specified in 7.4.2.3\r
-               ///  Returns : 1 if a->p is better\r
-               ///            0 if a->q or neither is better \r
-               /// </summary>\r
-               static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)\r
-               {\r
-                       Type argument_type = a.Type;\r
-                       Expression argument_expr = a.Expr;\r
-\r
-                       if (argument_type == null)\r
-                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");\r
-\r
-                       if (p == q)\r
-                               return 0;\r
-                       \r
-                       if (argument_type == p)\r
-                               return 1;\r
-\r
-                       if (argument_type == q)\r
-                               return 0;\r
-\r
-                       //\r
-                       // Now probe whether an implicit constant expression conversion\r
-                       // can be used.\r
-                       //\r
-                       // An implicit constant expression conversion permits the following\r
-                       // conversions:\r
-                       //\r
-                       //    * A constant-expression of type `int' can be converted to type\r
-                       //      sbyte, byute, short, ushort, uint, ulong provided the value of\r
-                       //      of the expression is withing the range of the destination type.\r
-                       //\r
-                       //    * A constant-expression of type long can be converted to type\r
-                       //      ulong, provided the value of the constant expression is not negative\r
-                       //\r
-                       // FIXME: Note that this assumes that constant folding has\r
-                       // taken place.  We dont do constant folding yet.\r
-                       //\r
-\r
-                       if (argument_expr is IntConstant){\r
-                               IntConstant ei = (IntConstant) argument_expr;\r
-                               int value = ei.Value;\r
-                               \r
-                               if (p == TypeManager.sbyte_type){\r
-                                       if (value >= SByte.MinValue && value <= SByte.MaxValue)\r
-                                               return 1;\r
-                               } else if (p == TypeManager.byte_type){\r
-                                       if (Byte.MinValue >= 0 && value <= Byte.MaxValue)\r
-                                               return 1;\r
-                               } else if (p == TypeManager.short_type){\r
-                                       if (value >= Int16.MinValue && value <= Int16.MaxValue)\r
-                                               return 1;\r
-                               } else if (p == TypeManager.ushort_type){\r
-                                       if (value >= UInt16.MinValue && value <= UInt16.MaxValue)\r
-                                               return 1;\r
-                               } else if (p == TypeManager.uint32_type){\r
-                                       //\r
-                                       // we can optimize this case: a positive int32\r
-                                       // always fits on a uint32\r
-                                       //\r
-                                       if (value >= 0)\r
-                                               return 1;\r
-                               } else if (p == TypeManager.uint64_type){\r
-                                       //\r
-                                       // we can optimize this case: a positive int32\r
-                                       // always fits on a uint64\r
-                                       //\r
-                                       if (value >= 0)\r
-                                               return 1;\r
-                               }\r
-                       } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){\r
-                               LongConstant lc = (LongConstant) argument_expr;\r
-                               \r
-                               if (p == TypeManager.uint64_type){\r
-                                       if (lc.Value > 0)\r
-                                               return 1;\r
-                               }\r
-                       }\r
-\r
-                       if (q == null) {\r
-                               Expression tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);\r
-                               \r
-                               if (tmp != null)\r
-                                       return 1;\r
-                               else\r
-                                       return 0;\r
-                       }\r
-\r
-                       Expression p_tmp = new EmptyExpression (p);\r
-                       Expression q_tmp = new EmptyExpression (q);\r
-                       \r
-                       if (StandardConversionExists (p_tmp, q) == true &&\r
-                           StandardConversionExists (q_tmp, p) == false)\r
-                               return 1;\r
-\r
-                       if (p == TypeManager.sbyte_type)\r
-                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||\r
-                                   q == TypeManager.uint32_type || q == TypeManager.uint64_type)\r
-                                       return 1;\r
-\r
-                       if (p == TypeManager.short_type)\r
-                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||\r
-                                   q == TypeManager.uint64_type)\r
-                                       return 1;\r
-\r
-                       if (p == TypeManager.int32_type)\r
-                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)\r
-                                       return 1;\r
-\r
-                       if (p == TypeManager.int64_type)\r
-                               if (q == TypeManager.uint64_type)\r
-                                       return 1;\r
-\r
-                       return 0;\r
-               }\r
-               \r
-               /// <summary>\r
-               ///  Determines "Better function"\r
-               /// </summary>\r
-               /// <remarks>\r
-               ///    and returns an integer indicating :\r
-               ///    0 if candidate ain't better\r
-               ///    1 if candidate is better than the current best match\r
-               /// </remarks>\r
-               static int BetterFunction (EmitContext ec, ArrayList args,\r
-                                          MethodBase candidate, MethodBase best,\r
-                                          bool expanded_form, Location loc)\r
-               {\r
-                       ParameterData candidate_pd = GetParameterData (candidate);\r
-                       ParameterData best_pd;\r
-                       int argument_count;\r
-               \r
-\r
-                       if (args == null)\r
-                               argument_count = 0;\r
-                       else\r
-                               argument_count = args.Count;\r
-\r
-                       int cand_count = candidate_pd.Count;\r
-\r
-                       if (cand_count == 0 && argument_count == 0)\r
-                               return 1;\r
-\r
-                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)\r
-                               if (cand_count != argument_count)\r
-                                       return 0;\r
-                       \r
-                       if (best == null) {\r
-                               int x = 0;\r
-\r
-                               if (argument_count == 0 && cand_count == 1 &&\r
-                                   candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)\r
-                                       return 1;\r
-                               \r
-                               for (int j = argument_count; j > 0;) {\r
-                                       j--;\r
-\r
-                                       Argument a = (Argument) args [j];\r
-                                       Type t = candidate_pd.ParameterType (j);\r
-\r
-                                       if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)\r
-                                               if (expanded_form)\r
-                                                       t = t.GetElementType ();\r
-\r
-                                       x = BetterConversion (ec, a, t, null, loc);\r
-                                       \r
-                                       if (x <= 0)\r
-                                               break;\r
-                               }\r
-                               \r
-                               if (x > 0)\r
-                                       return 1;\r
-                               else\r
-                                       return 0;\r
-                       }\r
-\r
-                       best_pd = GetParameterData (best);\r
-\r
-                       int rating1 = 0, rating2 = 0;\r
-                       \r
-                       for (int j = 0; j < argument_count; ++j) {\r
-                               int x, y;\r
-                               \r
-                               Argument a = (Argument) args [j];\r
-\r
-                               Type ct = candidate_pd.ParameterType (j);\r
-                               Type bt = best_pd.ParameterType (j);\r
-\r
-                               if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)\r
-                                       if (expanded_form)\r
-                                               ct = ct.GetElementType ();\r
-\r
-                               if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)\r
-                                       if (expanded_form)\r
-                                               bt = bt.GetElementType ();\r
-                               \r
-                               x = BetterConversion (ec, a, ct, bt, loc);\r
-                               y = BetterConversion (ec, a, bt, ct, loc);\r
-\r
-                               if (x < y)\r
-                                       return 0;\r
-                               \r
-                               rating1 += x;\r
-                               rating2 += y;\r
-                       }\r
-\r
-                       if (rating1 > rating2)\r
-                               return 1;\r
-                       else\r
-                               return 0;\r
-               }\r
-\r
-               public static string FullMethodDesc (MethodBase mb)\r
-               {\r
-                       string ret_type = "";\r
-\r
-                       if (mb is MethodInfo)\r
-                               ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);\r
-                       \r
-                       StringBuilder sb = new StringBuilder (ret_type + " " + mb.Name);\r
-                       ParameterData pd = GetParameterData (mb);\r
-\r
-                       int count = pd.Count;\r
-                       sb.Append (" (");\r
-                       \r
-                       for (int i = count; i > 0; ) {\r
-                               i--;\r
-\r
-                               sb.Append (pd.ParameterDesc (count - i - 1));\r
-                               if (i != 0)\r
-                                       sb.Append (", ");\r
-                       }\r
-                       \r
-                       sb.Append (")");\r
-                       return sb.ToString ();\r
-               }\r
-\r
-               public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2)\r
-               {\r
-                       MemberInfo [] miset;\r
-                       MethodGroupExpr union;\r
-                       \r
-                       if (mg1 != null && mg2 != null) {\r
-                               \r
-                               MethodGroupExpr left_set = null, right_set = null;\r
-                               int length1 = 0, length2 = 0;\r
-                               \r
-                               left_set = (MethodGroupExpr) mg1;\r
-                               length1 = left_set.Methods.Length;\r
-                               \r
-                               right_set = (MethodGroupExpr) mg2;\r
-                               length2 = right_set.Methods.Length;\r
-\r
-                               ArrayList common = new ArrayList ();\r
-                               \r
-                               for (int i = 0; i < left_set.Methods.Length; i++) {\r
-                                       for (int j = 0; j < right_set.Methods.Length; j++) {\r
-                                               if (left_set.Methods [i] == right_set.Methods [j]) \r
-                                                       common.Add (left_set.Methods [i]);\r
-                                       }\r
-                               }\r
-                               \r
-                               miset = new MemberInfo [length1 + length2 - common.Count];\r
-\r
-                               left_set.Methods.CopyTo (miset, 0);\r
-\r
-                               int k = 0;\r
-                               \r
-                               for (int j = 0; j < right_set.Methods.Length; j++)\r
-                                       if (!common.Contains (right_set.Methods [j]))\r
-                                               miset [length1 + k++] = right_set.Methods [j];\r
-                               \r
-                               union = new MethodGroupExpr (miset);\r
-\r
-                               return union;\r
-\r
-                       } else if (mg1 == null && mg2 != null) {\r
-                               \r
-                               MethodGroupExpr me = (MethodGroupExpr) mg2; \r
-                               \r
-                               miset = new MemberInfo [me.Methods.Length];\r
-                               me.Methods.CopyTo (miset, 0);\r
-\r
-                               union = new MethodGroupExpr (miset);\r
-                               \r
-                               return union;\r
-\r
-                       } else if (mg2 == null && mg1 != null) {\r
-                               \r
-                               MethodGroupExpr me = (MethodGroupExpr) mg1; \r
-                               \r
-                               miset = new MemberInfo [me.Methods.Length];\r
-                               me.Methods.CopyTo (miset, 0);\r
-\r
-                               union = new MethodGroupExpr (miset);\r
-                               \r
-                               return union;\r
-                       }\r
-                       \r
-                       return null;\r
-               }\r
-\r
-               /// <summary>\r
-               ///  Determines is the candidate method, if a params method, is applicable\r
-               ///  in its expanded form to the given set of arguments\r
-               /// </summary>\r
-               static bool IsParamsMethodApplicable (ArrayList arguments, MethodBase candidate)\r
-               {\r
-                       int arg_count;\r
-                       \r
-                       if (arguments == null)\r
-                               arg_count = 0;\r
-                       else\r
-                               arg_count = arguments.Count;\r
-                       \r
-                       ParameterData pd = GetParameterData (candidate);\r
-                       \r
-                       int pd_count = pd.Count;\r
-\r
-                       if (pd_count == 0)\r
-                               return false;\r
-                       \r
-                       if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)\r
-                               return false;\r
-                       \r
-                       if (pd_count - 1 > arg_count)\r
-                               return false;\r
-                       \r
-                       if (pd_count == 1 && arg_count == 0)\r
-                               return true;\r
-                       \r
-                       //\r
-                       // If we have come this far, the case which remains is when the number of parameters\r
-                       // is less than or equal to the argument count.\r
-\r
-                       for (int i = 0; i < pd_count - 1; ++i) {\r
-\r
-                               Argument a = (Argument) arguments [i];\r
-\r
-                               Parameter.Modifier a_mod = a.GetParameterModifier ();\r
-                               Parameter.Modifier p_mod = pd.ParameterModifier (i);\r
-\r
-                               if (a_mod == p_mod) {\r
-                                       \r
-                                       if (a_mod == Parameter.Modifier.NONE)\r
-                                               if (!StandardConversionExists (a.Expr, pd.ParameterType (i)))\r
-                                                       return false;\r
-                                                                               \r
-                                       if (a_mod == Parameter.Modifier.REF ||\r
-                                           a_mod == Parameter.Modifier.OUT)\r
-                                               if (pd.ParameterType (i) != a.Type)\r
-                                                       return false;\r
-                               } else\r
-                                       return false;\r
-                               \r
-                       }\r
-\r
-                       Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();\r
-\r
-                       for (int i = pd_count - 1; i < arg_count; i++) {\r
-                               Argument a = (Argument) arguments [i];\r
-                               \r
-                               if (!StandardConversionExists (a.Expr, element_type))\r
-                                       return false;\r
-                       }\r
-                       \r
-                       return true;\r
-               }\r
-\r
-               /// <summary>\r
-               ///  Determines if the candidate method is applicable (section 14.4.2.1)\r
-               ///  to the given set of arguments\r
-               /// </summary>\r
-               static bool IsApplicable (ArrayList arguments, MethodBase candidate)\r
-               {\r
-                       int arg_count;\r
-\r
-                       if (arguments == null)\r
-                               arg_count = 0;\r
-                       else\r
-                               arg_count = arguments.Count;\r
-\r
-                       ParameterData pd = GetParameterData (candidate);\r
-\r
-                       int pd_count = pd.Count;\r
-\r
-                       if (arg_count != pd.Count)\r
-                               return false;\r
-\r
-                       for (int i = arg_count; i > 0; ) {\r
-                               i--;\r
-\r
-                               Argument a = (Argument) arguments [i];\r
-\r
-                               Parameter.Modifier a_mod = a.GetParameterModifier ();\r
-                               Parameter.Modifier p_mod = pd.ParameterModifier (i);\r
-\r
-                               if (a_mod == p_mod) {\r
-                                       \r
-                                       if (a_mod == Parameter.Modifier.NONE)\r
-                                               if (!StandardConversionExists (a.Expr, pd.ParameterType (i)))\r
-                                                       return false;\r
-                                       \r
-                                       if (a_mod == Parameter.Modifier.REF ||\r
-                                           a_mod == Parameter.Modifier.OUT)\r
-                                               if (pd.ParameterType (i) != a.Type)\r
-                                                       return false;\r
-                               } else\r
-                                       return false;\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-               \r
-               \r
-\r
-               /// <summary>\r
-               ///   Find the Applicable Function Members (7.4.2.1)\r
-               ///\r
-               ///   me: Method Group expression with the members to select.\r
-               ///       it might contain constructors or methods (or anything\r
-               ///       that maps to a method).\r
-               ///\r
-               ///   Arguments: ArrayList containing resolved Argument objects.\r
-               ///\r
-               ///   loc: The location if we want an error to be reported, or a Null\r
-               ///        location for "probing" purposes.\r
-               ///\r
-               ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)\r
-               ///            that is the best match of me on Arguments.\r
-               ///\r
-               /// </summary>\r
-               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,\r
-                                                         ArrayList Arguments, Location loc)\r
-               {\r
-                       ArrayList afm = new ArrayList ();\r
-                       int best_match_idx = -1;\r
-                       MethodBase method = null;\r
-                       int argument_count;\r
-                       ArrayList candidates = new ArrayList ();\r
-\r
-                       for (int i = me.Methods.Length; i > 0; ){\r
-                               i--;\r
-                               MethodBase candidate  = me.Methods [i];\r
-                               int x;\r
-\r
-                               // Check if candidate is applicable (section 14.4.2.1)\r
-                               if (!IsApplicable (Arguments, candidate))\r
-                                       continue;\r
-\r
-                               candidates.Add (candidate);\r
-\r
-                               x = BetterFunction (ec, Arguments, candidate, method, false, loc);\r
-                               \r
-                               if (x == 0)\r
-                                       continue;\r
-                               else {\r
-                                       best_match_idx = i;\r
-                                       method = me.Methods [best_match_idx];\r
-                               }\r
-                       }\r
-\r
-                       if (Arguments == null)\r
-                               argument_count = 0;\r
-                       else\r
-                               argument_count = Arguments.Count;\r
-                       \r
-                       //\r
-                       // Now we see if we can find params functions, applicable in their expanded form\r
-                       // since if they were applicable in their normal form, they would have been selected\r
-                       // above anyways\r
-                       //\r
-                       bool chose_params_expanded = false;\r
-                       \r
-                       if (best_match_idx == -1) {\r
-\r
-                               candidates = new ArrayList ();\r
-                               for (int i = me.Methods.Length; i > 0; ) {\r
-                                       i--;\r
-                                       MethodBase candidate = me.Methods [i];\r
-\r
-                                       if (!IsParamsMethodApplicable (Arguments, candidate))\r
-                                               continue;\r
-\r
-                                       candidates.Add (candidate);\r
-\r
-                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);\r
-\r
-                                       if (x == 0)\r
-                                               continue;\r
-                                       else {\r
-                                               best_match_idx = i;\r
-                                               method = me.Methods [best_match_idx];\r
-                                               chose_params_expanded = true;\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       //\r
-                       // Now we see if we can at least find a method with the same number of arguments\r
-                       //\r
-                       ParameterData pd;\r
-                       int method_count = 0;\r
-\r
-                       if (best_match_idx == -1) {\r
-\r
-                               for (int i = me.Methods.Length; i > 0;) {\r
-                                       i--;\r
-                                       MethodBase mb = me.Methods [i];\r
-                                       pd = GetParameterData (mb);\r
-                                       \r
-                                       if (pd.Count == argument_count) {\r
-                                               best_match_idx = i;\r
-                                               method = me.Methods [best_match_idx];\r
-                                               method_count++;\r
-                                       } else\r
-                                               continue;\r
-                               }\r
-                       }\r
-\r
-                       if (method == null)\r
-                               return null;\r
-\r
-                       //\r
-                       // Now check that there are no ambiguities i.e the selected method\r
-                       // should be better than all the others\r
-                       //\r
-\r
-                       for (int i = 0; i < candidates.Count; ++i) {\r
-                               MethodBase candidate = (MethodBase) candidates [i];\r
-\r
-                               if (candidate == method)\r
-                                       continue;\r
-\r
-                               //\r
-                               // If a normal method is applicable in the sense that it has the same\r
-                               // number of arguments, then the expanded params method is never applicable\r
-                               // so we debar the params method.\r
-                               //\r
-                               if (IsParamsMethodApplicable (Arguments, candidate) &&\r
-                                   IsApplicable (Arguments, method))\r
-                                       continue;\r
-                                       \r
-                               int x = BetterFunction (ec, Arguments, method, candidate,\r
-                                                       chose_params_expanded, loc);\r
-\r
-                               if (x != 1) {\r
-                                       //Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));\r
-                                       //Console.WriteLine ("Best : " + FullMethodDesc (method));\r
-                                       Report.Error (\r
-                                               121, loc,\r
-                                               "Ambiguous call when selecting function due to implicit casts");\r
-                                       return null;\r
-                               }\r
-                       }\r
-                       \r
-                       // And now convert implicitly, each argument to the required type\r
-                       \r
-                       pd = GetParameterData (method);\r
-                       int pd_count = pd.Count;\r
-\r
-                       for (int j = 0; j < argument_count; j++) {\r
-                               Argument a = (Argument) Arguments [j];\r
-                               Expression a_expr = a.Expr;\r
-                               Type parameter_type = pd.ParameterType (j);\r
-\r
-                               if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS && chose_params_expanded)\r
-                                       parameter_type = parameter_type.GetElementType ();\r
-\r
-                               if (a.Type != parameter_type){\r
-                                       Expression conv;\r
-                                       \r
-                                       conv = ConvertImplicitStandard (ec, a_expr, parameter_type, loc);\r
-\r
-                                       if (conv == null) {\r
-                                               if (!Location.IsNull (loc)) {\r
-                                                       Error (1502, loc,\r
-                                                              "The best overloaded match for method '" +\r
-                                                              FullMethodDesc (method) +\r
-                                                              "' has some invalid arguments");\r
-                                                       Error (1503, loc,\r
-                                                        "Argument " + (j+1) +\r
-                                                        ": Cannot convert from '" + Argument.FullDesc (a) \r
-                                                        + "' to '" + pd.ParameterDesc (j) + "'");\r
-                                               }\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       //\r
-                                       // Update the argument with the implicit conversion\r
-                                       //\r
-                                       if (a_expr != conv)\r
-                                               a.Expr = conv;\r
-\r
-                                       // FIXME : For the case of params methods, we need to actually instantiate\r
-                                       // an array and initialize it with the argument values etc etc.\r
-\r
-                               }\r
-                               \r
-                               if (a.GetParameterModifier () != pd.ParameterModifier (j) &&\r
-                                   pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {\r
-                                       if (!Location.IsNull (loc)) {\r
-                                               Console.WriteLine ("A:P: " + a.GetParameterModifier ());\r
-                                               Console.WriteLine ("PP:: " + pd.ParameterModifier (j));\r
-                                               Console.WriteLine ("PT:  " + parameter_type.IsByRef);\r
-                                               Error (1502, loc,\r
-                                                      "The best overloaded match for method '" + FullMethodDesc (method)+\r
-                                                      "' has some invalid arguments");\r
-                                               Error (1503, loc,\r
-                                                      "Argument " + (j+1) +\r
-                                                      ": Cannot convert from '" + Argument.FullDesc (a) \r
-                                                      + "' to '" + pd.ParameterDesc (j) + "'");\r
-                                       }\r
-                                       return null;\r
-                               }\r
-                       }\r
-                       \r
-                       return method;\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // First, resolve the expression that is used to\r
-                       // trigger the invocation\r
-                       //\r
-                       if (expr is BaseAccess)\r
-                               is_base = true;\r
-\r
-                       expr = expr.Resolve (ec);\r
-                       if (expr == null)\r
-                               return null;\r
-\r
-                       if (!(expr is MethodGroupExpr)) {\r
-                               Type expr_type = expr.Type;\r
-\r
-                               if (expr_type != null){\r
-                                       bool IsDelegate = TypeManager.IsDelegateType (expr_type);\r
-                                       if (IsDelegate)\r
-                                               return (new DelegateInvocation (\r
-                                                       this.expr, Arguments, loc)).Resolve (ec);\r
-                               }\r
-                       }\r
-\r
-                       if (!(expr is MethodGroupExpr)){\r
-                               report118 (loc, this.expr, "method group");\r
-                               return null;\r
-                       }\r
-\r
-                       //\r
-                       // Next, evaluate all the expressions in the argument list\r
-                       //\r
-                       if (Arguments != null){\r
-                               for (int i = Arguments.Count; i > 0;){\r
-                                       --i;\r
-                                       Argument a = (Argument) Arguments [i];\r
-\r
-                                       if (!a.Resolve (ec, loc))\r
-                                               return null;\r
-                               }\r
-                       }\r
-\r
-                       method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments, loc);\r
-\r
-                       if (method == null){\r
-                               Error (-6, loc,\r
-                                      "Could not find any applicable function for this argument list");\r
-                               return null;\r
-                       }\r
-\r
-                       if (method is MethodInfo)\r
-                               type = ((MethodInfo)method).ReturnType;\r
-\r
-                       if (type.IsPointer){\r
-                               if (!ec.InUnsafe){\r
-                                       UnsafeError (loc);\r
-                                       return null;\r
-                               }\r
-                       }\r
-                       \r
-                       eclass = ExprClass.Value;\r
-                       return this;\r
-               }\r
-\r
-               // <summary>\r
-               //   Emits the list of arguments as an array\r
-               // </summary>\r
-               static void EmitParams (EmitContext ec, int idx, ArrayList arguments)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       int count = arguments.Count - idx;\r
-                       Argument a = (Argument) arguments [idx];\r
-                       Type t = a.expr.Type;\r
-                       string array_type = t.FullName + "[]";\r
-                       LocalBuilder array;\r
-                       \r
-                       array = ig.DeclareLocal (Type.GetType (array_type));\r
-                       IntConstant.EmitInt (ig, count);\r
-                       ig.Emit (OpCodes.Newarr, t);\r
-                       ig.Emit (OpCodes.Stloc, array);\r
-\r
-                       int top = arguments.Count;\r
-                       for (int j = idx; j < top; j++){\r
-                               a = (Argument) arguments [j];\r
-                               \r
-                               ig.Emit (OpCodes.Ldloc, array);\r
-                               IntConstant.EmitInt (ig, j - idx);\r
-                               a.Emit (ec);\r
-                               \r
-                               ArrayAccess.EmitStoreOpcode (ig, t);\r
-                       }\r
-                       ig.Emit (OpCodes.Ldloc, array);\r
-               }\r
-               \r
-               /// <summary>\r
-               ///   Emits a list of resolved Arguments that are in the arguments\r
-               ///   ArrayList.\r
-               /// \r
-               ///   The MethodBase argument might be null if the\r
-               ///   emission of the arguments is known not to contain\r
-               ///   a `params' field (for example in constructors or other routines\r
-               ///   that keep their arguments in this structure\r
-               /// </summary>\r
-               public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)\r
-               {\r
-                       ParameterData pd = null;\r
-                       int top;\r
-\r
-                       if (arguments != null)\r
-                               top = arguments.Count;\r
-                       else\r
-                               top = 0;\r
-\r
-                       if (mb != null)\r
-                                pd = GetParameterData (mb);\r
-\r
-                       for (int i = 0; i < top; i++){\r
-                               Argument a = (Argument) arguments [i];\r
-\r
-                               if (pd != null){\r
-                                       if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){\r
-                                               EmitParams (ec, i, arguments);\r
-                                               return;\r
-                                       }\r
-                               }\r
-                                           \r
-                               a.Emit (ec);\r
-                       }\r
-               }\r
-\r
-               /// <remarks>\r
-               ///   is_base tells whether we want to force the use of the `call'\r
-               ///   opcode instead of using callvirt.  Call is required to call\r
-               ///   a specific method, while callvirt will always use the most\r
-               ///   recent method in the vtable.\r
-               ///\r
-               ///   is_static tells whether this is an invocation on a static method\r
-               ///\r
-               ///   instance_expr is an expression that represents the instance\r
-               ///   it must be non-null if is_static is false.\r
-               ///\r
-               ///   method is the method to invoke.\r
-               ///\r
-               ///   Arguments is the list of arguments to pass to the method or constructor.\r
-               /// </remarks>\r
-               public static void EmitCall (EmitContext ec, bool is_base,\r
-                                            bool is_static, Expression instance_expr,\r
-                                            MethodBase method, ArrayList Arguments)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       bool struct_call = false;\r
-                               \r
-                       if (!is_static){\r
-                               \r
-                               if (method.DeclaringType.IsValueType)\r
-                                       struct_call = true;\r
-                               //\r
-                               // If this is ourselves, push "this"\r
-                               //\r
-                               if (instance_expr == null){\r
-                                       ig.Emit (OpCodes.Ldarg_0);\r
-                               } else {\r
-                                       //\r
-                                       // Push the instance expression\r
-                                       //\r
-                                       if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){\r
-                                               //\r
-                                               // Special case: calls to a function declared in a \r
-                                               // reference-type with a value-type argument need\r
-                                               // to have their value boxed.  \r
-\r
-                                               struct_call = true;\r
-                                               if (method.DeclaringType.IsValueType){\r
-                                                       //\r
-                                                       // If the expression implements IMemoryLocation, then\r
-                                                       // we can optimize and use AddressOf on the\r
-                                                       // return.\r
-                                                       //\r
-                                                       // If not we have to use some temporary storage for\r
-                                                       // it.\r
-                                                       if (instance_expr is IMemoryLocation){\r
-                                                               ((IMemoryLocation)instance_expr).\r
-                                                                       AddressOf (ec, AddressOp.LoadStore);\r
-                                                       }\r
-                                                       else {\r
-                                                               Type t = instance_expr.Type;\r
-                                                               \r
-                                                               instance_expr.Emit (ec);\r
-                                                               LocalBuilder temp = ig.DeclareLocal (t);\r
-                                                               ig.Emit (OpCodes.Stloc, temp);\r
-                                                               ig.Emit (OpCodes.Ldloca, temp);\r
-                                                       }\r
-                                               } else {\r
-                                                       instance_expr.Emit (ec);\r
-                                                       ig.Emit (OpCodes.Box, instance_expr.Type);\r
-                                               } \r
-                                       } else\r
-                                               instance_expr.Emit (ec);\r
-                               }\r
-                       }\r
-\r
-                       if (Arguments != null)\r
-                               EmitArguments (ec, method, Arguments);\r
-\r
-                       if (is_static || struct_call || is_base){\r
-                               if (method is MethodInfo)\r
-                                       ig.Emit (OpCodes.Call, (MethodInfo) method);\r
-                               else\r
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);\r
-                       } else {\r
-                               if (method is MethodInfo)\r
-                                       ig.Emit (OpCodes.Callvirt, (MethodInfo) method);\r
-                               else\r
-                                       ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);\r
-                       }\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       MethodGroupExpr mg = (MethodGroupExpr) this.expr;\r
-\r
-                       EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments);\r
-               }\r
-               \r
-               public override void EmitStatement (EmitContext ec)\r
-               {\r
-                       Emit (ec);\r
-\r
-                       // \r
-                       // Pop the return value if there is one\r
-                       //\r
-                       if (method is MethodInfo){\r
-                               if (((MethodInfo)method).ReturnType != TypeManager.void_type)\r
-                                       ec.ig.Emit (OpCodes.Pop);\r
-                       }\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///    Implements the new expression \r
-       /// </summary>\r
-       public class New : ExpressionStatement {\r
-               public readonly ArrayList Arguments;\r
-               public readonly string    RequestedType;\r
-\r
-               Location loc;\r
-               MethodBase method = null;\r
-\r
-               //\r
-               // If set, the new expression is for a value_target, and\r
-               // we will not leave anything on the stack.\r
-               //\r
-               Expression value_target;\r
-               \r
-               public New (string requested_type, ArrayList arguments, Location l)\r
-               {\r
-                       RequestedType = requested_type;\r
-                       Arguments = arguments;\r
-                       loc = l;\r
-               }\r
-\r
-               public Expression ValueTypeVariable {\r
-                       get {\r
-                               return value_target;\r
-                       }\r
-\r
-                       set {\r
-                               value_target = value;\r
-                       }\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       type = RootContext.LookupType (ec.DeclSpace, RequestedType, false, loc);\r
-                       \r
-                       if (type == null)\r
-                               return null;\r
-                       \r
-                       bool IsDelegate = TypeManager.IsDelegateType (type);\r
-                       \r
-                       if (IsDelegate)\r
-                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);\r
-                       \r
-                       bool is_struct = false;\r
-                       is_struct = type.IsSubclassOf (TypeManager.value_type);\r
-                       eclass = ExprClass.Value;\r
-\r
-                       //\r
-                       // SRE returns a match for .ctor () on structs (the object constructor), \r
-                       // so we have to manually ignore it.\r
-                       //\r
-                       if (is_struct && Arguments == null)\r
-                               return this;\r
-                       \r
-                       Expression ml;\r
-                       ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, AllBindingFlags, loc);\r
-                       \r
-                       if (! (ml is MethodGroupExpr)){\r
-                               if (!is_struct){\r
-                                       report118 (loc, ml, "method group");\r
-                                       return null;\r
-                               }\r
-                       }\r
-                       \r
-                       if (ml != null) {\r
-                               if (Arguments != null){\r
-                                       for (int i = Arguments.Count; i > 0;){\r
-                                               --i;\r
-                                               Argument a = (Argument) Arguments [i];\r
-                                               \r
-                                               if (!a.Resolve (ec, loc))\r
-                                                       return null;\r
-                                       }\r
-                               }\r
-\r
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,\r
-                                                                    Arguments, loc);\r
-                               \r
-                       }\r
-                       \r
-                       if (method == null && !is_struct) {\r
-                               Error (-6, loc,\r
-                                      "New invocation: Can not find a constructor for " +\r
-                                      "this argument list");\r
-                               return null;\r
-                       }\r
-                       return this;\r
-               }\r
-\r
-               //\r
-               // This DoEmit can be invoked in two contexts:\r
-               //    * As a mechanism that will leave a value on the stack (new object)\r
-               //    * As one that wont (init struct)\r
-               //\r
-               // You can control whether a value is required on the stack by passing\r
-               // need_value_on_stack.  The code *might* leave a value on the stack\r
-               // so it must be popped manually\r
-               //\r
-               // If we are dealing with a ValueType, we have a few\r
-               // situations to deal with:\r
-               //\r
-               //    * The target is a ValueType, and we have been provided\r
-               //      the instance (this is easy, we are being assigned).\r
-               //\r
-               //    * The target of New is being passed as an argument,\r
-               //      to a boxing operation or a function that takes a\r
-               //      ValueType.\r
-               //\r
-               //      In this case, we need to create a temporary variable\r
-               //      that is the argument of New.\r
-               //\r
-               // Returns whether a value is left on the stack\r
-               //\r
-               bool DoEmit (EmitContext ec, bool need_value_on_stack)\r
-               {\r
-                       bool is_value_type = type.IsSubclassOf (TypeManager.value_type);\r
-                       ILGenerator ig = ec.ig;\r
-                       \r
-                       if (is_value_type){\r
-                               IMemoryLocation ml;\r
-\r
-                               if (value_target == null)\r
-                                       value_target = new LocalTemporary (ec, type);\r
-\r
-                               ml = (IMemoryLocation) value_target;\r
-                               ml.AddressOf (ec, AddressOp.Store);\r
-                       }\r
-\r
-                       if (method != null)\r
-                               Invocation.EmitArguments (ec, method, Arguments);\r
-\r
-                       if (is_value_type){\r
-                               if (method == null)\r
-                                       ig.Emit (OpCodes.Initobj, type);\r
-                               else\r
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);\r
-\r
-                               if (need_value_on_stack){\r
-                                       value_target.Emit (ec);\r
-                                       return true;\r
-                               }\r
-                               return false;\r
-                       } else {\r
-                               ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       DoEmit (ec, true);\r
-               }\r
-               \r
-               public override void EmitStatement (EmitContext ec)\r
-               {\r
-                       if (DoEmit (ec, false))\r
-                               ec.ig.Emit (OpCodes.Pop);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Represents an array creation expression.\r
-       /// </summary>\r
-       ///\r
-       /// <remarks>\r
-       ///   There are two possible scenarios here: one is an array creation\r
-       ///   expression that specifies the dimensions and optionally the\r
-       ///   initialization data and the other which does not need dimensions\r
-       ///   specified but where initialization data is mandatory.\r
-       /// </remarks>\r
-       public class ArrayCreation : ExpressionStatement {\r
-               string RequestedType;\r
-               string Rank;\r
-               ArrayList Initializers;\r
-               Location  loc;\r
-\r
-               //\r
-               // The list of Argument types.\r
-               // This is used to constrcut the `newarray' or constructor signature\r
-               //\r
-               ArrayList Arguments;\r
-\r
-               MethodBase method = null;\r
-               Type array_element_type;\r
-               bool IsOneDimensional = false;\r
-               bool IsBuiltinType = false;\r
-               bool ExpectInitializers = false;\r
-\r
-               int dimensions = 0;\r
-               Type underlying_type;\r
-\r
-               ArrayList ArrayData;\r
-\r
-               Hashtable Bounds;\r
-\r
-               //\r
-               // The number of array initializers that we can handle\r
-               // via the InitializeArray method - through EmitStaticInitializers\r
-               //\r
-               int num_automatic_initializers;\r
-               \r
-               public ArrayCreation (string requested_type, ArrayList exprs,\r
-                                     string rank, ArrayList initializers, Location l)\r
-               {\r
-                       RequestedType = requested_type;\r
-                       Rank          = rank;\r
-                       Initializers  = initializers;\r
-                       loc = l;\r
-\r
-                       Arguments = new ArrayList ();\r
-\r
-                       foreach (Expression e in exprs)\r
-                               Arguments.Add (new Argument (e, Argument.AType.Expression));\r
-               }\r
-\r
-               public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)\r
-               {\r
-                       RequestedType = requested_type;\r
-                       Initializers = initializers;\r
-                       loc = l;\r
-\r
-                       Rank = rank.Substring (0, rank.LastIndexOf ("["));\r
-\r
-                       string tmp = rank.Substring (rank.LastIndexOf ("["));\r
-\r
-                       dimensions = tmp.Length - 1;\r
-                       ExpectInitializers = true;\r
-               }\r
-\r
-               public static string FormArrayType (string base_type, int idx_count, string rank)\r
-               {\r
-                       StringBuilder sb = new StringBuilder (base_type);\r
-\r
-                       sb.Append (rank);\r
-                       \r
-                       sb.Append ("[");\r
-                       for (int i = 1; i < idx_count; i++)\r
-                               sb.Append (",");\r
-                       \r
-                       sb.Append ("]");\r
-\r
-                       return sb.ToString ();\r
-                }\r
-\r
-               public static string FormElementType (string base_type, int idx_count, string rank)\r
-               {\r
-                       StringBuilder sb = new StringBuilder (base_type);\r
-                       \r
-                       sb.Append ("[");\r
-                       for (int i = 1; i < idx_count; i++)\r
-                               sb.Append (",");\r
-                       \r
-                       sb.Append ("]");\r
-                       \r
-                       sb.Append (rank);\r
-\r
-                       string val = sb.ToString ();\r
-\r
-                       return val.Substring (0, val.LastIndexOf ("["));\r
-               }\r
-\r
-               void error178 ()\r
-               {\r
-                       Report.Error (178, loc, "Incorrectly structured array initializer");\r
-               }\r
-               \r
-               public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)\r
-               {\r
-                       if (specified_dims) { \r
-                               Argument a = (Argument) Arguments [idx];\r
-                               \r
-                               if (!a.Resolve (ec, loc))\r
-                                       return false;\r
-                               \r
-                               if (!(a.Expr is Constant)) {\r
-                                       Report.Error (150, loc, "A constant value is expected");\r
-                                       return false;\r
-                               }\r
-                               \r
-                               int value = (int) ((Constant) a.Expr).GetValue ();\r
-                               \r
-                               if (value != probe.Count) {\r
-                                       error178 ();\r
-                                       return false;\r
-                               }\r
-                               \r
-                               Bounds [idx] = value;\r
-                       }\r
-                       \r
-                       foreach (object o in probe) {\r
-                               if (o is ArrayList) {\r
-                                       bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);\r
-                                       if (!ret)\r
-                                               return false;\r
-                               } else {\r
-                                       Expression tmp = (Expression) o;\r
-                                       tmp = tmp.Resolve (ec);\r
-                                       if (tmp == null)\r
-                                               continue;\r
-                                       \r
-                                       // Handle initialization from vars, fields etc.\r
-\r
-                                       Expression conv = ConvertImplicitRequired (\r
-                                               ec, tmp, underlying_type, loc);\r
-                                       \r
-                                       if (conv == null) \r
-                                               return false;\r
-\r
-                                       if (conv is StringConstant)\r
-                                               ArrayData.Add (conv);\r
-                                       else if (conv is Constant) {\r
-                                               ArrayData.Add (conv);\r
-                                               num_automatic_initializers++;\r
-                                       } else\r
-                                               ArrayData.Add (conv);\r
-                               }\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-               \r
-               public void UpdateIndices (EmitContext ec)\r
-               {\r
-                       int i = 0;\r
-                       for (ArrayList probe = Initializers; probe != null;) {\r
-                               if (probe.Count > 0 && probe [0] is ArrayList) {\r
-                                       Expression e = new IntConstant (probe.Count);\r
-                                       Arguments.Add (new Argument (e, Argument.AType.Expression));\r
-\r
-                                       Bounds [i++] =  probe.Count;\r
-                                       \r
-                                       probe = (ArrayList) probe [0];\r
-                                       \r
-                               } else {\r
-                                       Expression e = new IntConstant (probe.Count);\r
-                                       Arguments.Add (new Argument (e, Argument.AType.Expression));\r
-\r
-                                       Bounds [i++] = probe.Count;\r
-                                       probe = null;\r
-                               }\r
-                       }\r
-\r
-               }\r
-               \r
-               public bool ValidateInitializers (EmitContext ec)\r
-               {\r
-                       if (Initializers == null) {\r
-                               if (ExpectInitializers)\r
-                                       return false;\r
-                               else\r
-                                       return true;\r
-                       }\r
-                       \r
-                       underlying_type = RootContext.LookupType (\r
-                               ec.DeclSpace, RequestedType, false, loc);\r
-                       \r
-                       //\r
-                       // We use this to store all the date values in the order in which we\r
-                       // will need to store them in the byte blob later\r
-                       //\r
-                       ArrayData = new ArrayList ();\r
-                       Bounds = new Hashtable ();\r
-                       \r
-                       bool ret;\r
-\r
-                       if (Arguments != null) {\r
-                               ret = CheckIndices (ec, Initializers, 0, true);\r
-                               return ret;\r
-                               \r
-                       } else {\r
-                               Arguments = new ArrayList ();\r
-\r
-                               ret = CheckIndices (ec, Initializers, 0, false);\r
-                               \r
-                               if (!ret)\r
-                                       return false;\r
-                               \r
-                               UpdateIndices (ec);\r
-                               \r
-                               if (Arguments.Count != dimensions) {\r
-                                       error178 ();\r
-                                       return false;\r
-                               }\r
-\r
-                               return ret;\r
-                       }\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       int arg_count;\r
-\r
-                       //\r
-                       // First step is to validate the initializers and fill\r
-                       // in any missing bits\r
-                       //\r
-                       if (!ValidateInitializers (ec))\r
-                               return null;\r
-\r
-                       if (Arguments == null)\r
-                               arg_count = 0;\r
-                       else {\r
-                               arg_count = Arguments.Count;\r
-                               for (int i = 0; i < arg_count; i++){\r
-                                       Argument a = (Argument) Arguments [i];\r
-                                       \r
-                                       if (!a.Resolve (ec, loc))\r
-                                               return null;\r
-\r
-                                       //\r
-                                       // Now, convert that to an integer\r
-                                       //\r
-                                       Expression real_arg;\r
-                                       bool old_checked = ec.CheckState;\r
-                                       ec.CheckState = true;\r
-                       \r
-                                       real_arg = ConvertExplicit (\r
-                                               ec, a.expr, TypeManager.uint32_type, loc);\r
-                                       ec.CheckState = old_checked;\r
-                                       if (real_arg == null)\r
-                                               return null;\r
-\r
-                                       a.expr = real_arg;\r
-                               }\r
-                       }\r
-                       \r
-                       string array_type = FormArrayType (RequestedType, arg_count, Rank);\r
-                       string element_type = FormElementType (RequestedType, arg_count, Rank);\r
-\r
-                       type = RootContext.LookupType (ec.DeclSpace, array_type, false, loc);\r
-                       \r
-                       array_element_type = RootContext.LookupType (\r
-                               ec.DeclSpace, element_type, false, loc);\r
-                       \r
-                       if (type == null)\r
-                               return null;\r
-                       \r
-                       if (arg_count == 1) {\r
-                               IsOneDimensional = true;\r
-                               eclass = ExprClass.Value;\r
-                               return this;\r
-                       }\r
-\r
-                       IsBuiltinType = TypeManager.IsBuiltinType (type);\r
-                       \r
-                       if (IsBuiltinType) {\r
-\r
-                               Expression ml;\r
-                               \r
-                               ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,\r
-                                                  AllBindingFlags, loc);\r
-                               \r
-                               if (!(ml is MethodGroupExpr)){\r
-                                       report118 (loc, ml, "method group");\r
-                                       return null;\r
-                               }\r
-                               \r
-                               if (ml == null) {\r
-                                       Report.Error (-6, loc, "New invocation: Can not find a constructor for " +\r
-                                                     "this argument list");\r
-                                       return null;\r
-                               }\r
-                               \r
-                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);\r
-\r
-                               if (method == null) {\r
-                                       Report.Error (-6, loc, "New invocation: Can not find a constructor for " +\r
-                                                     "this argument list");\r
-                                       return null;\r
-                               }\r
-                               \r
-                               eclass = ExprClass.Value;\r
-                               return this;\r
-                               \r
-                       } else {\r
-\r
-                               ModuleBuilder mb = RootContext.ModuleBuilder;\r
-\r
-                               ArrayList args = new ArrayList ();\r
-                               if (Arguments != null){\r
-                                       for (int i = arg_count; i > 0;){\r
-                                               --i;\r
-                                               Argument a = (Argument) Arguments [i];\r
-                                               \r
-                                               args.Add (TypeManager.int32_type);\r
-                                       }\r
-                               }\r
-                               \r
-                               Type [] arg_types = null;\r
-\r
-                               if (args.Count > 0)\r
-                                       arg_types = new Type [args.Count];\r
-                               \r
-                               args.CopyTo (arg_types, 0);\r
-                               \r
-                               method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,\r
-                                                           arg_types);\r
-\r
-                               if (method == null) {\r
-                                       Report.Error (-6, loc, "New invocation: Can not find a constructor for " +\r
-                                                     "this argument list");\r
-                                       return null;\r
-                               }\r
-                               \r
-                               eclass = ExprClass.Value;\r
-                               return this;\r
-                               \r
-                       }\r
-               }\r
-\r
-               public static byte [] MakeByteBlob (ArrayList ArrayData, Type underlying_type, Location loc)\r
-               {\r
-                       int factor;\r
-                       byte [] data;\r
-                       byte [] element;\r
-                       int count = ArrayData.Count;\r
-\r
-                       factor = GetTypeSize (underlying_type);\r
-                       if (factor == 0)\r
-                               return null;\r
-\r
-                       data = new byte [(count * factor + 4) & ~3];\r
-                       int idx = 0;\r
-                       \r
-                       for (int i = 0; i < count; ++i) {\r
-                               object v = ArrayData [i];\r
-\r
-                               if (v is EnumConstant)\r
-                                       v = ((EnumConstant) v).Child;\r
-                               \r
-                               if (v is Constant && !(v is StringConstant))\r
-                                       v = ((Constant) v).GetValue ();\r
-                               else {\r
-                                       idx += factor;\r
-                                       continue;\r
-                               }\r
-                               \r
-                               if (underlying_type == TypeManager.int64_type){\r
-                                       if (!(v is Expression)){\r
-                                               long val = (long) v;\r
-                                               \r
-                                               for (int j = 0; j < factor; ++j) {\r
-                                                       data [idx + j] = (byte) (val & 0xFF);\r
-                                                       val = (val >> 8);\r
-                                               }\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.uint64_type){\r
-                                       if (!(v is Expression)){\r
-                                               ulong val = (ulong) v;\r
-\r
-                                               for (int j = 0; j < factor; ++j) {\r
-                                                       data [idx + j] = (byte) (val & 0xFF);\r
-                                                       val = (val >> 8);\r
-                                               }\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.float_type) {\r
-                                       if (!(v is Expression)){\r
-                                               element = BitConverter.GetBytes ((float) v);\r
-                                                       \r
-                                               for (int j = 0; j < factor; ++j)\r
-                                                       data [idx + j] = element [j];\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.double_type) {\r
-                                       if (!(v is Expression)){\r
-                                               element = BitConverter.GetBytes ((double) v);\r
-\r
-                                               for (int j = 0; j < factor; ++j)\r
-                                                       data [idx + j] = element [j];\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.char_type){\r
-                                       if (!(v is Expression)){\r
-                                               int val = (int) ((char) v);\r
-                                               \r
-                                               data [idx] = (byte) (val & 0xff);\r
-                                               data [idx+1] = (byte) (val >> 8);\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.short_type){\r
-                                       if (!(v is Expression)){\r
-                                               int val = (int) ((short) v);\r
-                                       \r
-                                               data [idx] = (byte) (val & 0xff);\r
-                                               data [idx+1] = (byte) (val >> 8);\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.ushort_type){\r
-                                       if (!(v is Expression)){\r
-                                               int val = (int) ((ushort) v);\r
-                                       \r
-                                               data [idx] = (byte) (val & 0xff);\r
-                                               data [idx+1] = (byte) (val >> 8);\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.int32_type) {\r
-                                       if (!(v is Expression)){\r
-                                               int val = (int) v;\r
-                                       \r
-                                               data [idx]   = (byte) (val & 0xff);\r
-                                               data [idx+1] = (byte) ((val >> 8) & 0xff);\r
-                                               data [idx+2] = (byte) ((val >> 16) & 0xff);\r
-                                               data [idx+3] = (byte) (val >> 24);\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.uint32_type) {\r
-                                       if (!(v is Expression)){\r
-                                               uint val = (uint) v;\r
-                                       \r
-                                               data [idx]   = (byte) (val & 0xff);\r
-                                               data [idx+1] = (byte) ((val >> 8) & 0xff);\r
-                                               data [idx+2] = (byte) ((val >> 16) & 0xff);\r
-                                               data [idx+3] = (byte) (val >> 24);\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.sbyte_type) {\r
-                                       if (!(v is Expression)){\r
-                                               sbyte val = (sbyte) v;\r
-                                               data [idx] = (byte) val;\r
-                                       }\r
-                               } else if (underlying_type == TypeManager.byte_type) {\r
-                                       if (!(v is Expression)){\r
-                                               byte val = (byte) v;\r
-                                               data [idx] = (byte) val;\r
-                                       }\r
-                               } else\r
-                                       throw new Exception ("Unrecognized type in MakeByteBlob");\r
-\r
-                                idx += factor;\r
-                       }\r
-\r
-                       return data;\r
-               }\r
-\r
-               //\r
-               // Emits the initializers for the array\r
-               //\r
-               void EmitStaticInitializers (EmitContext ec, bool is_expression)\r
-               {\r
-                       //\r
-                       // First, the static data\r
-                       //\r
-                       FieldBuilder fb;\r
-                       ILGenerator ig = ec.ig;\r
-                       \r
-                       byte [] data = MakeByteBlob (ArrayData, underlying_type, loc);\r
-                       \r
-                       if (data != null) {\r
-                               fb = RootContext.MakeStaticData (data);\r
-\r
-                               if (is_expression)\r
-                                       ig.Emit (OpCodes.Dup);\r
-                               ig.Emit (OpCodes.Ldtoken, fb);\r
-                               ig.Emit (OpCodes.Call,\r
-                                        TypeManager.void_initializearray_array_fieldhandle);\r
-                       }\r
-               }\r
-               \r
-               //\r
-               // Emits pieces of the array that can not be computed at compile\r
-               // time (variables and string locations).\r
-               //\r
-               // This always expect the top value on the stack to be the array\r
-               //\r
-               void EmitDynamicInitializers (EmitContext ec, bool is_expression)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       int dims = Bounds.Count;\r
-                       int [] current_pos = new int [dims];\r
-                       int top = ArrayData.Count;\r
-                       LocalBuilder temp = ig.DeclareLocal (type);\r
-\r
-                       ig.Emit (OpCodes.Stloc, temp);\r
-\r
-                       MethodInfo set = null;\r
-\r
-                       if (dims != 1){\r
-                               Type [] args;\r
-                               ModuleBuilder mb = null;\r
-                               mb = RootContext.ModuleBuilder;\r
-                               args = new Type [dims + 1];\r
-\r
-                               int j;\r
-                               for (j = 0; j < dims; j++)\r
-                                       args [j] = TypeManager.int32_type;\r
-\r
-                               args [j] = array_element_type;\r
-                               \r
-                               set = mb.GetArrayMethod (\r
-                                       type, "Set",\r
-                                       CallingConventions.HasThis | CallingConventions.Standard,\r
-                                       TypeManager.void_type, args);\r
-                       }\r
-                       \r
-                       for (int i = 0; i < top; i++){\r
-\r
-                               Expression e = null;\r
-\r
-                               if (ArrayData [i] is Expression)\r
-                                       e = (Expression) ArrayData [i];\r
-\r
-                               if (e != null) {\r
-                                       //\r
-                                       // Basically we do this for string literals and\r
-                                       // other non-literal expressions\r
-                                       //\r
-                                       if (e is StringConstant || !(e is Constant) || num_automatic_initializers <= 2) {\r
-\r
-                                               ig.Emit (OpCodes.Ldloc, temp);\r
-\r
-                                               for (int idx = dims; idx > 0; ) {\r
-                                                       idx--;\r
-                                                       IntConstant.EmitInt (ig, current_pos [idx]);\r
-                                               }\r
-\r
-                                               e.Emit (ec);\r
-                                               \r
-                                               if (dims == 1)\r
-                                                       ArrayAccess.EmitStoreOpcode (ig, array_element_type);\r
-                                               else \r
-                                                       ig.Emit (OpCodes.Call, set);\r
-                                               \r
-                                       }\r
-                               }\r
-                               \r
-                               //\r
-                               // Advance counter\r
-                               //\r
-                               for (int j = 0; j < dims; j++){\r
-                                       current_pos [j]++;\r
-                                       if (current_pos [j] < (int) Bounds [j])\r
-                                               break;\r
-                                       current_pos [j] = 0;\r
-                               }\r
-                       }\r
-\r
-                       if (is_expression)\r
-                               ig.Emit (OpCodes.Ldloc, temp);\r
-               }\r
-\r
-               void EmitArrayArguments (EmitContext ec)\r
-               {\r
-                       foreach (Argument a in Arguments)\r
-                               a.Emit (ec);\r
-               }\r
-               \r
-               void DoEmit (EmitContext ec, bool is_statement)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       \r
-                       EmitArrayArguments (ec);\r
-                       if (IsOneDimensional)\r
-                               ig.Emit (OpCodes.Newarr, array_element_type);\r
-                       else {\r
-                               if (IsBuiltinType) \r
-                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);\r
-                               else \r
-                                       ig.Emit (OpCodes.Newobj, (MethodInfo) method);\r
-                       }\r
-                       \r
-                       if (Initializers != null){\r
-                               //\r
-                               // FIXME: Set this variable correctly.\r
-                               // \r
-                               bool dynamic_initializers = true;\r
-\r
-                               if (underlying_type != TypeManager.string_type &&\r
-                                   underlying_type != TypeManager.object_type) {\r
-                                       if (num_automatic_initializers > 2)\r
-                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);\r
-                               }\r
-                               \r
-                               if (dynamic_initializers)\r
-                                       EmitDynamicInitializers (ec, !is_statement);\r
-                       }\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       DoEmit (ec, false);\r
-               }\r
-\r
-               public override void EmitStatement (EmitContext ec)\r
-               {\r
-                       DoEmit (ec, true);\r
-               }\r
-               \r
-       }\r
-       \r
-       /// <summary>\r
-       ///   Represents the `this' construct\r
-       /// </summary>\r
-       public class This : Expression, IAssignMethod, IMemoryLocation {\r
-               Location loc;\r
-               \r
-               public This (Location loc)\r
-               {\r
-                       this.loc = loc;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       eclass = ExprClass.Variable;\r
-                       type = ec.TypeContainer.TypeBuilder;\r
-\r
-                       if (ec.IsStatic){\r
-                               Report.Error (26, loc,\r
-                                             "Keyword this not valid in static code");\r
-                               return null;\r
-                       }\r
-                       \r
-                       return this;\r
-               }\r
-\r
-               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)\r
-               {\r
-                       DoResolve (ec);\r
-                       \r
-                       if (ec.TypeContainer is Class){\r
-                               Report.Error (1604, loc, "Cannot assign to `this'");\r
-                               return null;\r
-                       }\r
-\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ec.ig.Emit (OpCodes.Ldarg_0);\r
-               }\r
-\r
-               public void EmitAssign (EmitContext ec, Expression source)\r
-               {\r
-                       source.Emit (ec);\r
-                       ec.ig.Emit (OpCodes.Starg, 0);\r
-               }\r
-\r
-               public void AddressOf (EmitContext ec, AddressOp mode)\r
-               {\r
-                       ec.ig.Emit (OpCodes.Ldarg_0);\r
-\r
-                       // FIMXE\r
-                       // FIGURE OUT WHY LDARG_S does not work\r
-                       //\r
-                       // consider: struct X { int val; int P { set { val = value; }}}\r
-                       //\r
-                       // Yes, this looks very bad. Look at `NOTAS' for\r
-                       // an explanation.\r
-                       // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implements the typeof operator\r
-       /// </summary>\r
-       public class TypeOf : Expression {\r
-               public readonly string QueriedType;\r
-               Type typearg;\r
-               Location loc;\r
-               \r
-               public TypeOf (string queried_type, Location l)\r
-               {\r
-                       QueriedType = queried_type;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       typearg = RootContext.LookupType (\r
-                               ec.DeclSpace, QueriedType, false, loc);\r
-\r
-                       if (typearg == null)\r
-                               return null;\r
-\r
-                       type = TypeManager.type_type;\r
-                       eclass = ExprClass.Type;\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ec.ig.Emit (OpCodes.Ldtoken, typearg);\r
-                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implements the sizeof expression\r
-       /// </summary>\r
-       public class SizeOf : Expression {\r
-               public readonly string QueriedType;\r
-               Type type_queried;\r
-               Location loc;\r
-               \r
-               public SizeOf (string queried_type, Location l)\r
-               {\r
-                       this.QueriedType = queried_type;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       type_queried = RootContext.LookupType (\r
-                               ec.DeclSpace, QueriedType, false, loc);\r
-                       if (type_queried == null)\r
-                               return null;\r
-\r
-                       type = TypeManager.int32_type;\r
-                       eclass = ExprClass.Value;\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       int size = GetTypeSize (type_queried);\r
-\r
-                       if (size == 0)\r
-                               ec.ig.Emit (OpCodes.Sizeof, type_queried);\r
-                       else\r
-                               IntConstant.EmitInt (ec.ig, size);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implements the member access expression\r
-       /// </summary>\r
-       public class MemberAccess : Expression {\r
-               public readonly string Identifier;\r
-               Expression expr;\r
-               Expression member_lookup;\r
-               Location loc;\r
-               \r
-               public MemberAccess (Expression expr, string id, Location l)\r
-               {\r
-                       this.expr = expr;\r
-                       Identifier = id;\r
-                       loc = l;\r
-               }\r
-\r
-               public Expression Expr {\r
-                       get {\r
-                               return expr;\r
-                       }\r
-               }\r
-\r
-               static void error176 (Location loc, string name)\r
-               {\r
-                       Report.Error (176, loc, "Static member `" +\r
-                                     name + "' cannot be accessed " +\r
-                                     "with an instance reference, qualify with a " +\r
-                                     "type name instead");\r
-               }\r
-\r
-               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)\r
-               {\r
-                       if (left_original == null)\r
-                               return false;\r
-\r
-                       if (!(left_original is SimpleName))\r
-                               return false;\r
-\r
-                       SimpleName sn = (SimpleName) left_original;\r
-\r
-                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);\r
-                       if (t != null)\r
-                               return true;\r
-\r
-                       return false;\r
-               }\r
-               \r
-               public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,\r
-                                                             Expression left, Location loc,\r
-                                                             Expression left_original)\r
-               {\r
-                       //\r
-                       // Method Groups\r
-                       //\r
-                       if (member_lookup is MethodGroupExpr){\r
-                               MethodGroupExpr mg = (MethodGroupExpr) member_lookup;\r
-\r
-                               //\r
-                               // Type.MethodGroup\r
-                               //\r
-                               if (left is TypeExpr){\r
-                                       if (!mg.RemoveInstanceMethods ()){\r
-                                               SimpleName.Error120 (loc, mg.Methods [0].Name); \r
-                                               return null;\r
-                                       }\r
-\r
-                                       return member_lookup;\r
-                               }\r
-\r
-                               //\r
-                               // Instance.MethodGroup\r
-                               //\r
-                               if (IdenticalNameAndTypeName (ec, left_original, loc)){\r
-                                       if (mg.RemoveInstanceMethods ())\r
-                                               return member_lookup;\r
-                               }\r
-                               \r
-                               if (!mg.RemoveStaticMethods ()){\r
-                                       error176 (loc, mg.Methods [0].Name);\r
-                                       return null;\r
-                               } \r
-                               \r
-                               mg.InstanceExpression = left;\r
-                               return member_lookup;\r
-#if ORIGINAL\r
-                               if (!mg.RemoveStaticMethods ()){\r
-                                       if (IdenticalNameAndTypeName (ec, left_original, loc)){\r
-                                               if (!mg.RemoveInstanceMethods ()){\r
-                                                       SimpleName.Error120 (loc, mg.Methods [0].Name);\r
-                                                       return null;\r
-                                               }\r
-                                               return member_lookup;\r
-                                       }\r
-                                       \r
-                                       error176 (loc, mg.Methods [0].Name);\r
-                                       return null;\r
-                               }\r
-                               \r
-                               mg.InstanceExpression = left;\r
-                                       \r
-                               return member_lookup;\r
-#endif\r
-                       }\r
-\r
-                       if (member_lookup is FieldExpr){\r
-                               FieldExpr fe = (FieldExpr) member_lookup;\r
-                               FieldInfo fi = fe.FieldInfo;\r
-\r
-                               if (fi is FieldBuilder) {\r
-                                       Const c = TypeManager.LookupConstant ((FieldBuilder) fi);\r
-                                       \r
-                                       if (c != null) {\r
-                                               object o = c.LookupConstantValue (ec);\r
-                                               object real_value = ((Constant) c.Expr).GetValue ();\r
-\r
-                                               return Constantify (real_value, fi.FieldType);\r
-                                       }\r
-                               }\r
-\r
-                               if (fi.IsLiteral) {\r
-                                       Type t = fi.FieldType;\r
-                                       Type decl_type = fi.DeclaringType;\r
-                                       object o;\r
-\r
-                                       if (fi is FieldBuilder)\r
-                                               o = TypeManager.GetValue ((FieldBuilder) fi);\r
-                                       else\r
-                                               o = fi.GetValue (fi);\r
-                                       \r
-                                       if (decl_type.IsSubclassOf (TypeManager.enum_type)) {\r
-                                               Expression enum_member = MemberLookup (\r
-                                                       ec, decl_type, "value__", MemberTypes.Field,\r
-                                                       AllBindingFlags, loc); \r
-\r
-                                               Enum en = TypeManager.LookupEnum (decl_type);\r
-\r
-                                               Constant c;\r
-                                               if (en != null)\r
-                                                       c = Constantify (o, en.UnderlyingType);\r
-                                               else \r
-                                                       c = Constantify (o, enum_member.Type);\r
-                                               \r
-                                               return new EnumConstant (c, decl_type);\r
-                                       }\r
-                                       \r
-                                       Expression exp = Constantify (o, t);\r
-\r
-                                       if (!(left is TypeExpr)) {\r
-                                               error176 (loc, fe.FieldInfo.Name);\r
-                                               return null;\r
-                                       }\r
-                                       \r
-                                       return exp;\r
-                               }\r
-\r
-                               if (fi.FieldType.IsPointer && !ec.InUnsafe){\r
-                                       UnsafeError (loc);\r
-                                       return null;\r
-                               }\r
-                               \r
-                               if (left is TypeExpr){\r
-                                       // and refers to a type name or an \r
-                                       if (!fe.FieldInfo.IsStatic){\r
-                                               error176 (loc, fe.FieldInfo.Name);\r
-                                               return null;\r
-                                       }\r
-                                       return member_lookup;\r
-                               } else {\r
-                                       if (fe.FieldInfo.IsStatic){\r
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))\r
-                                                       return member_lookup;\r
-\r
-                                               error176 (loc, fe.FieldInfo.Name);\r
-                                               return null;\r
-                                       }\r
-                                       fe.InstanceExpression = left;\r
-\r
-                                       return fe;\r
-                               }\r
-                       }\r
-\r
-                       if (member_lookup is PropertyExpr){\r
-                               PropertyExpr pe = (PropertyExpr) member_lookup;\r
-\r
-                               if (left is TypeExpr){\r
-                                       if (!pe.IsStatic){\r
-                                               SimpleName.Error120 (loc, pe.PropertyInfo.Name);\r
-                                               return null;\r
-                                       }\r
-                                       return pe;\r
-                               } else {\r
-                                       if (pe.IsStatic){\r
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))\r
-                                                       return member_lookup;\r
-                                               error176 (loc, pe.PropertyInfo.Name);\r
-                                               return null;\r
-                                       }\r
-                                       pe.InstanceExpression = left;\r
-                                       \r
-                                       return pe;\r
-                               }\r
-                       }\r
-\r
-                       if (member_lookup is EventExpr) {\r
-\r
-                               EventExpr ee = (EventExpr) member_lookup;\r
-                               \r
-                               //\r
-                               // If the event is local to this class, we transform ourselves into\r
-                               // a FieldExpr\r
-                               //\r
-\r
-                               Expression ml = MemberLookup (\r
-                                       ec, ec.TypeContainer.TypeBuilder,\r
-                                       ee.EventInfo.Name, MemberTypes.Event, AllBindingFlags, loc);\r
-\r
-                               if (ml != null) {\r
-                                       MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);\r
-\r
-                                       if (mi == null) {\r
-                                               //\r
-                                               // If this happens, then we have an event with its own\r
-                                               // accessors and private field etc so there's no need\r
-                                               // to transform ourselves : we should instead flag an error\r
-                                               //\r
-                                               Assign.error70 (ee.EventInfo, loc);\r
-                                               return null;\r
-                                       }\r
-\r
-                                       ml = ExprClassFromMemberInfo (ec, mi, loc);\r
-                                       \r
-                                       if (ml == null) {\r
-                                               Report.Error (-200, loc, "Internal error!!");\r
-                                               return null;\r
-                                       }\r
-                                       return ResolveMemberAccess (ec, ml, left, loc, left_original);\r
-                               }\r
-\r
-                               if (left is TypeExpr) {\r
-                                       if (!ee.IsStatic) {\r
-                                               SimpleName.Error120 (loc, ee.EventInfo.Name);\r
-                                               return null;\r
-                                       }\r
-\r
-                                       return ee;\r
-\r
-                               } else {\r
-                                       if (ee.IsStatic) {\r
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))\r
-                                                       return ee;\r
-                                                   \r
-                                               error176 (loc, ee.EventInfo.Name);\r
-                                               return null;\r
-                                       }\r
-\r
-                                       ee.InstanceExpression = left;\r
-\r
-                                       return ee;\r
-                               }\r
-                       }\r
-\r
-                       if (member_lookup is TypeExpr){\r
-                               member_lookup.Resolve (ec);\r
-                               return member_lookup;\r
-                       }\r
-                       \r
-                       Console.WriteLine ("Left is: " + left);\r
-                       Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");\r
-                       Environment.Exit (0);\r
-                       return null;\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // We are the sole users of ResolveWithSimpleName (ie, the only\r
-                       // ones that can cope with it\r
-                       //\r
-                       Expression original = expr;\r
-                       expr = expr.ResolveWithSimpleName (ec);\r
-\r
-                       if (expr == null)\r
-                               return null;\r
-\r
-                       if (expr is SimpleName){\r
-                               SimpleName child_expr = (SimpleName) expr;\r
-                               \r
-                               expr = new SimpleName (child_expr.Name + "." + Identifier, loc);\r
-\r
-                               return expr.ResolveWithSimpleName (ec);\r
-                       }\r
-                                       \r
-                       //\r
-                       // TODO: I mailed Ravi about this, and apparently we can get rid\r
-                       // of this and put it in the right place.\r
-                       // \r
-                       // Handle enums here when they are in transit.\r
-                       // Note that we cannot afford to hit MemberLookup in this case because\r
-                       // it will fail to find any members at all\r
-                       //\r
-\r
-                       Type expr_type = expr.Type;\r
-                       if ((expr is TypeExpr) && (expr_type.IsSubclassOf (TypeManager.enum_type))){\r
-                               \r
-                               Enum en = TypeManager.LookupEnum (expr_type);\r
-                               \r
-                               if (en != null) {\r
-                                       object value = en.LookupEnumValue (ec, Identifier, loc);\r
-\r
-                                       if (value != null){\r
-                                               Constant c = Constantify (value, en.UnderlyingType);\r
-                                               return new EnumConstant (c, expr_type);\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       if (expr_type.IsPointer){\r
-                               Report.Error (23, loc,\r
-                                             "The `.' operator can not be applied to pointer operands (" +\r
-                                             TypeManager.CSharpName (expr_type) + ")");\r
-                               return null;\r
-                       }\r
-                       \r
-                       member_lookup = MemberLookup (ec, expr_type, Identifier, loc);\r
-\r
-                       if (member_lookup == null){\r
-                               Report.Error (117, loc, "`" + expr_type + "' does not contain a " +\r
-                                             "definition for `" + Identifier + "'");\r
-                                             \r
-                               return null;\r
-                       }\r
-\r
-                       return ResolveMemberAccess (ec, member_lookup, expr, loc, original);\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       throw new Exception ("Should not happen");\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implements checked expressions\r
-       /// </summary>\r
-       public class CheckedExpr : Expression {\r
-\r
-               public Expression Expr;\r
-\r
-               public CheckedExpr (Expression e)\r
-               {\r
-                       Expr = e;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       bool last_const_check = ec.ConstantCheckState;\r
-\r
-                       ec.ConstantCheckState = true;\r
-                       Expr = Expr.Resolve (ec);\r
-                       ec.ConstantCheckState = last_const_check;\r
-                       \r
-                       if (Expr == null)\r
-                               return null;\r
-\r
-                       eclass = Expr.eclass;\r
-                       type = Expr.Type;\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       bool last_check = ec.CheckState;\r
-                       bool last_const_check = ec.ConstantCheckState;\r
-                       \r
-                       ec.CheckState = true;\r
-                       ec.ConstantCheckState = true;\r
-                       Expr.Emit (ec);\r
-                       ec.CheckState = last_check;\r
-                       ec.ConstantCheckState = last_const_check;\r
-               }\r
-               \r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implements the unchecked expression\r
-       /// </summary>\r
-       public class UnCheckedExpr : Expression {\r
-\r
-               public Expression Expr;\r
-\r
-               public UnCheckedExpr (Expression e)\r
-               {\r
-                       Expr = e;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       bool last_const_check = ec.ConstantCheckState;\r
-\r
-                       ec.ConstantCheckState = false;\r
-                       Expr = Expr.Resolve (ec);\r
-                       ec.ConstantCheckState = last_const_check;\r
-\r
-                       if (Expr == null)\r
-                               return null;\r
-\r
-                       eclass = Expr.eclass;\r
-                       type = Expr.Type;\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       bool last_check = ec.CheckState;\r
-                       bool last_const_check = ec.ConstantCheckState;\r
-                       \r
-                       ec.CheckState = false;\r
-                       ec.ConstantCheckState = false;\r
-                       Expr.Emit (ec);\r
-                       ec.CheckState = last_check;\r
-                       ec.ConstantCheckState = last_const_check;\r
-               }\r
-               \r
-       }\r
-\r
-       /// <summary>\r
-       ///   An Element Access expression.\r
-       ///\r
-       ///   During semantic analysis these are transformed into \r
-       ///   IndexerAccess or ArrayAccess \r
-       /// </summary>\r
-       public class ElementAccess : Expression {\r
-               public ArrayList  Arguments;\r
-               public Expression Expr;\r
-               public Location   loc;\r
-               \r
-               public ElementAccess (Expression e, ArrayList e_list, Location l)\r
-               {\r
-                       Expr = e;\r
-\r
-                       loc  = l;\r
-                       \r
-                       if (e_list == null)\r
-                               return;\r
-                       \r
-                       Arguments = new ArrayList ();\r
-                       foreach (Expression tmp in e_list)\r
-                               Arguments.Add (new Argument (tmp, Argument.AType.Expression));\r
-                       \r
-               }\r
-\r
-               bool CommonResolve (EmitContext ec)\r
-               {\r
-                       Expr = Expr.Resolve (ec);\r
-\r
-                       if (Expr == null) \r
-                               return false;\r
-\r
-                       if (Arguments == null)\r
-                               return false;\r
-\r
-                       for (int i = Arguments.Count; i > 0;){\r
-                               --i;\r
-                               Argument a = (Argument) Arguments [i];\r
-                               \r
-                               if (!a.Resolve (ec, loc))\r
-                                       return false;\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-               Expression MakePointerAccess ()\r
-               {\r
-                       Type t = Expr.Type;\r
-\r
-                       if (t == TypeManager.void_ptr_type){\r
-                               Report.Error (\r
-                                       242, loc,\r
-                                       "The array index operation is not valid for void pointers");\r
-                               return null;\r
-                       }\r
-                       if (Arguments.Count != 1){\r
-                               Report.Error (\r
-                                       196, loc,\r
-                                       "A pointer must be indexed by a single value");\r
-                               return null;\r
-                       }\r
-                       Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t);\r
-                       return new Indirection (p);\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       if (!CommonResolve (ec))\r
-                               return null;\r
-\r
-                       //\r
-                       // We perform some simple tests, and then to "split" the emit and store\r
-                       // code we create an instance of a different class, and return that.\r
-                       //\r
-                       // I am experimenting with this pattern.\r
-                       //\r
-                       Type t = Expr.Type;\r
-\r
-                       if (t.IsSubclassOf (TypeManager.array_type))\r
-                               return (new ArrayAccess (this)).Resolve (ec);\r
-                       else if (t.IsPointer)\r
-                               return MakePointerAccess ();\r
-                       else\r
-                               return (new IndexerAccess (this)).Resolve (ec);\r
-               }\r
-\r
-               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)\r
-               {\r
-                       if (!CommonResolve (ec))\r
-                               return null;\r
-\r
-                       Type t = Expr.Type;\r
-                       if (t.IsSubclassOf (TypeManager.array_type))\r
-                               return (new ArrayAccess (this)).ResolveLValue (ec, right_side);\r
-                       else if (t.IsPointer)\r
-                               return MakePointerAccess ();\r
-                       else\r
-                               return (new IndexerAccess (this)).ResolveLValue (ec, right_side);\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       throw new Exception ("Should never be reached");\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Implements array access \r
-       /// </summary>\r
-       public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {\r
-               //\r
-               // Points to our "data" repository\r
-               //\r
-               ElementAccess ea;\r
-               \r
-               public ArrayAccess (ElementAccess ea_data)\r
-               {\r
-                       ea = ea_data;\r
-                       eclass = ExprClass.Variable;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       if (ea.Expr.eclass != ExprClass.Variable) {\r
-                               report118 (ea.loc, ea.Expr, "variable");\r
-                               return null;\r
-                       }\r
-\r
-                       Type t = ea.Expr.Type;\r
-                       if (t.GetArrayRank () != ea.Arguments.Count){\r
-                               Report.Error (22, ea.loc,\r
-                                             "Incorrect number of indexes for array " +\r
-                                             " expected: " + t.GetArrayRank () + " got: " +\r
-                                             ea.Arguments.Count);\r
-                               return null;\r
-                       }\r
-                       type = t.GetElementType ();\r
-                       if (type.IsPointer && !ec.InUnsafe){\r
-                               UnsafeError (ea.loc);\r
-                               return null;\r
-                       }\r
-                       \r
-                       eclass = ExprClass.Variable;\r
-\r
-                       return this;\r
-               }\r
-\r
-               /// <summary>\r
-               ///    Emits the right opcode to load an object of Type `t'\r
-               ///    from an array of T\r
-               /// </summary>\r
-               static public void EmitLoadOpcode (ILGenerator ig, Type type)\r
-               {\r
-                       if (type == TypeManager.byte_type || type == TypeManager.bool_type)\r
-                               ig.Emit (OpCodes.Ldelem_I1);\r
-                       else if (type == TypeManager.sbyte_type)\r
-                               ig.Emit (OpCodes.Ldelem_U1);\r
-                       else if (type == TypeManager.short_type)\r
-                               ig.Emit (OpCodes.Ldelem_I2);\r
-                       else if (type == TypeManager.ushort_type)\r
-                               ig.Emit (OpCodes.Ldelem_U2);\r
-                       else if (type == TypeManager.int32_type)\r
-                               ig.Emit (OpCodes.Ldelem_I4);\r
-                       else if (type == TypeManager.uint32_type)\r
-                               ig.Emit (OpCodes.Ldelem_U4);\r
-                       else if (type == TypeManager.uint64_type)\r
-                               ig.Emit (OpCodes.Ldelem_I8);\r
-                       else if (type == TypeManager.int64_type)\r
-                               ig.Emit (OpCodes.Ldelem_I8);\r
-                       else if (type == TypeManager.float_type)\r
-                               ig.Emit (OpCodes.Ldelem_R4);\r
-                       else if (type == TypeManager.double_type)\r
-                               ig.Emit (OpCodes.Ldelem_R8);\r
-                       else if (type == TypeManager.intptr_type)\r
-                               ig.Emit (OpCodes.Ldelem_I);\r
-                       else if (type.IsValueType){\r
-                               ig.Emit (OpCodes.Ldelema, type);\r
-                               ig.Emit (OpCodes.Ldobj, type);\r
-                       } else \r
-                               ig.Emit (OpCodes.Ldelem_Ref);\r
-               }\r
-\r
-               /// <summary>\r
-               ///    Emits the right opcode to store an object of Type `t'\r
-               ///    from an array of T.  \r
-               /// </summary>\r
-               static public void EmitStoreOpcode (ILGenerator ig, Type t)\r
-               {\r
-                       if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||\r
-                           t == TypeManager.bool_type)\r
-                               ig.Emit (OpCodes.Stelem_I1);\r
-                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type || t == TypeManager.char_type)\r
-                               ig.Emit (OpCodes.Stelem_I2);\r
-                       else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)\r
-                               ig.Emit (OpCodes.Stelem_I4);\r
-                       else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)\r
-                               ig.Emit (OpCodes.Stelem_I8);\r
-                       else if (t == TypeManager.float_type)\r
-                               ig.Emit (OpCodes.Stelem_R4);\r
-                       else if (t == TypeManager.double_type)\r
-                               ig.Emit (OpCodes.Stelem_R8);\r
-                       else if (t == TypeManager.intptr_type)\r
-                               ig.Emit (OpCodes.Stelem_I);\r
-                       else if (t.IsValueType)\r
-                               ig.Emit (OpCodes.Stobj, t);\r
-                       else\r
-                               ig.Emit (OpCodes.Stelem_Ref);\r
-               }\r
-\r
-               MethodInfo FetchGetMethod ()\r
-               {\r
-                       ModuleBuilder mb = RootContext.ModuleBuilder;\r
-                       int arg_count = ea.Arguments.Count;\r
-                       Type [] args = new Type [arg_count];\r
-                       MethodInfo get;\r
-                       \r
-                       for (int i = 0; i < arg_count; i++){\r
-                               //args [i++] = a.Type;\r
-                               args [i] = TypeManager.int32_type;\r
-                       }\r
-                       \r
-                       get = mb.GetArrayMethod (\r
-                               ea.Expr.Type, "Get",\r
-                               CallingConventions.HasThis |\r
-                               CallingConventions.Standard,\r
-                               type, args);\r
-                       return get;\r
-               }\r
-                               \r
-\r
-               MethodInfo FetchAddressMethod ()\r
-               {\r
-                       ModuleBuilder mb = RootContext.ModuleBuilder;\r
-                       int arg_count = ea.Arguments.Count;\r
-                       Type [] args = new Type [arg_count];\r
-                       MethodInfo address;\r
-                       string ptr_type_name;\r
-                       Type ret_type;\r
-                       \r
-                       ptr_type_name = type.FullName + "&";\r
-                       ret_type = Type.GetType (ptr_type_name);\r
-                       \r
-                       //\r
-                       // It is a type defined by the source code we are compiling\r
-                       //\r
-                       if (ret_type == null){\r
-                               ret_type = mb.GetType (ptr_type_name);\r
-                       }\r
-\r
-                       for (int i = 0; i < arg_count; i++){\r
-                               //args [i++] = a.Type;\r
-                               args [i] = TypeManager.int32_type;\r
-                       }\r
-                       \r
-                       address = mb.GetArrayMethod (\r
-                               ea.Expr.Type, "Address",\r
-                               CallingConventions.HasThis |\r
-                               CallingConventions.Standard,\r
-                               ret_type, args);\r
-\r
-                       return address;\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       int rank = ea.Expr.Type.GetArrayRank ();\r
-                       ILGenerator ig = ec.ig;\r
-\r
-                       ea.Expr.Emit (ec);\r
-\r
-                       foreach (Argument a in ea.Arguments)\r
-                               a.Expr.Emit (ec);\r
-\r
-                       if (rank == 1)\r
-                               EmitLoadOpcode (ig, type);\r
-                       else {\r
-                               MethodInfo method;\r
-                               \r
-                               method = FetchGetMethod ();\r
-                               ig.Emit (OpCodes.Call, method);\r
-                       }\r
-               }\r
-\r
-               public void EmitAssign (EmitContext ec, Expression source)\r
-               {\r
-                       int rank = ea.Expr.Type.GetArrayRank ();\r
-                       ILGenerator ig = ec.ig;\r
-\r
-                       ea.Expr.Emit (ec);\r
-\r
-                       foreach (Argument a in ea.Arguments)\r
-                               a.Expr.Emit (ec);\r
-\r
-                       Type t = source.Type;\r
-\r
-                       //\r
-                       // The stobj opcode used by value types will need\r
-                       // an address on the stack, not really an array/array\r
-                       // pair\r
-                       //\r
-                       if (rank == 1){\r
-                               if (t.IsValueType && !TypeManager.IsBuiltinType (t))\r
-                                       ig.Emit (OpCodes.Ldelema, t);\r
-                       }\r
-                       \r
-                       source.Emit (ec);\r
-\r
-                       if (rank == 1)\r
-                               EmitStoreOpcode (ig, t);\r
-                       else {\r
-                               ModuleBuilder mb = RootContext.ModuleBuilder;\r
-                               int arg_count = ea.Arguments.Count;\r
-                               Type [] args = new Type [arg_count + 1];\r
-                               MethodInfo set;\r
-                               \r
-                               for (int i = 0; i < arg_count; i++){\r
-                                       //args [i++] = a.Type;\r
-                                       args [i] = TypeManager.int32_type;\r
-                               }\r
-\r
-                               args [arg_count] = type;\r
-                               \r
-                               set = mb.GetArrayMethod (\r
-                                       ea.Expr.Type, "Set",\r
-                                       CallingConventions.HasThis |\r
-                                       CallingConventions.Standard,\r
-                                       TypeManager.void_type, args);\r
-                               \r
-                               ig.Emit (OpCodes.Call, set);\r
-                       }\r
-               }\r
-\r
-               public void AddressOf (EmitContext ec, AddressOp mode)\r
-               {\r
-                       int rank = ea.Expr.Type.GetArrayRank ();\r
-                       ILGenerator ig = ec.ig;\r
-                       \r
-                       ea.Expr.Emit (ec);\r
-\r
-                       foreach (Argument a in ea.Arguments)\r
-                               a.Expr.Emit (ec);\r
-\r
-                       if (rank == 1){\r
-                               ig.Emit (OpCodes.Ldelema, type);\r
-                       } else {\r
-                               MethodInfo address = FetchAddressMethod ();\r
-                               ig.Emit (OpCodes.Call, address);\r
-                       }\r
-               }\r
-       }\r
-\r
-       \r
-       class Indexers {\r
-               public ArrayList getters, setters;\r
-               static Hashtable map;\r
-\r
-               static Indexers ()\r
-               {\r
-                       map = new Hashtable ();\r
-               }\r
-\r
-               Indexers (MemberInfo [] mi)\r
-               {\r
-                       foreach (PropertyInfo property in mi){\r
-                               MethodInfo get, set;\r
-                               \r
-                               get = property.GetGetMethod (true);\r
-                               if (get != null){\r
-                                       if (getters == null)\r
-                                               getters = new ArrayList ();\r
-\r
-                                       getters.Add (get);\r
-                               }\r
-                               \r
-                               set = property.GetSetMethod (true);\r
-                               if (set != null){\r
-                                       if (setters == null)\r
-                                               setters = new ArrayList ();\r
-                                       setters.Add (set);\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               static public Indexers GetIndexersForType (Type t, TypeManager tm, Location loc) \r
-               {\r
-                       Indexers ix = (Indexers) map [t];\r
-                       string p_name = TypeManager.IndexerPropertyName (t);\r
-                       \r
-                       if (ix != null)\r
-                               return ix;\r
-\r
-                       MemberInfo [] mi = tm.FindMembers (\r
-                               t, MemberTypes.Property,\r
-                               BindingFlags.Public | BindingFlags.Instance,\r
-                               Type.FilterName, p_name);\r
-\r
-                       if (mi == null || mi.Length == 0){\r
-                               Report.Error (21, loc,\r
-                                             "Type `" + TypeManager.CSharpName (t) + "' does not have " +\r
-                                             "any indexers defined");\r
-                               return null;\r
-                       }\r
-                       \r
-                       ix = new Indexers (mi);\r
-                       map [t] = ix;\r
-\r
-                       return ix;\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   Expressions that represent an indexer call.\r
-       /// </summary>\r
-       public class IndexerAccess : Expression, IAssignMethod {\r
-               //\r
-               // Points to our "data" repository\r
-               //\r
-               ElementAccess ea;\r
-               MethodInfo get, set;\r
-               Indexers ilist;\r
-               ArrayList set_arguments;\r
-               \r
-               public IndexerAccess (ElementAccess ea_data)\r
-               {\r
-                       ea = ea_data;\r
-                       eclass = ExprClass.Value;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       Type indexer_type = ea.Expr.Type;\r
-                       \r
-                       //\r
-                       // Step 1: Query for all `Item' *properties*.  Notice\r
-                       // that the actual methods are pointed from here.\r
-                       //\r
-                       // This is a group of properties, piles of them.  \r
-\r
-                       if (ilist == null)\r
-                               ilist = Indexers.GetIndexersForType (\r
-                                       indexer_type, RootContext.TypeManager, ea.loc);\r
-\r
-\r
-                       //\r
-                       // Step 2: find the proper match\r
-                       //\r
-                       if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)\r
-                               get = (MethodInfo) Invocation.OverloadResolve (\r
-                                       ec, new MethodGroupExpr (ilist.getters), ea.Arguments, ea.loc);\r
-\r
-                       if (get == null){\r
-                               Report.Error (154, ea.loc,\r
-                                             "indexer can not be used in this context, because " +\r
-                                             "it lacks a `get' accessor");\r
-                               return null;\r
-                       }\r
-\r
-                       type = get.ReturnType;\r
-                       if (type.IsPointer && !ec.InUnsafe){\r
-                               UnsafeError (ea.loc);\r
-                               return null;\r
-                       }\r
-                       \r
-                       eclass = ExprClass.IndexerAccess;\r
-                       return this;\r
-               }\r
-\r
-               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)\r
-               {\r
-                       Type indexer_type = ea.Expr.Type;\r
-                       Type right_type = right_side.Type;\r
-\r
-                       if (ilist == null)\r
-                               ilist = Indexers.GetIndexersForType (\r
-                                       indexer_type, RootContext.TypeManager, ea.loc);\r
-\r
-                       if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){\r
-                               set_arguments = (ArrayList) ea.Arguments.Clone ();\r
-                               set_arguments.Add (new Argument (right_side, Argument.AType.Expression));\r
-\r
-                               set = (MethodInfo) Invocation.OverloadResolve (\r
-                                       ec, new MethodGroupExpr (ilist.setters), set_arguments, ea.loc);\r
-                       }\r
-                       \r
-                       if (set == null){\r
-                               Report.Error (200, ea.loc,\r
-                                             "indexer X.this [" + TypeManager.CSharpName (right_type) +\r
-                                             "] lacks a `set' accessor");\r
-                                       return null;\r
-                       }\r
-\r
-                       type = TypeManager.void_type;\r
-                       eclass = ExprClass.IndexerAccess;\r
-                       return this;\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       Invocation.EmitCall (ec, false, false, ea.Expr, get, ea.Arguments);\r
-               }\r
-\r
-               //\r
-               // source is ignored, because we already have a copy of it from the\r
-               // LValue resolution and we have already constructed a pre-cached\r
-               // version of the arguments (ea.set_arguments);\r
-               //\r
-               public void EmitAssign (EmitContext ec, Expression source)\r
-               {\r
-                       Invocation.EmitCall (ec, false, false, ea.Expr, set, set_arguments);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   The base operator for method names\r
-       /// </summary>\r
-       public class BaseAccess : Expression {\r
-               string member;\r
-               Location loc;\r
-               \r
-               public BaseAccess (string member, Location l)\r
-               {\r
-                       this.member = member;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       Expression member_lookup;\r
-                       Type current_type = ec.TypeContainer.TypeBuilder;\r
-                       Type base_type = current_type.BaseType;\r
-                       Expression e;\r
-\r
-                       if (ec.IsStatic){\r
-                               Report.Error (1511, loc,\r
-                                             "Keyword base is not allowed in static method");\r
-                               return null;\r
-                       }\r
-                       \r
-                       member_lookup = MemberLookup (ec, base_type, member, loc);\r
-                       if (member_lookup == null)\r
-                               return null;\r
-\r
-                       Expression left;\r
-                       \r
-                       if (ec.IsStatic)\r
-                               left = new TypeExpr (base_type);\r
-                       else\r
-                               left = ec.This;\r
-                       \r
-                       e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);\r
-                       if (e is PropertyExpr){\r
-                               PropertyExpr pe = (PropertyExpr) e;\r
-\r
-                               pe.IsBase = true;\r
-                       }\r
-\r
-                       return e;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       throw new Exception ("Should never be called"); \r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       ///   The base indexer operator\r
-       /// </summary>\r
-       public class BaseIndexerAccess : Expression {\r
-               ArrayList Arguments;\r
-               Location loc;\r
-               \r
-               public BaseIndexerAccess (ArrayList args, Location l)\r
-               {\r
-                       Arguments = args;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       Type current_type = ec.TypeContainer.TypeBuilder;\r
-                       Type base_type = current_type.BaseType;\r
-                       Expression member_lookup;\r
-\r
-                       if (ec.IsStatic){\r
-                               Report.Error (1511, loc,\r
-                                             "Keyword base is not allowed in static method");\r
-                               return null;\r
-                       }\r
-                       \r
-                       member_lookup = MemberLookup (ec, base_type, "get_Item", MemberTypes.Method, AllBindingFlags, loc);\r
-                       if (member_lookup == null)\r
-                               return null;\r
-\r
-                       return MemberAccess.ResolveMemberAccess (ec, member_lookup, ec.This, loc, null);\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       throw new Exception ("Should never be called");\r
-               }\r
-       }\r
-       \r
-       /// <summary>\r
-       ///   This class exists solely to pass the Type around and to be a dummy\r
-       ///   that can be passed to the conversion functions (this is used by\r
-       ///   foreach implementation to typecast the object return value from\r
-       ///   get_Current into the proper type.  All code has been generated and\r
-       ///   we only care about the side effect conversions to be performed\r
-       /// </summary>\r
-       public class EmptyExpression : Expression {\r
-               public EmptyExpression ()\r
-               {\r
-                       type = TypeManager.object_type;\r
-                       eclass = ExprClass.Value;\r
-               }\r
-\r
-               public EmptyExpression (Type t)\r
-               {\r
-                       type = t;\r
-                       eclass = ExprClass.Value;\r
-               }\r
-               \r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       // nothing, as we only exist to not do anything.\r
-               }\r
-\r
-               //\r
-               // This is just because we might want to reuse this bad boy\r
-               // instead of creating gazillions of EmptyExpressions.\r
-               // (CanConvertImplicit uses it)\r
-               //\r
-               public void SetType (Type t)\r
-               {\r
-                       type = t;\r
-               }\r
-       }\r
-\r
-       public class UserCast : Expression {\r
-               MethodBase method;\r
-               Expression source;\r
-               \r
-               public UserCast (MethodInfo method, Expression source)\r
-               {\r
-                       this.method = method;\r
-                       this.source = source;\r
-                       type = method.ReturnType;\r
-                       eclass = ExprClass.Value;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // We are born fully resolved\r
-                       //\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-\r
-                       source.Emit (ec);\r
-                       \r
-                       if (method is MethodInfo)\r
-                               ig.Emit (OpCodes.Call, (MethodInfo) method);\r
-                       else\r
-                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);\r
-\r
-               }\r
-       }\r
-\r
-       // <summary>\r
-       //   This class is used to "construct" the type during a typecast\r
-       //   operation.  Since the Type.GetType class in .NET can parse\r
-       //   the type specification, we just use this to construct the type\r
-       //   one bit at a time.\r
-       // </summary>\r
-       public class ComposedCast : Expression {\r
-               Expression left;\r
-               string dim;\r
-               Location loc;\r
-               \r
-               public ComposedCast (Expression left, string dim, Location l)\r
-               {\r
-                       this.left = left;\r
-                       this.dim = dim;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       left = left.Resolve (ec);\r
-                       if (left == null)\r
-                               return null;\r
-\r
-                       if (left.eclass != ExprClass.Type){\r
-                               report118 (loc, left, "type");\r
-                               return null;\r
-                       }\r
-                       \r
-                       type = RootContext.LookupType (\r
-                               ec.DeclSpace, left.Type.FullName + dim, false, loc);\r
-                       if (type == null)\r
-                               return null;\r
-\r
-                       if (!ec.InUnsafe && type.IsPointer){\r
-                               UnsafeError (loc);\r
-                               return null;\r
-                       }\r
-                       \r
-                       eclass = ExprClass.Type;\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       throw new Exception ("This should never be called");\r
-               }\r
-       }\r
-\r
-       //\r
-       // This class is used to represent the address of an array, used\r
-       // only by the Fixed statement, this is like the C "&a [0]" construct.\r
-       //\r
-       public class ArrayPtr : Expression {\r
-               Expression array;\r
-               \r
-               public ArrayPtr (Expression array)\r
-               {\r
-                       Type array_type = array.Type.GetElementType ();\r
-\r
-                       this.array = array;\r
-                       \r
-                       string array_ptr_type_name = array_type.FullName + "*";\r
-                       \r
-                       type = Type.GetType (array_ptr_type_name);\r
-                       if (type == null){\r
-                               ModuleBuilder mb = RootContext.ModuleBuilder;\r
-                               \r
-                               type = mb.GetType (array_ptr_type_name);\r
-                       }\r
-\r
-                       eclass = ExprClass.Value;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-                       \r
-                       array.Emit (ec);\r
-                       IntLiteral.EmitInt (ig, 0);\r
-                       ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       //\r
-                       // We are born fully resolved\r
-                       //\r
-                       return this;\r
-               }\r
-       }\r
-\r
-       //\r
-       // Used by the fixed statement\r
-       //\r
-       public class StringPtr : Expression {\r
-               LocalBuilder b;\r
-               \r
-               public StringPtr (LocalBuilder b)\r
-               {\r
-                       this.b = b;\r
-                       eclass = ExprClass.Value;\r
-                       type = TypeManager.char_ptr_type;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       // This should never be invoked, we are born in fully\r
-                       // initialized state.\r
-\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       ILGenerator ig = ec.ig;\r
-\r
-                       ig.Emit (OpCodes.Ldloc, b);\r
-                       ig.Emit (OpCodes.Conv_I);\r
-                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);\r
-                       ig.Emit (OpCodes.Add);\r
-               }\r
-       }\r
-       \r
-       //\r
-       // Implements the `stackalloc' keyword\r
-       //\r
-       public class StackAlloc : Expression {\r
-               Type otype;\r
-               string t;\r
-               Expression count;\r
-               Location loc;\r
-               \r
-               public StackAlloc (string type, Expression count, Location l)\r
-               {\r
-                       t = type;\r
-                       this.count = count;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       count = count.Resolve (ec);\r
-                       if (count == null)\r
-                               return null;\r
-                       \r
-                       if (count.Type != TypeManager.int32_type){\r
-                               count = ConvertImplicitRequired (ec, count, TypeManager.int32_type, loc);\r
-                               if (count == null)\r
-                                       return null;\r
-                       }\r
-\r
-                       if (ec.InCatch || ec.InFinally){\r
-                               Report.Error (255, loc,\r
-                                             "stackalloc can not be used in a catch or finally block");\r
-                               return null;\r
-                       }\r
-                       \r
-                       otype = RootContext.LookupType (ec.DeclSpace, t, false, loc);\r
-\r
-                       if (otype == null)\r
-                               return null;\r
-\r
-                       if (!TypeManager.VerifyUnManaged (otype, loc))\r
-                               return null;\r
-\r
-                       string ptr_name = otype.FullName + "*";\r
-                       type = Type.GetType (ptr_name);\r
-                       if (type == null){\r
-                               ModuleBuilder mb = RootContext.ModuleBuilder;\r
-                               \r
-                               type = mb.GetType (ptr_name);\r
-                       }\r
-                       eclass = ExprClass.Value;\r
-\r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       int size = GetTypeSize (otype);\r
-                       ILGenerator ig = ec.ig;\r
-                               \r
-                       if (size == 0)\r
-                               ig.Emit (OpCodes.Sizeof, otype);\r
-                       else\r
-                               IntConstant.EmitInt (ig, size);\r
-                       count.Emit (ec);\r
-                       ig.Emit (OpCodes.Mul);\r
-                       ig.Emit (OpCodes.Localloc);\r
-               }\r
-       }\r
-}\r
+//
+// expression.cs: Expression representation for the IL tree.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+//
+#define USE_OLD
+
+namespace Mono.MonoBASIC {
+       using System;
+       using System.Collections;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Text;
+
+       /// <summary>
+       ///   This is just a helper class, it is generated by Unary, UnaryMutator
+       ///   when an overloaded method has been found.  It just emits the code for a
+       ///   static call.
+       /// </summary>
+       public class StaticCallExpr : ExpressionStatement {
+               ArrayList args;
+               MethodInfo mi;
+
+               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)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       if (args != null) 
+                               Invocation.EmitArguments (ec, mi, args);
+
+                       ec.ig.Emit (OpCodes.Call, mi);
+                       return;
+               }
+               
+               static public Expression MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
+                                                        Expression e, Location loc)
+               {
+                       ArrayList args;
+                       MethodBase method;
+                       
+                       args = new ArrayList (1);
+                       args.Add (new Argument (e, Argument.AType.Expression));
+                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc);
+
+                       if (method == null)
+                               return null;
+
+                       return new StaticCallExpr ((MethodInfo) method, args, loc);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+                       if (TypeManager.TypeToCoreType (type) != TypeManager.void_type)
+                               ec.ig.Emit (OpCodes.Pop);
+               }
+       }
+       
+       /// <summary>
+       ///   Unary expressions.  
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   Unary implements unary expressions.   It derives from
+       ///   ExpressionStatement becuase the pre/post increment/decrement
+       ///   operators can be used in a statement context.
+       /// </remarks>
+       public class Unary : Expression {
+               public enum Operator : byte {
+                       UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
+                       Indirection, AddressOf,  TOP
+               }
+
+               public Operator Oper;
+               public Expression Expr;
+               
+               public Unary (Operator op, Expression expr, Location loc)
+               {
+                       this.Oper = op;
+                       this.Expr = expr;
+                       this.loc = loc;
+               }
+
+               /// <summary>
+               ///   Returns a stringified representation of the Operator
+               /// </summary>
+               static public string OperName (Operator oper)
+               {
+                       switch (oper){
+                       case Operator.UnaryPlus:
+                               return "+";
+                       case Operator.UnaryNegation:
+                               return "-";
+                       case Operator.LogicalNot:
+                               return "!";
+                       case Operator.OnesComplement:
+                               return "~";
+                       case Operator.AddressOf:
+                               return "&";
+                       case Operator.Indirection:
+                               return "*";
+                       }
+
+                       return oper.ToString ();
+               }
+
+               static string [] oper_names;
+
+               static Unary ()
+               {
+                       oper_names = new string [(int)Operator.TOP];
+
+                       oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";
+                       oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
+                       oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
+                       oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
+                       oper_names [(int) Operator.Indirection] = "op_Indirection";
+                       oper_names [(int) Operator.AddressOf] = "op_AddressOf";
+               }
+
+               void Error23 (Type t)
+               {
+                       Error (
+                               23, "Operator " + OperName (Oper) +
+                               " cannot be applied to operand of type '" +
+                               TypeManager.MonoBASIC_Name (t) + "'");
+               }
+
+               /// <remarks>
+               ///   The result has been already resolved:
+               ///
+               ///   FIXME: a minus constant -128 sbyte cant be turned into a
+               ///   constant byte.
+               /// </remarks>
+               static Expression TryReduceNegative (Constant expr)
+               {
+                       Expression e = null;
+                       
+                       if (expr is IntConstant)
+                               e = new IntConstant (-((IntConstant) expr).Value);
+                       else if (expr is UIntConstant){
+                               uint value = ((UIntConstant) expr).Value;
+
+                               if (value < 2147483649)
+                                       return new IntConstant (-(int)value);
+                               else
+                                       e = new LongConstant (value);
+                       }
+                       else if (expr is LongConstant)
+                               e = new LongConstant (-((LongConstant) expr).Value);
+                       else if (expr is ULongConstant){
+                               ulong value = ((ULongConstant) expr).Value;
+
+                               if (value < 9223372036854775809)
+                                       return new LongConstant(-(long)value);
+                       }
+                       else if (expr is FloatConstant)
+                               e = new FloatConstant (-((FloatConstant) expr).Value);
+                       else if (expr is DoubleConstant)
+                               e = new DoubleConstant (-((DoubleConstant) expr).Value);
+                       else if (expr is DecimalConstant)
+                               e = new DecimalConstant (-((DecimalConstant) expr).Value);
+                       else if (expr is ShortConstant)
+                               e = new IntConstant (-((ShortConstant) expr).Value);
+                       else if (expr is UShortConstant)
+                               e = new IntConstant (-((UShortConstant) expr).Value);
+                       return e;
+               }
+
+               // <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:
+                               result = e;
+                               return true;
+                               
+                       case Operator.UnaryNegation:
+                               result = TryReduceNegative (e);
+                               return true;
+                               
+                       case Operator.LogicalNot:
+                               if (expr_type != TypeManager.bool_type) {
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
+                               
+                               BoolConstant b = (BoolConstant) e;
+                               result = new BoolConstant (!(b.Value));
+                               return true;
+                               
+                       case Operator.OnesComplement:
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
+
+                               if (e is EnumConstant){
+                                       EnumConstant enum_constant = (EnumConstant) e;
+                                       Expression reduced;
+                                       
+                                       if (Reduce (ec, enum_constant.Child, out reduced)){
+                                               result = new EnumConstant ((Constant) reduced, enum_constant.Type);
+                                               return true;
+                                       } else {
+                                               result = null;
+                                               return false;
+                                       }
+                               }
+
+                               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;
+
+                       case Operator.AddressOf:
+                               result = this;
+                               return false;
+
+                       case Operator.Indirection:
+                               result = this;
+                               return false;
+                       }
+                       throw new Exception ("Can not constant fold: " + Oper.ToString());
+               }
+
+               Expression ResolveOperator (EmitContext ec)
+               {
+                       Type expr_type = Expr.Type;
+
+                       //
+                       // Step 1: Perform Operator Overload location
+                       //
+                       Expression mg;
+                       string op_name;
+                       
+                       op_name = oper_names [(int) Oper];
+
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+                       
+                       if (mg != null) {
+                               Expression e = StaticCallExpr.MakeSimpleCall (
+                                       ec, (MethodGroupExpr) mg, Expr, loc);
+
+                               if (e == null){
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+                               
+                               return e;
+                       }
+
+                       // Only perform numeric promotions on:
+                       // +, - 
+
+                       if (expr_type == null)
+                               return null;
+                       
+                       //
+                       // Step 2: Default operations on CLI native types.
+                       //
+
+                       // 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;
+                               }
+                               
+                               type = TypeManager.bool_type;
+                               return this;
+
+                       case Operator.OnesComplement:
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+                                       Expression e;
+
+                                       e = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.int32_type;
+                                               return this;
+                                       }
+                                       e = ConvertImplicit (ec, Expr, TypeManager.uint32_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.uint32_type;
+                                               return this;
+                                       }
+                                       e = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.int64_type;
+                                               return this;
+                                       }
+                                       e = ConvertImplicit (ec, Expr, TypeManager.uint64_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.uint64_type;
+                                               return this;
+                                       }
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+                               type = expr_type;
+                               return this;
+
+                       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;
+
+                       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;
+                               }
+
+                               //
+                               // perform numeric promotions to int,
+                               // long, double.
+                               //
+                               //
+                               // The following is inneficient, because we call
+                               // ConvertImplicit too many times.
+                               //
+                               // It is also not clear if we should convert to Float
+                               // or Double initially.
+                               //
+                               if (expr_type == TypeManager.uint32_type){
+                                       //
+                                       // FIXME: handle exception to this rule that
+                                       // permits the int value -2147483648 (-2^31) to
+                                       // bt wrote as a decimal interger literal
+                                       //
+                                       type = TypeManager.int64_type;
+                                       Expr = ConvertImplicit (ec, Expr, type, loc);
+                                       return this;
+                               }
+
+                               if (expr_type == TypeManager.uint64_type){
+                                       //
+                                       // FIXME: Handle exception of 'long value'
+                                       // -92233720368547758087 (-2^63) to be wrote as
+                                       // decimal integer literal.
+                                       //
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+
+                               if (expr_type == TypeManager.float_type){
+                                       type = expr_type;
+                                       return this;
+                               }
+                               
+                               expr = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               } 
+
+                               expr = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               }
+
+                               expr = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               }
+                               
+                               Error23 (expr_type);
+                               return null;
+                       }
+
+                       Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" +
+                              TypeManager.MonoBASIC_Name (expr_type) + "'");
+                       return null;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (Oper == Operator.AddressOf)
+                               Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
+                       else
+                               Expr = Expr.Resolve (ec);
+                       
+                       if (Expr == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       return ResolveOperator (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Type expr_type = Expr.Type;
+                       
+                       switch (Oper) {
+                       case Operator.UnaryPlus:
+                               throw new Exception ("This should be caught by Resolve");
+                               
+                       case Operator.UnaryNegation:
+                               Expr.Emit (ec);
+                               ig.Emit (OpCodes.Neg);
+                               break;
+                               
+                       case Operator.LogicalNot:
+                               Expr.Emit (ec);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Ceq);
+                               break;
+                               
+                       case Operator.OnesComplement:
+                               Expr.Emit (ec);
+                               ig.Emit (OpCodes.Not);
+                               break;
+                               
+                       case Operator.AddressOf:
+                               ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
+                               break;
+                               
+                       default:
+                               throw new Exception ("This should not happen: Operator = "
+                                                    + Oper.ToString ());
+                       }
+               }
+
+               /// <summary>
+               ///   This will emit the child expression for 'ec' avoiding the logical
+               ///   not.  The parent will take care of changing brfalse/brtrue
+               /// </summary>
+               public void EmitLogicalNot (EmitContext ec)
+               {
+                       if (Oper != Operator.LogicalNot)
+                               throw new Exception ("EmitLogicalNot can only be called with !expr");
+
+                       Expr.Emit (ec);
+               }
+
+               public override string ToString ()
+               {
+                       return "Unary (" + Oper + ", " + Expr + ")";
+               }
+               
+       }
+
+       //
+       // Unary operators are turned into Indirection expressions
+       // after semantic analysis (this is so we can take the address
+       // of an indirection).
+       //
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+               Expression expr;
+               LocalTemporary temporary;
+               bool have_temporary;
+               
+               public Indirection (Expression expr, Location l)
+               {
+                       this.expr = expr;
+                       this.type = TypeManager.TypeToCoreType (expr.Type.GetElementType ());
+                       eclass = ExprClass.Variable;
+                       loc = l;
+               }
+
+               void LoadExprValue (EmitContext ec)
+               {
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       if (temporary != null){
+                               if (have_temporary){
+                                       temporary.Emit (ec);
+                                       return;
+                               }
+                               expr.Emit (ec);
+                               ec.ig.Emit (OpCodes.Dup);
+                               temporary.Store (ec);
+                               have_temporary = true;
+                       } else
+                               expr.Emit (ec);
+                       
+                       LoadFromPtr (ig, Type);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       if (temporary != null){
+                               if (have_temporary){
+                                       temporary.Emit (ec);
+                                       return;
+                               }
+                               expr.Emit (ec);
+                               ec.ig.Emit (OpCodes.Dup);
+                               temporary.Store (ec);
+                               have_temporary = true;
+                       } else
+                               expr.Emit (ec);
+
+                       source.Emit (ec);
+                       StoreFromPtr (ec.ig, type);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       if (temporary != null){
+                               if (have_temporary){
+                                       temporary.Emit (ec);
+                                       return;
+                               }
+                               expr.Emit (ec);
+                               ec.ig.Emit (OpCodes.Dup);
+                               temporary.Store (ec);
+                               have_temporary = true;
+                       } else
+                               expr.Emit (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // Born fully resolved
+                       //
+                       return this;
+               }
+
+               public new void CacheTemporaries (EmitContext ec)
+               {
+                       temporary = new LocalTemporary (ec, type);
+               }
+       }
+       
+       /// <summary>
+       ///   Unary Mutator expressions (pre and post ++ and --)
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   UnaryMutator implements ++ and -- expressions.   It derives from
+       ///   ExpressionStatement becuase the pre/post increment/decrement
+       ///   operators can be used in a statement context.
+       ///
+       /// FIXME: Idea, we could split this up in two classes, one simpler
+       /// for the common case, and one with the extra fields for more complex
+       /// 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.  
+       /// </remarks>
+       public class UnaryMutator : ExpressionStatement {
+               public enum Mode : byte {
+                       PreIncrement, PreDecrement, PostIncrement, PostDecrement
+               }
+               
+               Mode mode;
+               Expression expr;
+               LocalTemporary temp_storage;
+
+               //
+               // This is expensive for the simplest case.
+               //
+               Expression method;
+                       
+               public UnaryMutator (Mode m, Expression e, Location l)
+               {
+                       mode = m;
+                       loc = l;
+                       expr = e;
+               }
+
+               static string OperName (Mode mode)
+               {
+                       return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
+                               "++" : "--";
+               }
+               
+               void Error23 (Type 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
+               ///   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)
+               /// </summary>
+               static bool IsIncrementableNumber (Type t)
+               {
+                       return (t == TypeManager.sbyte_type) ||
+                               (t == TypeManager.byte_type) ||
+                               (t == TypeManager.short_type) ||
+                               (t == TypeManager.ushort_type) ||
+                               (t == TypeManager.int32_type) ||
+                               (t == TypeManager.uint32_type) ||
+                               (t == TypeManager.int64_type) ||
+                               (t == TypeManager.uint64_type) ||
+                               (t == TypeManager.char_type) ||
+                               (t.IsSubclassOf (TypeManager.enum_type)) ||
+                               (t == TypeManager.float_type) ||
+                               (t == TypeManager.double_type) ||
+                               (t.IsPointer && t != TypeManager.void_ptr_type);
+               }
+
+               Expression ResolveOperator (EmitContext ec)
+               {
+                       Type expr_type = expr.Type;
+
+                       //
+                       // Step 1: Perform Operator Overload location
+                       //
+                       Expression mg;
+                       string op_name;
+                       
+                       if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
+                               op_name = "op_Increment";
+                       else 
+                               op_name = "op_Decrement";
+
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+
+                       if (mg == null && expr_type.BaseType != null)
+                               mg = MemberLookup (ec, expr_type.BaseType, op_name,
+                                                  MemberTypes.Method, AllBindingFlags, loc);
+                       
+                       if (mg != null) {
+                               method = StaticCallExpr.MakeSimpleCall (
+                                       ec, (MethodGroupExpr) mg, expr, loc);
+
+                               type = method.Type;
+                               return this;
+                       }
+
+                       //
+                       // The operand of the prefix/postfix increment decrement operators
+                       // should be an expression that is classified as a variable,
+                       // a property access or an indexer access
+                       //
+                       type = expr_type;
+                       if (expr.eclass == ExprClass.Variable){
+                               if (IsIncrementableNumber (expr_type) ||
+                                   expr_type == TypeManager.decimal_type){
+                                       return this;
+                               }
+                       } else if (expr.eclass == ExprClass.IndexerAccess){
+                               IndexerAccess ia = (IndexerAccess) expr;
+                               
+                               temp_storage = new LocalTemporary (ec, expr.Type);
+                               
+                               expr = ia.ResolveLValue (ec, temp_storage);
+                               if (expr == null)
+                                       return null;
+
+                               return this;
+                       } else if (expr.eclass == ExprClass.PropertyAccess){
+                               PropertyExpr pe = (PropertyExpr) expr;
+
+                               if (pe.VerifyAssignable ())
+                                       return this;
+
+                               return null;
+                       } else {
+                               expr.Error118 ("variable, indexer or property access");
+                               return null;
+                       }
+
+                       Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
+                              TypeManager.MonoBASIC_Name (expr_type) + "'");
+                       return null;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       
+                       if (expr == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       return ResolveOperator (ec);
+               }
+
+               static int PtrTypeSize (Type t)
+               {
+                       return GetTypeSize (t.GetElementType ());
+               }
+
+               //
+               // Loads the proper "1" into the stack based on the type
+               //
+               static void LoadOne (ILGenerator ig, Type t)
+               {
+                       if (t == TypeManager.uint64_type || t == TypeManager.int64_type)
+                               ig.Emit (OpCodes.Ldc_I8, 1L);
+                       else if (t == TypeManager.double_type)
+                               ig.Emit (OpCodes.Ldc_R8, 1.0);
+                       else if (t == TypeManager.float_type)
+                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
+                       else if (t.IsPointer){
+                               int n = PtrTypeSize (t);
+                               
+                               if (n == 0)
+                                       ig.Emit (OpCodes.Sizeof, t);
+                               else
+                                       IntConstant.EmitInt (ig, n);
+                       } else 
+                               ig.Emit (OpCodes.Ldc_I4_1);
+               }
+
+               
+               //
+               // FIXME: We need some way of avoiding the use of temp_storage
+               // for some types of storage (parameters, local variables,
+               // static fields) and single-dimension array access.
+               //
+               void EmitCode (EmitContext ec, bool is_expr)
+               {
+                       ILGenerator ig = ec.ig;
+                       IAssignMethod ia = (IAssignMethod) expr;
+                       Type expr_type = expr.Type;
+                       
+                       if (temp_storage == null)
+                               temp_storage = new LocalTemporary (ec, expr_type);
+
+                       ia.CacheTemporaries (ec);
+                       ig.Emit (OpCodes.Nop);
+                       switch (mode){
+                       case Mode.PreIncrement:
+                       case Mode.PreDecrement:
+                               if (method == null){
+                                       expr.Emit (ec);
+
+                                       LoadOne (ig, expr_type);
+                                       
+                                       //
+                                       // Select the opcode based on the check state (then the type)
+                                       // and the actual operation
+                                       //
+                                       if (ec.CheckState){
+                                               if (expr_type == TypeManager.int32_type ||
+                                                   expr_type == TypeManager.int64_type){
+                                                       if (mode == Mode.PreDecrement)
+                                                               ig.Emit (OpCodes.Sub_Ovf);
+                                                       else
+                                                               ig.Emit (OpCodes.Add_Ovf);
+                                               } else if (expr_type == TypeManager.uint32_type ||
+                                                          expr_type == TypeManager.uint64_type){
+                                                       if (mode == Mode.PreDecrement)
+                                                               ig.Emit (OpCodes.Sub_Ovf_Un);
+                                                       else
+                                                               ig.Emit (OpCodes.Add_Ovf_Un);
+                                               } else {
+                                                       if (mode == Mode.PreDecrement)
+                                                               ig.Emit (OpCodes.Sub_Ovf);
+                                                       else
+                                                               ig.Emit (OpCodes.Add_Ovf);
+                                               }
+                                       } else {
+                                               if (mode == Mode.PreDecrement)
+                                                       ig.Emit (OpCodes.Sub);
+                                               else
+                                                       ig.Emit (OpCodes.Add);
+                                       }
+                               } else 
+                                       method.Emit (ec);
+
+                               temp_storage.Store (ec);
+                               ia.EmitAssign (ec, temp_storage);
+                               if (is_expr)
+                                       temp_storage.Emit (ec);
+                               break;
+                               
+                       case Mode.PostIncrement:
+                       case Mode.PostDecrement:
+                               if (is_expr)
+                                       expr.Emit (ec);
+                               
+                               if (method == null){
+                                       if (!is_expr)
+                                               expr.Emit (ec);
+                                       else
+                                               ig.Emit (OpCodes.Dup);
+
+                                       LoadOne (ig, expr_type);
+                                       
+                                       if (ec.CheckState){
+                                               if (expr_type == TypeManager.int32_type ||
+                                                   expr_type == TypeManager.int64_type){
+                                                       if (mode == Mode.PostDecrement)
+                                                               ig.Emit (OpCodes.Sub_Ovf);
+                                                       else
+                                                               ig.Emit (OpCodes.Add_Ovf);
+                                               } else if (expr_type == TypeManager.uint32_type ||
+                                                          expr_type == TypeManager.uint64_type){
+                                                       if (mode == Mode.PostDecrement)
+                                                               ig.Emit (OpCodes.Sub_Ovf_Un);
+                                                       else
+                                                               ig.Emit (OpCodes.Add_Ovf_Un);
+                                               } else {
+                                                       if (mode == Mode.PostDecrement)
+                                                               ig.Emit (OpCodes.Sub_Ovf);
+                                                       else
+                                                               ig.Emit (OpCodes.Add_Ovf);
+                                               }
+                                       } else {
+                                               if (mode == Mode.PostDecrement)
+                                                       ig.Emit (OpCodes.Sub);
+                                               else
+                                                       ig.Emit (OpCodes.Add);
+                                       }
+                               } else {
+                                       method.Emit (ec);
+                               }
+                               
+                               temp_storage.Store (ec);
+                               ia.EmitAssign (ec, temp_storage);
+                               break;
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       EmitCode (ec, true);
+                       
+               }
+               
+               public override void EmitStatement (EmitContext ec)
+               {
+                       EmitCode (ec, false);
+               }
+
+       }
+
+       /// <summary>
+       ///   Base class for the 'Is' and 'As' classes. 
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   FIXME: Split this in two, and we get to save the 'Operator' Oper
+       ///   size. 
+       /// </remarks>
+       public abstract class Probe : Expression {
+               public readonly Expression ProbeType;
+               protected Expression expr;
+               protected Type probe_type;
+               
+               public Probe (Expression expr, Expression probe_type, Location l)
+               {
+                       ProbeType = probe_type;
+                       loc = l;
+                       this.expr = expr;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
+
+                       if (probe_type == null)
+                               return null;
+
+                       expr = expr.Resolve (ec);
+                       
+                       return this;
+               }
+       }
+
+       /// <summary>
+       ///   Implementation of the 'is' operator.
+       /// </summary>
+       public class Is : Probe {
+               public Is (Expression expr, Expression probe_type, Location l)
+                       : base (expr, probe_type, l)
+               {
+               }
+
+               enum Action {
+                       AlwaysTrue, AlwaysNull, AlwaysFalse, LeaveOnStack, Probe
+               }
+
+               Action action;
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       expr.Emit (ec);
+
+                       switch (action){
+                       case Action.AlwaysFalse:
+                               ig.Emit (OpCodes.Pop);
+                               IntConstant.EmitInt (ig, 0);
+                               return;
+                       case Action.AlwaysTrue:
+                               ig.Emit (OpCodes.Pop);
+                               ig.Emit (OpCodes.Nop);
+                               IntConstant.EmitInt (ig, 1);
+                               return;
+                       case Action.LeaveOnStack:
+                               // the 'e != null' rule.
+                               return;
+                       case Action.Probe:
+                               ig.Emit (OpCodes.Isinst, probe_type);
+                               ig.Emit (OpCodes.Ldnull);
+                               ig.Emit (OpCodes.Cgt_Un);
+                               return;
+                       }
+                       throw new Exception ("never reached");
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+
+                       if ((e == null) || (expr == null))
+                               return null;
+
+                       Type etype = expr.Type;
+                       bool warning_always_matches = false;
+                       bool warning_never_matches = false;
+
+                       type = TypeManager.bool_type;
+                       eclass = ExprClass.Value;
+
+                       //
+                       // First case, if at compile time, there is an implicit conversion
+                       // then e != null (objects) or true (value types)
+                       //
+                       e = ConvertImplicitStandard (ec, expr, probe_type, loc);
+                       if (e != null){
+                               expr = e;
+                               if (etype.IsValueType)
+                                       action = Action.AlwaysTrue;
+                               else
+                                       action = Action.LeaveOnStack;
+
+                               warning_always_matches = true;
+                       } else if (ExplicitReferenceConversionExists (etype, probe_type)){
+                               //
+                               // Second case: explicit reference convresion
+                               //
+                               if (expr is NullLiteral)
+                                       action = Action.AlwaysFalse;
+                               else
+                                       action = Action.Probe;
+                       } else {
+                               action = Action.AlwaysFalse;
+                               warning_never_matches = true;
+                       }
+                       
+                       if (RootContext.WarningLevel >= 1){
+                               if (warning_always_matches)
+                                       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))
+                                               Warning (
+                                                       184,
+                                                       "The expression is never of type '" +
+                                                       TypeManager.MonoBASIC_Name (probe_type) + "'");
+                               }
+                       }
+
+                       return this;
+               }                               
+       }
+
+       /// <summary>
+       ///   Implementation of the 'as' operator.
+       /// </summary>
+       public class As : Probe {
+               public As (Expression expr, Expression probe_type, Location l)
+                       : base (expr, probe_type, l)
+               {
+               }
+
+               bool do_isinst = false;
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       expr.Emit (ec);
+
+                       if (do_isinst)
+                               ig.Emit (OpCodes.Isinst, probe_type);
+               }
+
+               static void Error_CannotConvertType (Type source, Type target, Location loc)
+               {
+                       Report.Error (
+                               39, loc, "as operator can not convert from '" +
+                               TypeManager.MonoBASIC_Name (source) + "' to '" +
+                               TypeManager.MonoBASIC_Name (target) + "'");
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+
+                       if (e == null)
+                               return null;
+
+                       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){
+                               expr = e;
+                               do_isinst = false;
+                               return this;
+                       }
+
+                       if (ExplicitReferenceConversionExists (etype, probe_type)){
+                               do_isinst = true;
+                               return this;
+                       }
+
+                       Error_CannotConvertType (etype, probe_type, loc);
+                       return null;
+               }                               
+       }
+       
+       /// <summary>
+       ///   This represents a typecast in the source language.
+       ///
+       ///   FIXME: Cast expressions have an unusual set of parsing
+       ///   rules, we need to figure those out.
+       /// </summary>
+       public class Cast : Expression {
+               Expression target_type;
+               Expression expr;
+               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 {
+                       get {
+                               return target_type;
+                       }
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+                       set {
+                               expr = value;
+                       }
+               }
+
+               public bool IsRuntimeCast\r
+               {
+                       get {
+                               return runtime_cast;
+                       }
+                       set{
+                               runtime_cast = value;
+                       }
+               }
+
+               /// <summary>
+               ///   Attempts to do a compile-time folding of a constant cast.
+               /// </summary>
+               Expression TryReduce (EmitContext ec, Type target_type)
+               {
+                       if (expr is ByteConstant){
+                               byte v = ((ByteConstant) expr).Value;
+       
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (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;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+
+                       return null;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       int errors = Report.Errors;
+
+                       type = ec.DeclSpace.ResolveType (target_type, false, Location);
+
+                       if (type == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       
+                       if (expr is Constant){
+                               Expression e = TryReduce (ec, type);
+
+                               if (e != null)
+                                       return e;
+                       }
+                       
+                       expr = ConvertExplicit (ec, expr, type, runtime_cast, loc);
+                       return expr;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       //
+                       // This one will never happen
+                       //
+                       throw new Exception ("Should not happen");
+               }
+       }
+
+       /// <summary>
+       ///   Binary operators
+       /// </summary>
+       public class Binary : Expression {
+               public enum Operator : byte {
+                       Multiply, Division, Modulus,
+                       Addition, Subtraction,
+                       LeftShift, RightShift,
+                       LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
+                       Equality, Inequality,
+                       BitwiseAnd,
+                       ExclusiveOr,
+                       BitwiseOr,
+                       LogicalAnd,
+                       LogicalOr,
+                       TOP
+               }
+
+               Operator oper;
+               Expression left, right;
+
+               //
+               // After resolution, method might contain the operator overload
+               // method.
+               //
+               protected MethodBase method;
+               ArrayList  Arguments;
+
+               bool DelegateOperation;
+
+               // This must be kept in sync with Operator!!!
+               static string [] oper_names;
+
+               static Binary ()
+               {
+                       oper_names = new string [(int) Operator.TOP];
+
+                       oper_names [(int) Operator.Multiply] = "op_Multiply";
+                       oper_names [(int) Operator.Division] = "op_Division";
+                       oper_names [(int) Operator.Modulus] = "op_Modulus";
+                       oper_names [(int) Operator.Addition] = "op_Addition";
+                       oper_names [(int) Operator.Subtraction] = "op_Subtraction";
+                       oper_names [(int) Operator.LeftShift] = "op_LeftShift";
+                       oper_names [(int) Operator.RightShift] = "op_RightShift";
+                       oper_names [(int) Operator.LessThan] = "op_LessThan";
+                       oper_names [(int) Operator.GreaterThan] = "op_GreaterThan";
+                       oper_names [(int) Operator.LessThanOrEqual] = "op_LessThanOrEqual";
+                       oper_names [(int) Operator.GreaterThanOrEqual] = "op_GreaterThanOrEqual";
+                       oper_names [(int) Operator.Equality] = "op_Equality";
+                       oper_names [(int) Operator.Inequality] = "op_Inequality";
+                       oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd";
+                       oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr";
+                       oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
+                       oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
+                       oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
+               }
+
+               public Binary (Operator oper, Expression left, Expression right, Location loc)
+               {
+                       this.oper = oper;
+                       this.left = left;
+                       this.right = right;
+                       this.loc = loc;
+               }
+
+               public Operator Oper {
+                       get {
+                               return oper;
+                       }
+                       set {
+                               oper = value;
+                       }
+               }
+               
+               public Expression Left {
+                       get {
+                               return left;
+                       }
+                       set {
+                               left = value;
+                       }
+               }
+
+               public Expression Right {
+                       get {
+                               return right;
+                       }
+                       set {
+                               right = value;
+                       }
+               }
+
+
+               /// <summary>
+               ///   Returns a stringified representation of the Operator
+               /// </summary>
+               static string OperName (Operator oper)
+               {
+                       switch (oper){
+                       case Operator.Multiply:
+                               return "*";
+                       case Operator.Division:
+                               return "/";
+                       case Operator.Modulus:
+                               return "%";
+                       case Operator.Addition:
+                               return "+";
+                       case Operator.Subtraction:
+                               return "-";
+                       case Operator.LeftShift:
+                               return "<<";
+                       case Operator.RightShift:
+                               return ">>";
+                       case Operator.LessThan:
+                               return "<";
+                       case Operator.GreaterThan:
+                               return ">";
+                       case Operator.LessThanOrEqual:
+                               return "<=";
+                       case Operator.GreaterThanOrEqual:
+                               return ">=";
+                       case Operator.Equality:
+                               return "==";
+                       case Operator.Inequality:
+                               return "!=";
+                       case Operator.BitwiseAnd:
+                               return "&";
+                       case Operator.BitwiseOr:
+                               return "|";
+                       case Operator.ExclusiveOr:
+                               return "^";
+                       case Operator.LogicalOr:
+                               return "||";
+                       case Operator.LogicalAnd:
+                               return "&&";
+                       }
+
+                       return oper.ToString ();
+               }
+
+               public override string ToString ()
+               {
+                       return "operator " + OperName (oper) + "(" + left.ToString () + ", " +
+                               right.ToString () + ")";
+               }
+               
+               Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
+               {
+                       if (expr.Type == target_type)
+                               return expr;
+
+                       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.MonoBASIC_Name (l) + "' "
+                               + "and '" + TypeManager.MonoBASIC_Name (r)
+                               + "'");
+               }
+
+               //
+               // Note that handling the case l == Decimal || r == Decimal
+               // is taken care of by the Step 1 Operator Overload resolution.
+               //
+               bool DoNumericPromotions (EmitContext ec, Type l, Type r)
+               {
+                       if (l == TypeManager.double_type || r == TypeManager.double_type){
+                               //
+                               // If either operand is of type double, the other operand is
+                               // conveted to type double.
+                               //
+                               if (r != TypeManager.double_type)
+                                       right = ConvertImplicit (ec, right, TypeManager.double_type, loc);
+                               if (l != TypeManager.double_type)
+                                       left = ConvertImplicit (ec, left, TypeManager.double_type, loc);
+                               
+                               type = TypeManager.double_type;
+                       } else if (l == TypeManager.float_type || r == TypeManager.float_type){
+                               //
+                               // if either operand is of type float, the other operand is
+                               // converted to type float.
+                               //
+                               if (r != TypeManager.double_type)
+                                       right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
+                               if (l != TypeManager.double_type)
+                                       left = ConvertImplicit (ec, left, TypeManager.float_type, loc);
+                               type = TypeManager.float_type;
+                       } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
+                               Expression e;
+                               Type other;
+                               //
+                               // If either operand is of type ulong, the other operand is
+                               // converted to type ulong.  or an error ocurrs if the other
+                               // operand is of type sbyte, short, int or long
+                               //
+                               if (l == TypeManager.uint64_type){
+                                       if (r != TypeManager.uint64_type){
+                                               if (right is IntConstant){
+                                                       IntConstant ic = (IntConstant) right;
+                                                       
+                                                       e = TryImplicitIntConversion (l, ic);
+                                                       if (e != null)
+                                                               right = e;
+                                               } else if (right is LongConstant){
+                                                       long ll = ((LongConstant) right).Value;
+
+                                                       if (ll > 0)
+                                                               right = new ULongConstant ((ulong) ll);
+                                               } else {
+                                                       e = ImplicitNumericConversion (ec, right, l, loc);
+                                                       if (e != null)
+                                                               right = e;
+                                               }
+                                       }
+                                       other = right.Type;
+                               } else {
+                                       if (left is IntConstant){
+                                               e = TryImplicitIntConversion (r, (IntConstant) left);
+                                               if (e != null)
+                                                       left = e;
+                                       } else if (left is LongConstant){
+                                               long ll = ((LongConstant) left).Value;
+                                               
+                                               if (ll > 0)
+                                                       left = new ULongConstant ((ulong) ll);
+                                       } else {
+                                               e = ImplicitNumericConversion (ec, left, r, loc);
+                                               if (e != null)
+                                                       left = e;
+                                       }
+                                       other = left.Type;
+                               }
+
+                               if ((other == TypeManager.sbyte_type) ||
+                                   (other == TypeManager.short_type) ||
+                                   (other == TypeManager.int32_type) ||
+                                   (other == TypeManager.int64_type))
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
+                               type = TypeManager.uint64_type;
+                       } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
+                               //
+                               // If either operand is of type long, the other operand is converted
+                               // to type long.
+                               //
+                               if (l != TypeManager.int64_type)
+                                       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){
+                               //
+                               // If either operand is of type uint, and the other
+                               // operand is of type sbyte, short or int, othe operands are
+                               // converted to type long.
+                               //
+                               Type other = null;
+                               
+                               if (l == TypeManager.uint32_type){
+                                       if (right is IntConstant){
+                                               IntConstant ic = (IntConstant) right;
+                                               int val = ic.Value;
+                                               
+                                               if (val >= 0)
+                                                       right = new UIntConstant ((uint) val);
+
+                                               type = l;
+                                               return true;
+                                       }
+                                       other = r;
+                               } 
+                               else if (r == TypeManager.uint32_type){
+                                       if (left is IntConstant){
+                                               IntConstant ic = (IntConstant) left;
+                                               int val = ic.Value;
+                                               
+                                               if (val >= 0)
+                                                       left = new UIntConstant ((uint) val);
+
+                                               type = r;
+                                               return true;
+                                       }
+                                       
+                                       other = l;
+                               }
+
+                               if ((other == TypeManager.sbyte_type) ||
+                                   (other == TypeManager.short_type) ||
+                                   (other == TypeManager.int32_type)){
+                                       left = ForceConversion (ec, left, TypeManager.int64_type);
+                                       right = ForceConversion (ec, right, TypeManager.int64_type);
+                                       type = TypeManager.int64_type;
+                               } else {
+                                       //
+                                       // if either operand is of type uint, the other
+                                       // operand is converd to type uint
+                                       //
+                                       left = ForceConversion (ec, left, TypeManager.uint32_type);
+                                       right = ForceConversion (ec, right, TypeManager.uint32_type);
+                                       type = TypeManager.uint32_type;
+                               } 
+                       } 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 {
+                               left = ForceConversion (ec, left, TypeManager.int32_type);
+                               right = ForceConversion (ec, right, TypeManager.int32_type);
+
+                               type = TypeManager.int32_type;
+                       }
+
+                       return (left != null) && (right != null);
+               }
+
+               static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type 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 ()
+               {
+                       Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
+               }
+
+               static bool is_32_or_64 (Type t)
+               {
+                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+                               t == TypeManager.int64_type || t == TypeManager.uint64_type);
+               }
+
+               static bool is_unsigned (Type t)
+               {
+                       return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
+                               t == TypeManager.short_type || t == TypeManager.byte_type);
+               }
+                                       
+               Expression CheckShiftArguments (EmitContext ec)
+               {
+                       Expression e;
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       e = ForceConversion (ec, right, TypeManager.int32_type);
+                       if (e == null){
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+                       right = e;
+
+                       if (((e = ConvertImplicit (ec, left, TypeManager.int32_type, loc)) != null) ||
+                           ((e = ConvertImplicit (ec, left, TypeManager.uint32_type, loc)) != null) ||
+                           ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) ||
+                           ((e = ConvertImplicit (ec, left, TypeManager.uint64_type, loc)) != null)){
+                               left = e;
+                               type = e.Type;
+
+                               return this;
+                       }
+                       Error_OperatorCannotBeApplied ();
+                       return null;
+               }
+
+               Expression ResolveOperator (EmitContext ec)
+               {
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       bool overload_failed = false;
+
+                       //
+                       // Step 1: Perform Operator Overload location
+                       //
+                       Expression left_expr, right_expr;
+                               
+                       string op = oper_names [(int) oper];
+                               
+                       MethodGroupExpr union;
+                       left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
+                       if (r != l){
+                               right_expr = MemberLookup (
+                                       ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
+                               union = Invocation.MakeUnionSet (left_expr, right_expr, loc);
+                       } else
+                               union = (MethodGroupExpr) left_expr;
+                               
+                       if (union != null) {
+                               Arguments = new ArrayList ();
+                               Arguments.Add (new Argument (left, Argument.AType.Expression));
+                               Arguments.Add (new Argument (right, Argument.AType.Expression));
+                               
+                               method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
+                               if (method != null) {
+                                       MethodInfo mi = (MethodInfo) method;
+                                       
+                                       type = mi.ReturnType;
+                                       return this;
+                               } else {
+                                       overload_failed = true;
+                               }
+                       }       
+                       
+                       //
+                       // Step 2: Default operations on CLI native types.
+                       //
+
+                       //
+                       // Step 0: String concatenation (because overloading will get this wrong)
+                       //
+                       if (oper == Operator.Addition){
+                               //
+                               // If any of the arguments is a string, cast to string
+                               //
+                               
+                               if (l == TypeManager.string_type){
+                                       
+                                       if (r == TypeManager.void_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       
+                                       if (r == TypeManager.string_type){
+                                               if (left is Constant && right is Constant){
+                                                       StringConstant ls = (StringConstant) left;
+                                                       StringConstant rs = (StringConstant) right;
+                                                       
+                                                       return new StringConstant (
+                                                               ls.Value + rs.Value);
+                                               }
+                                               
+                                               // string + string
+                                               method = TypeManager.string_concat_string_string;
+                                       } else {
+                                               // string + object
+                                               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;
+
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+                                       return this;
+                                       
+                               } else if (r == TypeManager.string_type){
+                                       // object + string
+
+                                       if (l == TypeManager.void_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       
+                                       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));
+
+                                       type = TypeManager.string_type;
+
+                                       return this;
+                               }
+
+                               //
+                               // Transform a + ( - b) into a - b
+                               //
+                               if (right is Unary){
+                                       Unary right_unary = (Unary) right;
+
+                                       if (right_unary.Oper == Unary.Operator.UnaryNegation){
+                                               oper = Operator.Subtraction;
+                                               right = right_unary.Expr;
+                                               r = right.Type;
+                                       }
+                               }
+                       }
+
+                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                               if (l == TypeManager.bool_type || r == TypeManager.bool_type){
+                                       if (r != TypeManager.bool_type || l != TypeManager.bool_type){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               //
+                               // operator != (object a, object b)
+                               // operator == (object a, object b)
+                               //
+                               // For this to be used, both arguments have to be reference-types.
+                               // Read the rationale on the spec (14.9.6)
+                               //
+                               // Also, if at compile time we know that the classes do not inherit
+                               // one from the other, then we catch the error there.
+                               //
+                               if (!(l.IsValueType || r.IsValueType)){
+                                       type = TypeManager.bool_type;
+
+                                       if (l == r)
+                                               return this;
+                                       
+                                       if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
+                                               return this;
+
+                                       //
+                                       // Also, a standard conversion must exist from either one
+                                       //
+                                       if (!(StandardConversionExists (left, r) ||
+                                             StandardConversionExists (right, l))){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       //
+                                       // We are going to have to convert to an object to compare
+                                       //
+                                       if (l != TypeManager.object_type)
+                                               left = new EmptyCast (left, TypeManager.object_type);
+                                       if (r != TypeManager.object_type)
+                                               right = new EmptyCast (right, TypeManager.object_type);
+
+                                       //
+                                       // FIXME: CSC here catches errors cs254 and cs252
+                                       //
+                                       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:
+                       // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
+                       //
+                       if (oper == Operator.Addition || oper == Operator.Subtraction) {
+                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
+                                   r.IsSubclassOf (TypeManager.delegate_type)) {
+                                       
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       
+                                       if (oper == Operator.Addition)
+                                               method = TypeManager.delegate_combine_delegate_delegate;
+                                       else
+                                               method = TypeManager.delegate_remove_delegate_delegate;
+
+                                       if (l != r) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       DelegateOperation = true;
+                                       type = l;
+                                       return this;
+                               }
+
+                               //
+                               // Pointer arithmetic:
+                               //
+                               // T* operator + (T* x, int y);
+                               // T* operator + (T* x, uint y);
+                               // T* operator + (T* x, long y);
+                               // T* operator + (T* x, ulong y);
+                               //
+                               // T* operator + (int y,   T* x);
+                               // T* operator + (uint y,  T *x);
+                               // T* operator + (long y,  T *x);
+                               // T* operator + (ulong y, T *x);
+                               //
+                               // T* operator - (T* x, int y);
+                               // T* operator - (T* x, uint y);
+                               // T* operator - (T* x, long y);
+                               // T* operator - (T* x, ulong y);
+                               //
+                               // long operator - (T* x, T *y)
+                               //
+                               if (l.IsPointer){
+                                       if (r.IsPointer && oper == Operator.Subtraction){
+                                               if (r == l)
+                                                       return new PointerArithmetic (
+                                                               false, left, right, TypeManager.int64_type,
+                                                               loc);
+                                       } else if (is_32_or_64 (r))
+                                               return new PointerArithmetic (
+                                                       oper == Operator.Addition, left, right, l, loc);
+                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
+                                       return new PointerArithmetic (
+                                               true, right, left, r, loc);
+                       }
+                       
+                       //
+                       // Enumeration operators
+                       //
+                       bool lie = TypeManager.IsEnumType (l);
+                       bool rie = TypeManager.IsEnumType (r);
+                       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 || oper == Operator.Subtraction){
+                                       Type enum_type = lie ? l : r;
+                                       Type other_type = lie ? r : l;
+                                       Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
+;
+                                       
+                                       if (underlying_type != other_type){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       type = enum_type;
+                                       return this;
+                               }
+                               
+                               if (!rie){
+                                       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){
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (oper == Operator.BitwiseAnd ||
+                                   oper == Operator.BitwiseOr ||
+                                   oper == Operator.ExclusiveOr){
+                                       type = l;
+                                       return this;
+                               }
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+                       
+                       if (oper == Operator.LeftShift || oper == Operator.RightShift)
+                               return CheckShiftArguments (ec);
+
+                       if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
+                               if (l != TypeManager.bool_type || r != TypeManager.bool_type){
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+
+                               type = TypeManager.bool_type;
+                               return this;
+                       } 
+
+                       //
+                       // operator & (bool x, bool y)
+                       // operator | (bool x, bool y)
+                       // operator ^ (bool x, bool y)
+                       //
+                       if (l == TypeManager.bool_type && r == TypeManager.bool_type){
+                               if (oper == Operator.BitwiseAnd ||
+                                   oper == Operator.BitwiseOr ||
+                                   oper == Operator.ExclusiveOr){
+                                       type = l;
+                                       return this;
+                               }
+                       }
+                       
+                       //
+                       // Pointer comparison
+                       //
+                       if (l.IsPointer && r.IsPointer){
+                               if (oper == Operator.Equality || oper == Operator.Inequality ||
+                                   oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
+                                   oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+                       }
+                       
+                       //
+                       // We are dealing with numbers
+                       //
+                       if (overload_failed){
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+
+                       //
+                       // 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;
+                       }
+
+                       //
+                       // reload our cached types if required
+                       //
+                       l = left.Type;
+                       r = right.Type;
+                       
+                       if (oper == Operator.BitwiseAnd ||
+                           oper == Operator.BitwiseOr ||
+                           oper == Operator.ExclusiveOr){
+                               if (l == r){
+                                       if (!((l == TypeManager.int32_type) ||
+                                             (l == TypeManager.uint32_type) ||
+                                             (l == TypeManager.int64_type) ||
+                                             (l == TypeManager.uint64_type)))
+                                               type = l;
+                               } else {
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+                       }
+
+                       if (oper == Operator.Equality ||
+                           oper == Operator.Inequality ||
+                           oper == Operator.LessThanOrEqual ||
+                           oper == Operator.LessThan ||
+                           oper == Operator.GreaterThanOrEqual ||
+                           oper == Operator.GreaterThan){
+                               type = TypeManager.bool_type;
+                       }
+
+                       return this;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       left = left.Resolve (ec);
+                       right = right.Resolve (ec);
+
+                       if (left == null || right == null)
+                               return null;
+
+                       if (left.Type == null)
+                               throw new Exception (
+                                       "Resolve returned non null, but did not set the type! (" +
+                                       left + ") at Line: " + loc.Row);
+                       if (right.Type == null)
+                               throw new Exception (
+                                       "Resolve returned non null, but did not set the type! (" +
+                                       right + ") at Line: "+ loc.Row);
+
+                       eclass = ExprClass.Value;
+
+                       if (left is Constant && right is Constant){
+                               Expression e = ConstantFold.BinaryFold (
+                                       ec, oper, (Constant) left, (Constant) right, loc);
+                               if (e != null)
+                                       return e;
+                       }
+
+                       return ResolveOperator (ec);
+               }
+
+               /// <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 (method != null)
+                               return false;
+
+                       ILGenerator ig = ec.ig;
+
+                       //
+                       // 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.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 (onTrue)
+                                       ig.Emit (OpCodes.Beq, target);
+                               else
+                                       ig.Emit (OpCodes.Bne_Un, target);
+                               break;
+
+                       case Operator.Inequality:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Bne_Un, target);
+                               else
+                                       ig.Emit (OpCodes.Beq, target);
+                               break;
+
+                       case Operator.LessThan:
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Blt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Blt, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bge_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bge, target);
+                               break;
+
+                       case Operator.GreaterThan:
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bgt, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Ble_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Ble, target);
+                               break;
+
+                       case Operator.LessThanOrEqual:
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Ble_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Ble, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bgt, target);
+                               break;
+
+
+                       case Operator.GreaterThanOrEqual:
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bge_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bge, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Blt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Blt, target);
+                               break;
+
+                       default:
+                               return false;
+                       }
+                       
+                       return true;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Type l = left.Type;
+                       Type r = right.Type;
+                       OpCode opcode;
+
+                       if (method != null) {
+
+                               // Note that operators are static anyway
+                               
+                               if (Arguments != null) 
+                                       Invocation.EmitArguments (ec, method, Arguments);
+                               
+                               if (method is MethodInfo)
+                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               else
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+
+                               if (DelegateOperation)
+                                       ig.Emit (OpCodes.Castclass, type);
+                                       
+                               return;
+                       }
+
+                       //
+                       // Handle short-circuit operators differently
+                       // than the rest
+                       //
+                       if (oper == Operator.LogicalAnd){
+                               Label load_zero = ig.DefineLabel ();
+                               Label end = ig.DefineLabel ();
+                               
+                               left.Emit (ec);
+                               ig.Emit (OpCodes.Brfalse, load_zero);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Br, end);
+                               ig.MarkLabel (load_zero);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.MarkLabel (end);
+                               return;
+                       } else if (oper == Operator.LogicalOr){
+                               Label load_one = ig.DefineLabel ();
+                               Label end = ig.DefineLabel ();
+                               
+                               left.Emit (ec);
+                               ig.Emit (OpCodes.Brtrue, load_one);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Br, end);
+                               ig.MarkLabel (load_one);
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.MarkLabel (end);
+                               return;
+                       }
+                       
+                       left.Emit (ec);
+                       right.Emit (ec);
+
+                       switch (oper){
+                       case Operator.Multiply:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Mul_Ovf;
+                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
+                                               opcode = OpCodes.Mul_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Mul;
+                               } else
+                                       opcode = OpCodes.Mul;
+
+                               break;
+
+                       case Operator.Division:
+                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
+                                       opcode = OpCodes.Div_Un;
+                               else
+                                       opcode = OpCodes.Div;
+                               break;
+
+                       case Operator.Modulus:
+                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
+                                       opcode = OpCodes.Rem_Un;
+                               else
+                                       opcode = OpCodes.Rem;
+                               break;
+
+                       case Operator.Addition:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Add_Ovf;
+                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
+                                               opcode = OpCodes.Add_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Add;
+                               } else
+                                       opcode = OpCodes.Add;
+                               break;
+
+                       case Operator.Subtraction:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Sub_Ovf;
+                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
+                                               opcode = OpCodes.Sub_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Sub;
+                               } else
+                                       opcode = OpCodes.Sub;
+                               break;
+
+                       case Operator.RightShift:
+                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
+                                       opcode = OpCodes.Shr_Un;
+                               else
+                                       opcode = OpCodes.Shr;
+                               break;
+                               
+                       case Operator.LeftShift:
+                               opcode = OpCodes.Shl;
+                               break;
+
+                       case Operator.Equality:
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.Inequality:
+                               ec.ig.Emit (OpCodes.Ceq);
+                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.LessThan:
+                               opcode = OpCodes.Clt;
+                               break;
+
+                       case Operator.GreaterThan:
+                               opcode = OpCodes.Cgt;
+                               break;
+
+                       case Operator.LessThanOrEqual:
+                               ec.ig.Emit (OpCodes.Cgt);
+                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.GreaterThanOrEqual:
+                               ec.ig.Emit (OpCodes.Clt);
+                               ec.ig.Emit (OpCodes.Ldc_I4_1);
+                               
+                               opcode = OpCodes.Sub;
+                               break;
+
+                       case Operator.BitwiseOr:
+                               opcode = OpCodes.Or;
+                               break;
+
+                       case Operator.BitwiseAnd:
+                               opcode = OpCodes.And;
+                               break;
+
+                       case Operator.ExclusiveOr:
+                               opcode = OpCodes.Xor;
+                               break;
+
+                       default:
+                               throw new Exception ("This should not happen: Operator = "
+                                                    + oper.ToString ());
+                       }
+
+                       ig.Emit (opcode);
+               }
+
+               public bool IsBuiltinOperator {
+                       get {
+                               return method == null;
+                       }
+               }
+       }
+
+       public class PointerArithmetic : Expression {
+               Expression left, right;
+               bool is_add;
+
+               //
+               // We assume that 'l' is always a pointer
+               //
+               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t,
+                                         Location loc)
+               {
+                       type = t;
+                       eclass = ExprClass.Variable;
+                       this.loc = loc;
+                       left = l;
+                       right = r;
+                       is_add = is_addition;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Type op_type = left.Type;
+                       ILGenerator ig = ec.ig;
+                       int size = GetTypeSize (op_type.GetElementType ());
+                       
+                       if (right.Type.IsPointer){
+                               //
+                               // handle (pointer - pointer)
+                               //
+                               left.Emit (ec);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Sub);
+
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Div);
+                               }
+                               ig.Emit (OpCodes.Conv_I8);
+                       } else {
+                               //
+                               // handle + and - on (pointer op int)
+                               //
+                               left.Emit (ec);
+                               ig.Emit (OpCodes.Conv_I);
+                               right.Emit (ec);
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Mul);
+                               }
+                               if (is_add)
+                                       ig.Emit (OpCodes.Add);
+                               else
+                                       ig.Emit (OpCodes.Sub);
+                       }
+               }
+       }
+       
+       /// <summary>
+       ///   Implements the ternary conditional operator (?:)
+       /// </summary>
+       public class Conditional : Expression {
+               Expression expr, trueExpr, falseExpr;
+               
+               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
+               {
+                       this.expr = expr;
+                       this.trueExpr = trueExpr;
+                       this.falseExpr = falseExpr;
+                       this.loc = l;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               public Expression TrueExpr {
+                       get {
+                               return trueExpr;
+                       }
+               }
+
+               public Expression FalseExpr {
+                       get {
+                               return falseExpr;
+                       }
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+
+                       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 (trueExpr == null || falseExpr == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       if (trueExpr.Type == falseExpr.Type)
+                               type = trueExpr.Type;
+                       else {
+                               Expression conv;
+                               Type true_type = trueExpr.Type;
+                               Type false_type = falseExpr.Type;
+
+                               if (trueExpr is NullLiteral){
+                                       type = false_type;
+                                       return this;
+                               } else if (falseExpr is NullLiteral){
+                                       type = true_type;
+                                       return this;
+                               }
+                               
+                               //
+                               // First, if an implicit conversion exists from trueExpr
+                               // to falseExpr, then the result type is of type falseExpr.Type
+                               //
+                               conv = ConvertImplicit (ec, trueExpr, false_type, loc);
+                               if (conv != null){
+                                       //
+                                       // Check if both can convert implicitl to each other's type
+                                       //
+                                       if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){
+                                               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;
+                                       trueExpr = conv;
+                               } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){
+                                       type = true_type;
+                                       falseExpr = conv;
+                               } else {
+                                       Error (173, "The type of the conditional expression can " +
+                                              "not be computed because there is no implicit conversion" +
+                                              " from '" + TypeManager.MonoBASIC_Name (trueExpr.Type) + "'" +
+                                              " and '" + TypeManager.MonoBASIC_Name (falseExpr.Type) + "'");
+                                       return null;
+                               }
+                       }
+
+                       if (expr is BoolConstant){
+                               BoolConstant bc = (BoolConstant) expr;
+
+                               if (bc.Value)
+                                       return trueExpr;
+                               else
+                                       return falseExpr;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label false_target = ig.DefineLabel ();
+                       Label end_target = ig.DefineLabel ();
+
+                       Statement.EmitBoolExpression (ec, expr, false_target, false);
+                       trueExpr.Emit (ec);
+                       ig.Emit (OpCodes.Br, end_target);
+                       ig.MarkLabel (false_target);
+                       falseExpr.Emit (ec);
+                       ig.MarkLabel (end_target);
+               }
+
+       }
+
+       /// <summary>
+       ///   Local variables
+       /// </summary>
+       public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+               public readonly string Name;
+               public readonly Block Block;
+               VariableInfo variable_info;
+               bool is_readonly;
+               
+               public LocalVariableReference (Block block, string name, Location l)
+               {
+                       Block = block;
+                       Name = name;
+                       loc = l;
+                       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) {
+                                       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)
+               {
+                       VariableInfo vi = VariableInfo;
+
+                       if (Block.IsConstant (Name)) {
+                               Expression e = Block.GetConstantExpression (Name);
+
+                               vi.Used = true;
+                               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;
+
+                       if (is_readonly){
+                               Error (1604, "cannot assign to '" + Name + "' because it is readonly");
+                               return null;
+                       }
+                       
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       VariableInfo vi = VariableInfo;
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+                       vi.Used = true;
+               }
+               
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       ILGenerator ig = ec.ig;
+                       VariableInfo vi = VariableInfo;
+
+                       vi.Assigned = true;
+
+                       source.Emit (ec);
+                       
+                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       VariableInfo vi = VariableInfo;
+
+                       ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);
+               }
+       }
+
+       /// <summary>
+       ///   This represents a reference to a parameter in the intermediate
+       ///   representation.
+       /// </summary>
+       public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+               Parameters pars;
+               String name;
+               int idx;
+               public Parameter.Modifier mod;
+               public bool is_ref, is_out;
+               
+               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.
+               //
+               // for "ref int a":
+               //   externally we expose "int&"
+               //   here we expose       "int".
+               //
+               // We record this in "is_ref".  This means that the type system can treat
+               // the type as it is expected, but when we generate the code, we generate
+               // the alternate kind of code.
+               //
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = 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
+               // is already stored in the parameter, not the address of the pointer,
+               // and not the value of the variable).
+               //
+               public void EmitLoad (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       EmitLdArg (ig, arg_idx);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       EmitLdArg (ig, arg_idx);
+
+                       if (!is_ref)
+                               return;
+
+                       //
+                       // If we are a reference, we loaded on the stack a pointer
+                       // Now lets load the real value
+                       //
+                       LoadFromPtr (ig, type);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       ILGenerator ig = ec.ig;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       if (is_ref)
+                               EmitLdArg (ig, arg_idx);
+                       
+                       source.Emit (ec);
+
+                       if (is_ref)
+                               StoreFromPtr (ig, type);
+                       else {
+                               if (arg_idx <= 255)
+                                       ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
+                               else
+                                       ig.Emit (OpCodes.Starg, arg_idx);
+                       }
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       if (is_ref){
+                               if (arg_idx <= 255)
+                                       ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
+                               else
+                                       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);
+                       }
+               }
+       }
+       
+       
+       /// <summary>
+       ///   Invocation of methods or delegates.
+       /// </summary>
+       public class Invocation : ExpressionStatement {
+               public ArrayList Arguments;
+
+               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 ()
+               {
+                       method_parameter_cache = new PtrHashtable ();
+               }
+                       
+               //
+               // arguments is an ArrayList, but we do not want to typecast,
+               // as it might be null.
+               //
+               // FIXME: only allow expr to be a method invocation or a
+               // delegate invocation (7.5.5)
+               //
+               public Invocation (Expression expr, ArrayList arguments, Location l)
+               {
+                       this.expr = expr;
+                       Arguments = arguments;
+                       loc = l;
+                       CompareName = new MemberFilter (compare_name_filter);
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               /// <summary>
+               ///   Returns the Parameters (a ParameterData interface) for the
+               ///   Method 'mb'
+               /// </summary>
+               public static ParameterData GetParameterData (MethodBase mb)
+               {
+                       object pd = method_parameter_cache [mb];
+                       object ip;
+                       
+                       if (pd != null)
+                               return (ParameterData) pd;
+
+                       
+                       ip = TypeManager.LookupParametersByBuilder (mb);
+                       if (ip != null){
+                               method_parameter_cache [mb] = ip;
+
+                               return (ParameterData) ip;
+                       } else {
+                               ParameterInfo [] pi = mb.GetParameters ();
+                               ReflectionParameters rp = new ReflectionParameters (pi);
+                               method_parameter_cache [mb] = rp;
+
+                               return (ParameterData) rp;
+                       }
+               }
+
+               /// <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");
+
+                       //
+                       // This is a special case since csc behaves this way. I can't find
+                       // it anywhere in the spec but oh well ...
+                       //
+                       if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+                               return 1;
+                       else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+                               return 0;
+                       
+                       if (p == q)
+                               return 0;
+                       
+                       if (argument_type == p)
+                               return 1;
+
+                       if (argument_type == q)
+                               return 0;
+
+                       //
+                       // 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>
+               /// <remarks>
+               ///    and returns an integer indicating :
+               ///    0 if candidate ain't better
+               ///    1 if candidate is better than the current best match
+               /// </remarks>
+               static int BetterFunction (EmitContext ec, ArrayList args,
+                                          MethodBase candidate, MethodBase best,
+                                          bool expanded_form, Location loc)
+               {
+                       ParameterData candidate_pd = GetParameterData (candidate);
+                       ParameterData best_pd;
+                       int argument_count;
+               
+                       if (args == null)
+                               argument_count = 0;
+                       else
+                               argument_count = args.Count;
+
+                       int cand_count = candidate_pd.Count;
+
+                       if (cand_count == 0 && argument_count == 0)
+                               return 1;
+
+                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+                               if (cand_count != argument_count)
+                                       return 0;
+                       
+                       if (best == null) {
+                               int x = 0;
+
+                               if (argument_count == 0 && cand_count == 1 &&
+                                   candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
+                                       return 1;
+                               
+                               for (int j = argument_count; j > 0;) {
+                                       j--;
+
+                                       Argument a = (Argument) args [j];
+                                       Type t = candidate_pd.ParameterType (j);
+
+                                       if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                               if (expanded_form)
+                                                       t = t.GetElementType ();
+
+                                       x = BetterConversion (ec, a, t, null, loc);
+                                       
+                                       if (x <= 0)
+                                               break;
+                               }
+
+                               if (x > 0)
+                                       return 1;
+                               else
+                                       return 0;
+                       }
+
+                       best_pd = GetParameterData (best);
+
+                       int rating1 = 0, rating2 = 0;
+                       
+                       for (int j = 0; j < argument_count; ++j) {
+                               int x, y;
+                               
+                               Argument a = (Argument) args [j];
+
+                               Type ct = candidate_pd.ParameterType (j);
+                               Type bt = best_pd.ParameterType (j);
+
+                               if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                       if (expanded_form)
+                                               ct = ct.GetElementType ();
+
+                               if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                       if (expanded_form)
+                                               bt = bt.GetElementType ();
+                               
+                               x = BetterConversion (ec, a, ct, bt, loc);
+                               y = BetterConversion (ec, a, bt, ct, loc);
+
+                               if (x < y)
+                                       return 0;
+                               
+                               rating1 += x;
+                               rating2 += y;
+                       }
+
+                       if (rating1 > rating2)
+                               return 1;
+                       else
+                               return 0;
+               }
+
+               public static string FullMethodDesc (MethodBase mb)
+               {
+                       string ret_type = "";
+
+                       if (mb is MethodInfo)
+                               ret_type = TypeManager.MonoBASIC_Name (((MethodInfo) mb).ReturnType) + " ";
+                       
+                       StringBuilder sb = new StringBuilder (ret_type + mb.Name);
+                       ParameterData pd = GetParameterData (mb);
+
+                       int count = pd.Count;
+                       sb.Append (" (");
+                       
+                       for (int i = count; i > 0; ) {
+                               i--;
+
+                               sb.Append (pd.ParameterDesc (count - i - 1));
+                               if (i != 0)
+                                       sb.Append (", ");
+                       }
+                       
+                       sb.Append (")");
+                       return sb.ToString ();
+               }
+
+               public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
+               {
+                       MemberInfo [] miset;
+                       MethodGroupExpr union;
+
+                       if (mg1 == null){
+                               if (mg2 == null)
+                                       return null;
+                               return (MethodGroupExpr) mg2;
+                       } else {
+                               if (mg2 == null)
+                                       return (MethodGroupExpr) mg1;
+                       }
+                       
+                       MethodGroupExpr left_set = null, right_set = null;
+                       int length1 = 0, length2 = 0;
+                       
+                       left_set = (MethodGroupExpr) mg1;
+                       length1 = left_set.Methods.Length;
+                       
+                       right_set = (MethodGroupExpr) mg2;
+                       length2 = right_set.Methods.Length;
+                       
+                       ArrayList common = new ArrayList ();
+
+                       foreach (MethodBase l in left_set.Methods){
+                               foreach (MethodBase r in right_set.Methods){
+                                       if (l != r)
+                                               continue;
+                                       common.Add (r);
+                                       break;
+                               }
+                       }
+                       
+                       miset = new MemberInfo [length1 + length2 - common.Count];
+                       left_set.Methods.CopyTo (miset, 0);
+                       
+                       int k = length1;
+
+                       foreach (MemberInfo mi in right_set.Methods){
+                               if (!common.Contains (mi))
+                                       miset [k++] = mi;
+                       }
+                       
+                       union = new MethodGroupExpr (miset, loc);
+                       
+                       return union;
+               }
+
+               /// <summary>
+               ///  Determines is the candidate method, if a params method, is applicable
+               ///  in its expanded form to the given set of arguments
+               /// </summary>
+               static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
+               {
+                       int arg_count;
+                       
+                       if (arguments == null)
+                               arg_count = 0;
+                       else
+                               arg_count = arguments.Count;
+                       
+                       ParameterData pd = GetParameterData (candidate);
+                       
+                       int pd_count = pd.Count;
+
+                       if (pd_count == 0)
+                               return false;
+                       
+                       if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
+                               return false;
+                       
+                       if (pd_count - 1 > arg_count)
+                               return false;
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               return true;
+
+                       //
+                       // If we have come this far, the case which remains is when the number of parameters
+                       // is less than or equal to the argument count.
+                       //
+                       for (int i = 0; i < pd_count - 1; ++i) {
+
+                               Argument a = (Argument) arguments [i];
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
+                               if (a_mod == p_mod) {
+
+                                       if (a_mod == Parameter.Modifier.NONE)
+                                               if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+                                                       return false;
+                                                                               
+                                       if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+                                               Type pt = pd.ParameterType (i);
+
+                                               if (!pt.IsByRef)
+                                                       pt = TypeManager.LookupType (pt.FullName + "&");
+                                               
+                                               if (pt != a.Type)
+                                                       return false;
+                                       }
+                               } else
+                                       return false;
+                               
+                       }
+
+                       Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
+
+                       for (int i = pd_count - 1; i < arg_count; i++) {
+                               Argument a = (Argument) arguments [i];
+                               
+                               if (!StandardConversionExists (a.Expr, element_type))
+                                       return false;
+                       }
+                       
+                       return true;
+               }
+
+               static bool CheckParameterAgainstArgument (EmitContext ec, ParameterData pd, int i, Argument a, Type ptype)
+               {
+                       Parameter.Modifier a_mod = a.GetParameterModifier () &
+                               ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                       Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                               ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
+                       if (a_mod == p_mod || (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
+                               if (a_mod == Parameter.Modifier.NONE)   
+                                       if (! (ImplicitConversionExists (ec, a.Expr, ptype) || RuntimeConversionExists (ec, a.Expr, ptype)) )
+                                               return false;
+                               
+                               if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+                                       Type pt = pd.ParameterType (i);
+                                       
+                                       if (!pt.IsByRef)
+                                               pt = TypeManager.LookupType (pt.FullName + "&");
+
+                                       if (pt != a.Type)
+                                               return false;
+                               }
+                       } else
+                               return false;                                   
+                       return true;                                    
+               }
+               
+               /// <summary>
+               ///  Determines if the candidate method is applicable (section 14.4.2.1)
+               ///  to the given set of arguments
+               /// </summary>
+               static bool IsApplicable (EmitContext ec, ref ArrayList arguments, MethodBase candidate)
+               {
+                       int arg_count, ps_count, po_count;
+                       Type param_type;
+                       
+                       if (arguments == null)
+                               arg_count = 0;
+                       else
+                               arg_count = arguments.Count;
+
+                       ParameterData pd = GetParameterData (candidate);
+                       Parameters ps = GetFullParameters (candidate);
+                       if (ps == null) {
+                               ps_count = 0;
+                               po_count = 0;
+                       }
+                       else {
+                               ps_count = ps.CountStandardParams();                    
+                               po_count = ps.CountOptionalParams();
+                       }
+                       int pd_count = pd.Count;
+
+                       // Validate argument count
+                       if (po_count == 0) {
+                               if (arg_count != pd.Count)
+                                       return false;
+                       }
+                       else {
+                               if ((arg_count < ps_count) || (arg_count > pd_count))
+                                       return false;   
+                       }       
+                       
+                       if (arg_count > 0) {
+                               for (int i = arg_count; i > 0 ; ) {
+                                       i--;
+
+                                       Argument a = (Argument) arguments [i];
+                                       if (a.ArgType == Argument.AType.NoArg) {
+                                               Parameter p = (Parameter) ps.FixedParameters[i];
+                                               a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
+                                               param_type = p.ParameterInitializer.Type;
+                                       }
+                                       else {
+                                               param_type = pd.ParameterType (i);
+                                               if (ps != null) {
+                                                       Parameter p = (Parameter) ps.FixedParameters[i];
+                                                       bool IsDelegate = TypeManager.IsDelegateType (param_type);
+
+                                                       if (IsDelegate) {       
+                                                               if (a.ArgType == Argument.AType.AddressOf) {
+                                                                       a = new Argument ((Expression) a.Expr, Argument.AType.Expression);
+                                                                       ArrayList args = new ArrayList();
+                                                                       args.Add (a);
+                                                                       string param_name = pd.ParameterDesc(i).Replace('+', '.');
+                                                                       Expression pname = MonoBASIC.Parser.DecomposeQI (param_name, Location.Null);
+
+
+                                                                       New temp_new = new New ((Expression)pname, args, Location.Null);
+                                                                       Expression del_temp = temp_new.DoResolve(ec);
+
+                                                                       if (del_temp == null)
+                                                                               return false;
+
+                                                                       a = new Argument (del_temp, Argument.AType.Expression);
+                                                                       if (!a.Resolve(ec, Location.Null))\r
+                                                                               return false;
+                                                               }
+                                                       }
+                                                       else {
+                                                               if (a.ArgType == Argument.AType.AddressOf)
+                                                                       return false;
+                                                       }
+
+                                                       if ((p.ModFlags & Parameter.Modifier.REF) != 0) {
+                                                               a = new Argument (a.Expr, Argument.AType.Ref);
+                                                               if (!a.Resolve(ec,Location.Null))
+                                                                       return false;
+                                                       }
+                                               }
+                                       }       
+\r
+                                       if (!CheckParameterAgainstArgument (ec, pd, i, a, param_type))
+                                               return (false);
+                               }
+                       }
+                       else {
+                               // If we have no arguments AND the first parameter is optional
+                               // we must check for a candidate (the loop above wouldn't)      
+                               if (po_count > 0) {
+                                       ArrayList arglist = new ArrayList();
+                                       
+                                       // Since we got so far, there's no need to check if
+                                       // arguments are optional; we simply retrieve
+                                       // parameter default values and build a brand-new 
+                                       // argument list.
+                                       
+                                       for (int i = 0; i < ps.FixedParameters.Length; i++) {
+                                               Parameter p = ps.FixedParameters[i];
+                                               Argument a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
+                                               a.Resolve(ec, Location.Null);
+                                               arglist.Add (a);
+                                       }
+                                       arguments = arglist;
+                                       return true;
+                               }
+                       }
+                       // We've found a candidate, so we exchange the dummy NoArg arguments
+                       // with new arguments containing the default value for that parameter
+
+                       ArrayList newarglist = new ArrayList();
+                       for (int i = 0; i < arg_count; i++) {
+                               Argument a = (Argument) arguments [i];
+                               Parameter p = null;
+
+                               if (ps != null)
+                                       p = (Parameter) ps.FixedParameters[i];
+
+                               if (a.ArgType == Argument.AType.NoArg){
+                                       a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
+                                       a.Resolve(ec, Location.Null);
+                               }
+
+                               // 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 (del_temp == null)
+                                               return false;
+
+                                       a = new Argument (del_temp, Argument.AType.Expression);
+                                       if (!a.Resolve(ec, Location.Null))\r
+                                               return false;
+                               }
+
+                               if ((p != null) && ((p.ModFlags & Parameter.Modifier.REF) != 0)) {
+                                       a.ArgType = Argument.AType.Ref;
+                                       a.Resolve(ec, Location.Null);
+                               }       
+                               newarglist.Add(a);
+                               int n = pd_count - arg_count;
+                               if (n > 0) {
+                                       for (int x = 0; x < n; x++) {
+                                               Parameter op = (Parameter) ps.FixedParameters[x + arg_count];
+                                               Argument b = new Argument (op.ParameterInitializer, Argument.AType.Expression);
+                                               b.Resolve(ec, Location.Null);
+                                               newarglist.Add (b);
+                                       }
+                               }
+                       }
+                       arguments = newarglist;
+                       return true;
+               }
+               
+               static bool compare_name_filter (MemberInfo m, object filterCriteria)
+               {
+                       return (m.Name == ((string) filterCriteria));
+               }
+
+               static Parameters GetFullParameters (MethodBase mb)
+               {
+                       TypeContainer tc = TypeManager.LookupTypeContainer (mb.DeclaringType);
+                       InternalParameters ip = TypeManager.LookupParametersByBuilder(mb);
+                       
+                       return (ip != null) ? ip.Parameters : null;
+               }
+               
+               // We need an overload for OverloadResolve because Invocation.DoResolve
+               // must pass Arguments by reference, since a later call to IsApplicable
+               // can change the argument list if optional parameters are defined
+               // in the method declaration
+               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
+                                                         ArrayList Arguments, Location loc)
+               {
+                       ArrayList a = Arguments;
+                       return OverloadResolve (ec, me, ref a, loc);    
+               }
+               
+               /// <summary>
+               ///   Find the Applicable Function Members (7.4.2.1)
+               ///
+               ///   me: Method Group expression with the members to select.
+               ///       it might contain constructors or methods (or anything
+               ///       that maps to a method).
+               ///
+               ///   Arguments: ArrayList containing resolved Argument objects.
+               ///
+               ///   loc: The location if we want an error to be reported, or a Null
+               ///        location for "probing" purposes.
+               ///
+               ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
+               ///            that is the best match of me on Arguments.
+               ///
+               /// </summary>
+               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
+                                                         ref ArrayList Arguments, Location loc)
+               {
+                       ArrayList afm = new ArrayList ();
+                       MethodBase method = null;
+                       Type current_type = null;
+                       int argument_count;
+                       ArrayList candidates = new ArrayList ();
+
+                       foreach (MethodBase candidate in me.Methods){
+                               int x;
+
+                               // If we're going one level higher in the class hierarchy, abort if
+                               // we already found an applicable method.
+                               if (candidate.DeclaringType != current_type) {
+                                       current_type = candidate.DeclaringType;
+                                       if (method != null)
+                                               break;
+                               }
+
+                               // Check if candidate is applicable (section 14.4.2.1)
+                               if (!IsApplicable (ec, ref Arguments, candidate))
+                                       continue;
+
+                               candidates.Add (candidate);
+                               x = BetterFunction (ec, Arguments, candidate, method, false, loc);
+                               
+                               if (x == 0)
+                                       continue;
+
+                               method = candidate;
+                       }
+
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+                       
+                       
+                       //
+                       // Now we see if we can find params functions, applicable in their expanded form
+                       // since if they were applicable in their normal form, they would have been selected
+                       // above anyways
+                       //
+                       bool chose_params_expanded = false;
+                       
+                       if (method == null) {
+                               candidates = new ArrayList ();
+                               foreach (MethodBase candidate in me.Methods){
+                                       if (!IsParamsMethodApplicable (ec, Arguments, candidate))
+                                               continue;
+
+                                       candidates.Add (candidate);
+
+                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
+                                       if (x == 0)
+                                               continue;
+
+                                       method = candidate; 
+                                       chose_params_expanded = true;
+                               }
+                       }
+
+                       if (method == null) {
+                               //
+                               // Okay so we have failed to find anything so we
+                               // return by providing info about the closest match
+                               //
+                               for (int i = 0; i < me.Methods.Length; ++i) {
+
+                                       MethodBase c = (MethodBase) me.Methods [i];
+                                       ParameterData pd = GetParameterData (c);
+
+                                       if (pd.Count != argument_count)
+                                               continue;
+
+                                       VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
+                                                              null, loc);
+                               }
+                               
+                               return null;
+                       }
+
+                       //
+                       // Now check that there are no ambiguities i.e the selected method
+                       // 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, ref Arguments, method))
+                                       continue;
+                                       
+                               int x = BetterFunction (ec, Arguments, method, candidate,
+                                                       chose_params_expanded, loc);
+
+                               if (x != 1) {
+                                       Report.Error (
+                                               121, loc,
+                                               "Ambiguous call 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 (VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+                                                  chose_params_expanded, null, loc))
+                               return method;
+                       else
+                               return null;
+               }
+
+               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,
+                                                         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);
+                                       
+                               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 = TypeManager.TypeToCoreType (parameter_type.GetElementType ());
+
+                               if (a.Type != parameter_type){
+                                       Expression conv;
+                                       
+                                       conv = ConvertImplicit (ec, a_expr, parameter_type, loc);
+
+                                       if (conv == null) {
+                                               if (!Location.IsNull (loc)) {
+                                                       if (delegate_type == null) 
+                                                               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.");
+                                                       Report.Error (1503, loc,
+                                                        "Argument " + (j+1) +
+                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
+                                                        + "' to '" + pd.ParameterDesc (j) + "'");
+                                               }
+                                               
+                                               return false;
+                                       }
+                                       
+                                       //
+                                       // Update the argument with the implicit conversion
+                                       //
+                                       if (a_expr != conv)
+                                               a.Expr = conv;
+                               }
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (j) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
+                               
+                               if (a_mod != p_mod &&
+                                   pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
+                                       if (!Location.IsNull (loc)) {
+                                               Report.Error (1502, loc,
+                                                      "The best overloaded match for method '" + FullMethodDesc (method)+
+                                                      "' has some invalid arguments");
+                                               Report.Error (1503, loc,
+                                                      "Argument " + (j+1) +
+                                                      ": Cannot convert from '" + Argument.FullDesc (a) 
+                                                      + "' to '" + pd.ParameterDesc (j) + "'");
+                                       }
+                                       
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+       
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       this.is_left_hand = true;
+                       return DoResolve (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // First, resolve the expression that is used to
+                       // trigger the invocation
+                       //
+                       Expression expr_to_return = null;
+
+                       if (expr is BaseAccess)
+                               is_base = true;
+
+                       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 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)
+                               {
+                                       bool IsDelegate = TypeManager.IsDelegateType (expr_type);
+                                       if (IsDelegate)
+                                               return (new DelegateInvocation (
+                                                       this.expr, Arguments, loc)).Resolve (ec);
+                               }
+                       }
+
+                       //
+                       // Next, evaluate all the expressions in the argument list
+                       //
+                       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;
+                       }
+
+                       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(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 (expr is FieldExpr || expr is LocalVariableReference || expr is ParameterReference) {
+                               if (expr.Type.IsArray) {
+                                       // If we are here, expr must be an ArrayAccess
+                                       ArrayList idxs = new ArrayList();
+                                       foreach (Argument a in Arguments)
+                                       {
+                                               idxs.Add (a.Expr);
+                                       }
+                                       ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
+                                       ArrayAccess aa = new ArrayAccess (ea, expr.Location);
+                                       expr_to_return = aa.DoResolve(ec);
+                                       expr_to_return.eclass = ExprClass.Variable;
+                               }
+                               else
+                               {
+                                       // We can't resolve now, but we
+                                       // have to try to access the array with a call
+                                       // to LateIndexGet/Set in the runtime
+                                       Expression lig_call_expr;
+
+                                       if (!is_left_hand)
+                                               lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexGet", Location.Null);
+                                       else
+                                               lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexSet", Location.Null);
+                                       Expression obj_type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", Location.Null);
+                                       ArrayList adims = new ArrayList();
+
+                                       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;
+                               }
+                       }
+
+                       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>
+               static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
+               {
+                       ILGenerator ig = ec.ig;
+                       int count = arguments.Count - idx;
+                       Argument a = (Argument) arguments [idx];
+                       Type t = a.Expr.Type;
+                       string array_type = t.FullName + "[]";
+                       LocalBuilder array;
+
+                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
+                       IntConstant.EmitInt (ig, count);
+                       ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
+                       ig.Emit (OpCodes.Stloc, array);
+
+                       int top = arguments.Count;
+                       for (int j = idx; j < top; j++){
+                               a = (Argument) arguments [j];
+                               
+                               ig.Emit (OpCodes.Ldloc, array);
+                               IntConstant.EmitInt (ig, j - idx);
+                               a.Emit (ec);
+                               
+                               ArrayAccess.EmitStoreOpcode (ig, t);
+                       }
+                       ig.Emit (OpCodes.Ldloc, array);
+               }
+               
+               /// <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;
+
+                       //
+                       // If we are calling a params method with no arguments, special case it
+                       //
+                       if (arguments == null){
+                               if (pd != null && 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;
+                       }
+
+                       int top = arguments.Count;
+
+                       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;
+                                       }
+                               }
+                                           
+                               a.Emit (ec);
+                       }
+
+                       if (pd != null && pd.Count > top &&
+                           pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
+                               ILGenerator ig = ec.ig;
+
+                               IntConstant.EmitInt (ig, 0);
+                               ig.Emit (OpCodes.Newarr, pd.ParameterType (top).GetElementType ());
+                       }
+               }
+
+               /// <remarks>
+               ///   is_base tells whether we want to force the use of the 'call'
+               ///   opcode instead of using callvirt.  Call is required to call
+               ///   a specific method, while callvirt will always use the most
+               ///   recent method in the vtable.
+               ///
+               ///   is_static tells whether this is an invocation on a static method
+               ///
+               ///   instance_expr is an expression that represents the instance
+               ///   it must be non-null if is_static is false.
+               ///
+               ///   method is the method to invoke.
+               ///
+               ///   Arguments is the list of arguments to pass to the method or constructor.
+               /// </remarks>
+               public static void EmitCall (EmitContext ec, bool is_base,
+                                            bool is_static, Expression instance_expr,
+                                            MethodBase method, ArrayList Arguments, 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.StdLib) 
+                       {
+                               // Replace any calls to the system's System.Array type with calls to
+                               // the newly created one.
+                               if (method == TypeManager.system_int_array_get_length)
+                                       method = TypeManager.int_array_get_length;
+                               else if (method == TypeManager.system_int_array_get_rank)
+                                       method = TypeManager.int_array_get_rank;
+                               else if (method == TypeManager.system_object_array_clone)
+                                       method = TypeManager.object_array_clone;
+                               else if (method == TypeManager.system_int_array_get_length_int)
+                                       method = TypeManager.int_array_get_length_int;
+                               else if (method == TypeManager.system_int_array_get_lower_bound_int)
+                                       method = TypeManager.int_array_get_lower_bound_int;
+                               else if (method == TypeManager.system_int_array_get_upper_bound_int)
+                                       method = TypeManager.int_array_get_upper_bound_int;
+                               else if (method == TypeManager.system_void_array_copyto_array_int)
+                                       method = TypeManager.void_array_copyto_array_int;
+                       }
+
+                       //
+                       // This checks the 'ConditionalAttribute' on the method, and the
+                       // ObsoleteAttribute
+                       //
+                       TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
+                       if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
+                               return;
+                       if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+                               return;
+                       
+                       if (!is_static)
+                       {
+                               if (decl_type.IsValueType)
+                                       struct_call = true;
+                               //
+                               // If this is ourselves, push "this"
+                               //
+                               if (instance_expr == null)
+                               {
+                                       ig.Emit (OpCodes.Ldarg_0);
+                               } 
+                               else 
+                               {
+                                       //
+                                       // Push the instance expression
+                                       //
+                                       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 the expression implements IMemoryLocation, then
+                                                       // we can optimize and use AddressOf on the
+                                                       // return.
+                                                       //
+                                                       // If not we have to use some temporary storage for
+                                                       // it.
+                                                       if (instance_expr is IMemoryLocation)
+                                                       {
+                                                               ((IMemoryLocation)instance_expr).
+                                                                       AddressOf (ec, AddressOp.LoadStore);
+                                                       }
+                                                       else 
+                                                       {
+                                                               Type t = instance_expr.Type;
+                                                               
+                                                               instance_expr.Emit (ec);
+                                                               LocalBuilder temp = ig.DeclareLocal (t);
+                                                               ig.Emit (OpCodes.Stloc, temp);
+                                                               ig.Emit (OpCodes.Ldloca, temp);
+                                                       }
+                                               } 
+                                               else 
+                                               {
+                                                       instance_expr.Emit (ec);
+                                                       ig.Emit (OpCodes.Box, instance_expr.Type);
+                                               } 
+                                       } 
+                                       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) 
+                               {
+                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               } 
+                               else
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                       } 
+                       else 
+                       {
+                               if (method is MethodInfo)
+                                       ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                               else
+                                       ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+                       }
+               }
+               
+               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, loc);
+               }
+               
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+
+                       // 
+                       // Pop the return value if there is one
+                       //
+                       if (method is MethodInfo){
+                               Type ret = ((MethodInfo)method).ReturnType;
+                               if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
+                                       ec.ig.Emit (OpCodes.Pop);
+                       }
+               }
+       }
+
+       //
+       // This class is used to "disable" the code generation for the
+       // temporary variable when initializing value types.
+       //
+       class EmptyAddressOf : EmptyExpression, IMemoryLocation {
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       // nothing
+               }
+       }
+       
+       /// <summary>
+       ///    Implements the new expression 
+       /// </summary>
+       public class New : ExpressionStatement {
+               public readonly ArrayList Arguments;
+               public readonly Expression RequestedType;
+
+               MethodBase method = null;
+
+               //
+               // If set, the new expression is for a value_target, and
+               // we will not leave anything on the stack.
+               //
+               Expression value_target;
+               bool value_target_set = false;
+               public bool isDelegate = false;
+               
+               public New (Expression requested_type, ArrayList arguments, Location l)
+               {
+                       RequestedType = requested_type;
+                       Arguments = arguments;
+                       loc = l;
+               }
+
+               public Expression ValueTypeVariable {
+                       get {
+                               return value_target;
+                       }
+
+                       set {
+                               value_target = value;
+                               value_target_set = true;
+                       }
+               }
+
+               //
+               // This function is used to disable the following code sequence for
+               // value type initialization:
+               //
+               // AddressOf (temporary)
+               // Construct/Init
+               // LoadTemporary
+               //
+               // Instead the provide will have provided us with the address on the
+               // stack to store the results.
+               //
+               static Expression MyEmptyExpression;
+               
+               public void DisableTemporaryValueType ()
+               {
+                       if (MyEmptyExpression == null)
+                               MyEmptyExpression = new EmptyAddressOf ();
+
+                       //
+                       // To enable this, look into:
+                       // test-34 and test-89 and self bootstrapping.
+                       //
+                       // 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)
+               {
+                       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;
+                       
+                       bool IsDelegate = TypeManager.IsDelegateType (type);
+                       
+                       if (IsDelegate)
+                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+
+                       if (type.IsInterface || type.IsAbstract){
+                               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.IsValueType;
+                       eclass = ExprClass.Value;
+
+                       //
+                       // SRE returns a match for .ctor () on structs (the object constructor), 
+                       // so we have to manually ignore it.
+                       //
+                       if (is_struct && Arguments == null)
+                               return this;
+                       
+                       Expression ml;
+                       ml = MemberLookupFinal (ec, type, ".ctor",
+                                               MemberTypes.Constructor,
+                                               AllBindingFlags | BindingFlags.Public, loc);
+
+                       if (ml == null)
+                               return null;
+                       
+                       if (! (ml is MethodGroupExpr)){
+                               if (!is_struct){
+                                       ml.Error118 ("method group");
+                                       return null;
+                               }
+                       }
+
+                       if (ml != null) {
+                               if (Arguments != null){
+                                       foreach (Argument a in Arguments){
+                                               if (!a.Resolve (ec, loc))
+                                                       return null;
+                                       }
+                               }
+
+                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
+                                                                    Arguments, loc);
+                               
+                       }
+
+                       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;
+               }
+
+               //
+               // This DoEmit can be invoked in two contexts:
+               //    * As a mechanism that will leave a value on the stack (new object)
+               //    * As one that wont (init struct)
+               //
+               // You can control whether a value is required on the stack by passing
+               // need_value_on_stack.  The code *might* leave a value on the stack
+               // so it must be popped manually
+               //
+               // If we are dealing with a ValueType, we have a few
+               // situations to deal with:
+               //
+               //    * The target is a ValueType, and we have been provided
+               //      the instance (this is easy, we are being assigned).
+               //
+               //    * The target of New is being passed as an argument,
+               //      to a boxing operation or a function that takes a
+               //      ValueType.
+               //
+               //      In this case, we need to create a temporary variable
+               //      that is the argument of New.
+               //
+               // Returns whether a value is left on the stack
+               //
+               bool DoEmit (EmitContext ec, bool need_value_on_stack)
+               {
+                       bool is_value_type = type.IsValueType;
+                       ILGenerator ig = ec.ig;
+
+                       if (is_value_type){
+                               IMemoryLocation ml;
+
+                               // 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;
+                               ml.AddressOf (ec, AddressOp.Store);
+                       }
+
+                       if (method != null)
+                               Invocation.EmitArguments (ec, method, Arguments);
+
+                       if (is_value_type){
+                               if (method == null)
+                                       ig.Emit (OpCodes.Initobj, type);
+                               else 
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                                if (need_value_on_stack){
+                                        value_target.Emit (ec);
+                                        return true;
+                                }
+                                return false;
+                       } else {
+                               ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+                               return true;
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       DoEmit (ec, true);
+               }
+               
+               public override void EmitStatement (EmitContext ec)
+               {
+                       if (DoEmit (ec, false))
+                               ec.ig.Emit (OpCodes.Pop);
+               }
+       }
+
+       /// <summary>
+       ///   14.5.10.2: Represents an array creation expression.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   There are two possible scenarios here: one is an array creation
+       ///   expression that specifies the dimensions and optionally the
+       ///   initialization data and the other which does not need dimensions
+       ///   specified but where initialization data is mandatory.
+       /// </remarks>
+       public class ArrayCreation : ExpressionStatement {
+               Expression requested_base_type;
+               ArrayList initializers;
+
+               //
+               // The list of Argument types.
+               // This is used to construct the 'newarray' or constructor signature
+               //
+               ArrayList arguments;
+
+               //
+               // Method used to create the array object.
+               //
+               MethodBase new_method = null;
+               
+               Type array_element_type;
+               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 array_data;
+
+               Hashtable bounds;
+
+               //
+               // The number of array initializers that we can handle
+               // via the InitializeArray method - through EmitStaticInitializers
+               //
+               int num_automatic_initializers;
+               
+               public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
+               {
+                       this.requested_base_type = requested_base_type;
+                       this.initializers = initializers;
+                       this.rank = rank;
+                       loc = l;
+
+                       arguments = new ArrayList ();
+
+                       foreach (Expression e in exprs) {
+                               arguments.Add (new Argument (e, Argument.AType.Expression));
+                               num_arguments++;
+                       }
+               }
+
+               public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
+               {
+                       this.requested_base_type = requested_base_type;
+                       this.initializers = initializers;
+                       this.rank = rank;
+                       loc = l;
+
+                       //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+                       //
+                       //string tmp = rank.Substring (rank.LastIndexOf ("["));
+                       //
+                       //dimensions = tmp.Length - 1;
+                       expect_initializers = true;
+               }
+
+               public Expression FormArrayType (Expression base_type, int idx_count, string rank)
+               {
+                       StringBuilder sb = new StringBuilder (rank);
+                       
+                       sb.Append ("[");
+                       for (int i = 1; i < idx_count; i++)
+                               sb.Append (",");
+                       
+                       sb.Append ("]");
+
+                       return new ComposedCast (base_type, sb.ToString (), loc);
+               }
+
+               void Error_IncorrectArrayInitializer ()
+               {
+                       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];
+                               
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                               
+                               if (!(a.Expr is Constant)) {
+                                       Error (150, "A constant value is expected");
+                                       return false;
+                               }
+                               
+                               int value = (int) ((Constant) a.Expr).GetValue ();
+                               
+                               if (value != probe.Count) {
+                                       Error_IncorrectArrayInitializer ();
+                                       return false;
+                               }
+                               
+                               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 (
+                                               ec, tmp, underlying_type, loc);
+                                       
+                                       if (conv == null) 
+                                               return false;
+
+                                       if (conv is StringConstant)
+                                               array_data.Add (conv);
+                                       else if (conv is Constant) {
+                                               array_data.Add (conv);
+                                               num_automatic_initializers++;
+                                       } else
+                                               array_data.Add (conv);
+                               }
+                       }
+
+                       return true;
+               }
+               
+               public void UpdateIndices (EmitContext ec)
+               {
+                       int i = 0;
+                       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));
+
+                                       bounds [i++] =  probe.Count;
+                                       
+                                       probe = (ArrayList) probe [0];
+                                       
+                               } else {
+                                       Expression e = new IntConstant (probe.Count);
+                                       arguments.Add (new Argument (e, Argument.AType.Expression));
+
+                                       bounds [i++] = probe.Count;
+                                       probe = null;
+                               }
+                       }
+
+               }
+               
+               public bool ValidateInitializers (EmitContext ec, Type array_type)
+               {
+                       if (initializers == null) {
+                               if (expect_initializers)
+                                       return false;
+                               else
+                                       return true;
+                       }
+                       
+                       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
+                       //
+                       array_data = new ArrayList ();
+                       bounds = new Hashtable ();
+                       
+                       bool ret;
+
+                       if (arguments != null) {
+                               ret = CheckIndices (ec, initializers, 0, true);
+                               return ret;
+                       } else {
+                               arguments = new ArrayList ();
+
+                               ret = CheckIndices (ec, initializers, 0, false);
+                               
+                               if (!ret)
+                                       return false;
+                               
+                               UpdateIndices (ec);
+                               
+                               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, type))
+                               return null;
+
+                       if (arguments == null)
+                               arg_count = 0;
+                       else {
+                               arg_count = arguments.Count;
+                               foreach (Argument a in arguments){
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+
+                                       Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc);
+                                       if (real_arg == null)
+                                               return null;
+
+                                       a.Expr = real_arg;
+                               }
+                       }
+                       
+                       array_element_type = TypeManager.TypeToCoreType (type.GetElementType ());
+
+                       if (arg_count == 1) {
+                               is_one_dimensional = true;
+                               eclass = ExprClass.Value;
+                               return this;
+                       }
+
+                       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)) {
+                                       ml.Error118 ("method group");
+                                       return null;
+                               }
+                               
+                               if (ml == null) {
+                                       Error (-6, "New invocation: Can not find a constructor for " +
+                                                     "this argument list");
+                                       return null;
+                               }
+                               
+                               new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
+
+                               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) {
+                                       for (int i = 0; i < arg_count; i++)
+                                               args.Add (TypeManager.int32_type);
+                               }
+                               
+                               Type [] arg_types = null;
+
+                               if (args.Count > 0)
+                                       arg_types = new Type [args.Count];
+                               
+                               args.CopyTo (arg_types, 0);
+                               
+                               new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
+                                                           arg_types);
+
+                               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 array_data, Type underlying_type, Location loc)
+               {
+                       int factor;
+                       byte [] data;
+                       byte [] element;
+                       int count = array_data.Count;
+
+                       if (underlying_type.IsEnum)
+                               underlying_type = TypeManager.EnumToUnderlying (underlying_type);
+                       
+                       factor = GetTypeSize (underlying_type);
+                       if (factor == 0)
+                               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 = array_data [i];
+
+                               if (v is EnumConstant)
+                                       v = ((EnumConstant) v).Child;
+                               
+                               if (v is Constant && !(v is StringConstant))
+                                       v = ((Constant) v).GetValue ();
+                               else {
+                                       idx += factor;
+                                       continue;
+                               }
+                               
+                               if (underlying_type == TypeManager.int64_type){
+                                       if (!(v is Expression)){
+                                               long val = (long) v;
+                                               
+                                               for (int j = 0; j < factor; ++j) {
+                                                       data [idx + j] = (byte) (val & 0xFF);
+                                                       val = (val >> 8);
+                                               }
+                                       }
+                               } else if (underlying_type == TypeManager.uint64_type){
+                                       if (!(v is Expression)){
+                                               ulong val = (ulong) v;
+
+                                               for (int j = 0; j < factor; ++j) {
+                                                       data [idx + j] = (byte) (val & 0xFF);
+                                                       val = (val >> 8);
+                                               }
+                                       }
+                               } else if (underlying_type == TypeManager.float_type) {
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((float) v);
+                                                       
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
+                                       }
+                               } else if (underlying_type == TypeManager.double_type) {
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((double) v);
+
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
+                                       }
+                               } else if (underlying_type == TypeManager.char_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((char) v);
+                                               
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.short_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((short) v);
+                                       
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.ushort_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((ushort) v);
+                                       
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.int32_type) {
+                                       if (!(v is Expression)){
+                                               int val = (int) v;
+                                       
+                                               data [idx]   = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) ((val >> 8) & 0xff);
+                                               data [idx+2] = (byte) ((val >> 16) & 0xff);
+                                               data [idx+3] = (byte) (val >> 24);
+                                       }
+                               } else if (underlying_type == TypeManager.uint32_type) {
+                                       if (!(v is Expression)){
+                                               uint val = (uint) v;
+                                       
+                                               data [idx]   = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) ((val >> 8) & 0xff);
+                                               data [idx+2] = (byte) ((val >> 16) & 0xff);
+                                               data [idx+3] = (byte) (val >> 24);
+                                       }
+                               } else if (underlying_type == TypeManager.sbyte_type) {
+                                       if (!(v is Expression)){
+                                               sbyte val = (sbyte) v;
+                                               data [idx] = (byte) val;
+                                       }
+                               } else if (underlying_type == TypeManager.byte_type) {
+                                       if (!(v is Expression)){
+                                               byte val = (byte) v;
+                                               data [idx] = (byte) val;
+                                       }
+                               } else if (underlying_type == TypeManager.bool_type) {
+                                       if (!(v is Expression)){
+                                               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: " + underlying_type);
+
+                                idx += factor;
+                       }
+
+                       return data;
+               }
+
+               //
+               // Emits the initializers for the array
+               //
+               void EmitStaticInitializers (EmitContext ec, bool is_expression)
+               {
+                       //
+                       // First, the static data
+                       //
+                       FieldBuilder fb;
+                       ILGenerator ig = ec.ig;
+                       
+                       byte [] data = MakeByteBlob (array_data, underlying_type, loc);
+
+                       fb = RootContext.MakeStaticData (data);
+
+                       if (is_expression)
+                               ig.Emit (OpCodes.Dup);
+                       ig.Emit (OpCodes.Ldtoken, fb);
+                       ig.Emit (OpCodes.Call,
+                                TypeManager.void_initializearray_array_fieldhandle);
+               }
+               
+               //
+               // Emits pieces of the array that can not be computed at compile
+               // time (variables and string locations).
+               //
+               // This always expect the top value on the stack to be the array
+               //
+               void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+               {
+                       ILGenerator ig = ec.ig;
+                       int dims = bounds.Count;
+                       int [] current_pos = new int [dims];
+                       int top = array_data.Count;
+                       LocalBuilder temp = ig.DeclareLocal (type);
+
+                       ig.Emit (OpCodes.Stloc, temp);
+
+                       MethodInfo set = null;
+
+                       if (dims != 1){
+                               Type [] args;
+                               ModuleBuilder mb = null;
+                               mb = CodeGen.ModuleBuilder;
+                               args = new Type [dims + 1];
+
+                               int j;
+                               for (j = 0; j < dims; j++)
+                                       args [j] = TypeManager.int32_type;
+
+                               args [j] = array_element_type;
+                               
+                               set = mb.GetArrayMethod (
+                                       type, "Set",
+                                       CallingConventions.HasThis | CallingConventions.Standard,
+                                       TypeManager.void_type, args);
+                       }
+                       
+                       for (int i = 0; i < top; i++){
+
+                               Expression e = null;
+
+                               if (array_data [i] is Expression)
+                                       e = (Expression) array_data [i];
+
+                               if (e != null) {
+                                       //
+                                       // Basically we do this for string literals and
+                                       // other non-literal expressions
+                                       //
+                                       if (e is StringConstant || !(e is Constant) ||
+                                           num_automatic_initializers <= 2) {
+                                               Type etype = e.Type;
+                                               
+                                               ig.Emit (OpCodes.Ldloc, temp);
+
+                                               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 ((dims == 1) &&
+                                                   etype.IsSubclassOf (TypeManager.value_type) &&
+                                                   (!TypeManager.IsBuiltinType (etype) ||
+                                                    etype == TypeManager.decimal_type)) {
+                                                       if (e is New){
+                                                               New n = (New) e;
+
+                                                               //
+                                                               // Let new know that we are providing
+                                                               // the address where to store the results
+                                                               //
+                                                               n.DisableTemporaryValueType ();
+                                                       }
+                                                                            
+                                                       ig.Emit (OpCodes.Ldelema, etype);
+                                               }
+
+                                               e.Emit (ec);
+                                               
+                                               if (dims == 1)
+                                                       ArrayAccess.EmitStoreOpcode (ig, array_element_type);
+                                               else 
+                                                       ig.Emit (OpCodes.Call, set);
+                                       }
+                               }
+                               
+                               //
+                               // Advance counter
+                               //
+                               for (int j = dims - 1; j >= 0; j--){
+                                       current_pos [j]++;
+                                       if (current_pos [j] < (int) bounds [j])
+                                               break;
+                                       current_pos [j] = 0;
+                               }
+                       }
+
+                       if (is_expression)
+                               ig.Emit (OpCodes.Ldloc, temp);
+               }
+
+               void EmitArrayArguments (EmitContext ec)
+               {
+                       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)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       EmitArrayArguments (ec);
+                       if (is_one_dimensional)
+                               ig.Emit (OpCodes.Newarr, array_element_type);
+                       else {
+                               if (is_builtin_type) 
+                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
+                               else 
+                                       ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
+                       }
+                       
+                       if (initializers != null){
+                               //
+                               // FIXME: Set this variable correctly.
+                               // 
+                               bool dynamic_initializers = true;
+
+                               if (underlying_type != TypeManager.string_type &&
+                                   underlying_type != TypeManager.object_type) {
+                                       if (num_automatic_initializers > 2)
+                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+                               }
+                               
+                               if (dynamic_initializers)
+                                       EmitDynamicInitializers (ec, !is_statement);
+                       }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       DoEmit (ec, false);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       DoEmit (ec, true);
+               }
+               
+       }
+       
+       /// <summary>
+       ///   Represents the 'this' construct
+       /// </summary>
+       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){
+                               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){
+                               Error (1604, "Cannot assign to 'this'");
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       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)
+               {
+                       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)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+
+                       // FIMXE
+                       // FIGURE OUT WHY LDARG_S does not work
+                       //
+                       // consider: struct X { int val; int P { set { val = value; }}}
+                       //
+                       // Yes, this looks very bad. Look at 'NOTAS' for
+                       // an explanation.
+                       // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
+               }
+       }
+
+       /// <summary>
+       ///   Implements the typeof operator
+       /// </summary>
+       public class TypeOf : Expression {
+               public readonly Expression QueriedType;
+               Type typearg;
+               
+               public TypeOf (Expression queried_type, Location l)
+               {
+                       QueriedType = queried_type;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
+
+                       if (typearg == null)
+                               return null;
+
+                       type = TypeManager.type_type;
+                       eclass = ExprClass.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldtoken, typearg);
+                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+               }
+
+               public Type TypeArg { 
+                       get { return typearg; }
+               }
+       }
+
+       /// <summary>
+       ///   Implements the sizeof expression
+       /// </summary>
+       public class SizeOf : Expression {
+               public readonly Expression QueriedType;
+               Type type_queried;
+               
+               public SizeOf (Expression queried_type, Location l)
+               {
+                       this.QueriedType = queried_type;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       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;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int size = GetTypeSize (type_queried);
+
+                       if (size == 0)
+                               ec.ig.Emit (OpCodes.Sizeof, type_queried);
+                       else
+                               IntConstant.EmitInt (ec.ig, size);
+               }
+       }
+
+       /// <summary>
+       ///   Implements the member access expression
+       /// </summary>
+       public class MemberAccess : Expression, ITypeExpression {
+               public readonly string Identifier;
+               Expression expr;
+               Expression member_lookup;
+               
+               public MemberAccess (Expression expr, string id, Location l)
+               {
+                       this.expr = expr;
+                       Identifier = id;
+                       loc = l;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               static void error176 (Location loc, string name)
+               {
+                       Report.Error (176, loc, "Static member '" +
+                                     name + "' cannot be accessed " +
+                                     "with an instance reference, qualify with a " +
+                                     "type name instead");
+               }
+
+               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
+               {
+                       if (left_original == null)
+                               return false;
+
+                       if (!(left_original is SimpleName))
+                               return false;
+
+                       SimpleName sn = (SimpleName) left_original;
+
+                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
+                       if (t != null)
+                               return true;
+
+                       return false;
+               }
+               
+               public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
+                                                             Expression left, Location loc,
+                                                             Expression left_original)
+               {
+                       bool left_is_type, left_is_explicit;
+
+                       // 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;
+
+                               // 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){
+                               FieldExpr fe = (FieldExpr) member_lookup;
+                               FieldInfo fi = fe.FieldInfo;
+                               Type decl_type = fi.DeclaringType;
+                               
+                               if (fi is FieldBuilder) {
+                                       Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
+                                       
+                                       if (c != null) {
+                                               object o = c.LookupConstantValue (ec);
+                                               object real_value = ((Constant) c.Expr).GetValue ();
+
+                                               return Constantify (real_value, fi.FieldType);
+                                       }
+                               }
+
+                               if (fi.IsLiteral) {
+                                       Type t = fi.FieldType;
+                                       
+                                       object o;
+
+                                       if (fi is FieldBuilder)
+                                               o = TypeManager.GetValue ((FieldBuilder) fi);
+                                       else
+                                               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); 
+
+                                               Enum en = TypeManager.LookupEnum (decl_type);
+
+                                               Constant c;
+                                               if (en != null) {
+                                                       c = Constantify (o, en.UnderlyingType);
+                                                       return new EnumConstant (c, en.UnderlyingType);
+                                               }
+                                               else {
+                                                       c = Constantify (o, enum_member.Type);
+                                                       return new EnumConstant (c, enum_member.Type);
+                                               }
+                                               
+                                               
+                                       }
+                                       
+                                       Expression exp = Constantify (o, t);
+
+                                       if (left_is_explicit && !left_is_type) {
+                                               error176 (loc, fe.FieldInfo.Name);
+                                               return null;
+                                       }
+                                       
+                                       return exp;
+                               }
+
+                               if (fi.FieldType.IsPointer && !ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+                       }
+
+                       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 (ee.EventInfo.DeclaringType == ec.ContainerType) {
+                                       MemberInfo mi = GetFieldFromEvent (ee);
+
+                                       if (mi == null) {
+                                               //
+                                               // If this happens, then we have an event with its own
+                                               // accessors and private field etc so there's no need
+                                               // to transform ourselves : we should instead flag an error
+                                               //
+                                               Assign.error70 (ee.EventInfo, loc);
+                                               return null;
+                                       }
+
+                                       Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
+                                       
+                                       if (ml == null) {
+                                               Report.Error (-200, loc, "Internal error!!");
+                                               return null;
+                                       }
+                                       
+                                       return ResolveMemberAccess (ec, ml, left, loc, left_original);
+                               }
+                       }
+                       
+                       if (member_lookup is IMemberExpr) {
+                               IMemberExpr me = (IMemberExpr) member_lookup;
+
+                               if (left_is_type){
+                                       MethodGroupExpr mg = me as MethodGroupExpr;
+                                       if ((mg != null) && left_is_explicit && left.Type.IsInterface)
+                                               mg.IsExplicitImpl = left_is_explicit;
+
+                                       if (!me.IsStatic){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
+
+                                               SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
+                                               return null;
+                                       }
+
+                               } else {
+                                       if (!me.IsInstance){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
+
+                                               /*if (left_is_explicit) {
+                                                       error176 (loc, me.Name);
+                                                       return null;
+                                               }*/
+                                       }
+
+                                       //
+                                       // Since we can not check for instance objects in SimpleName,
+                                       // becaue of the rule that allows types and variables to share
+                                       // the name (as long as they can be de-ambiguated later, see 
+                                       // IdenticalNameAndTypeName), we have to check whether left 
+                                       // is an instance variable in a static context
+                                       //
+                                       // However, if the left-hand value is explicitly given, then
+                                       // it is already our instance expression, so we aren't in
+                                       // static context.
+                                       //
+
+                                       if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
+                                               IMemberExpr mexp = (IMemberExpr) left;
+
+                                               if (!mexp.IsStatic){
+                                                       SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name);
+                                                       return null;
+                                               }
+                                       }
+
+                                       me.InstanceExpression = left;
+                               }
+
+                               return member_lookup;
+                       }
+
+                       if (member_lookup is TypeExpr){
+                               member_lookup.Resolve (ec, ResolveFlags.Type);
+                               return member_lookup;
+                       }
+                       
+                       Console.WriteLine ("Left is: " + left);
+                       Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
+                       Environment.Exit (0);
+                       return null;
+               }
+               
+               public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags)
+               {
+                       if (type != null)
+                               throw new Exception ();
+                       //
+                       // 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.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
+
+                       if (expr == null)
+                               return null;
+
+                       if (expr is SimpleName){
+                               SimpleName child_expr = (SimpleName) expr;
+
+                               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);
+                       }
+                                       
+                       int errors = Report.Errors;
+                       
+                       Type expr_type = expr.Type;
+
+                       if (expr_type.IsPointer){
+                               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)
+                       {
+                               // 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 |
+                                       BindingFlags.NonPublic, Identifier);
+                                       
+                               if (lookup == null)
+                                       Error (30456, "'" + expr_type + "' does not contain a definition for '" + Identifier + "'");
+                               else
+                               {
+                                       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;
+                       }
+
+                       if ((expr is TypeExpr) && (expr_type.IsSubclassOf (TypeManager.enum_type)))     {
+                               Enum en = TypeManager.LookupEnum (expr_type);
+                               
+                               if (en != null) {
+                                       object value = en.LookupEnumValue (ec, Identifier, loc);
+                                       expr_type = TypeManager.int32_type;
+                                       if (value != null) {
+                                               Constant c = Constantify (value, en.UnderlyingType);
+                                               return new EnumConstant (c, en.UnderlyingType);
+                                       }
+                               }
+                       }
+
+                       if (member_lookup is TypeExpr){
+                               member_lookup.Resolve (ec, ResolveFlags.Type);
+
+                               return member_lookup;
+                       } else if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
+                               return null;
+                       
+                       member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
+                       if (member_lookup == null)
+                               return null;
+
+                       // The following DoResolve/DoResolveLValue will do the definite assignment
+                       // check.
+                       if (right_side != null)
+                               member_lookup = member_lookup.DoResolveLValue (ec, right_side);
+                       else
+                               member_lookup = member_lookup.DoResolve (ec);
+
+                       return member_lookup;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolve (ec, null, ResolveFlags.VariableOrValue |
+                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
+                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+               }
+
+               public Expression DoResolveType (EmitContext ec)
+               {
+                       return DoResolve (ec, null, ResolveFlags.Type);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should not happen");
+               }
+
+               public override string ToString ()
+               {
+                       return expr + "." + Identifier;
+               }
+       }
+
+       
+       
+       /// <summary>
+       ///   Implements checked expressions
+       /// </summary>
+       public class CheckedExpr : Expression {
+
+               public Expression Expr;
+
+               public CheckedExpr (Expression e, Location l)
+               {
+                       Expr = e;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.ConstantCheckState = true;
+                       Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
+                       
+                       if (Expr == null)
+                               return null;
+
+                       if (Expr is Constant)
+                               return Expr;
+                       
+                       eclass = Expr.eclass;
+                       type = Expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
+                       
+                       ec.CheckState = true;
+                       ec.ConstantCheckState = true;
+                       Expr.Emit (ec);
+                       ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
+               }
+               
+       }
+
+       /// <summary>
+       ///   Implements the unchecked expression
+       /// </summary>
+       public class UnCheckedExpr : Expression {
+
+               public Expression Expr;
+
+               public UnCheckedExpr (Expression e, Location l)
+               {
+                       Expr = e;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.ConstantCheckState = false;
+                       Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
+
+                       if (Expr == null)
+                               return null;
+
+                       if (Expr is Constant)
+                               return Expr;
+                       
+                       eclass = Expr.eclass;
+                       type = Expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
+                       
+                       ec.CheckState = false;
+                       ec.ConstantCheckState = false;
+                       Expr.Emit (ec);
+                       ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
+               }
+               
+       }
+
+       /// <summary>
+       ///   An Element Access expression.
+       ///
+       ///   During semantic analysis these are transformed into 
+       ///   IndexerAccess or ArrayAccess 
+       /// </summary>
+       public class ElementAccess : Expression {
+               public ArrayList  Arguments;
+               public Expression Expr;
+               
+               public ElementAccess (Expression e, ArrayList e_list, Location l)
+               {
+                       Expr = e;
+
+                       loc  = l;
+                       
+                       if (e_list == null)
+                               return;
+                       
+                       Arguments = new ArrayList ();
+                       foreach (Expression tmp in e_list)
+                               Arguments.Add (new Argument (tmp, Argument.AType.Expression));
+                       
+               }
+
+               bool CommonResolve (EmitContext ec)
+               {
+                       Expr = Expr.Resolve (ec);
+
+                       if (Expr == null) 
+                               return false;
+
+                       if (Arguments == null)
+                               return false;
+
+                       foreach (Argument a in Arguments){
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                       }
+
+                       return true;
+               }
+
+               Expression MakePointerAccess ()
+               {
+                       Type t = Expr.Type;
+
+                       if (t == TypeManager.void_ptr_type){
+                               Error (
+                                       242,
+                                       "The array index operation is not valid for void pointers");
+                               return null;
+                       }
+                       if (Arguments.Count != 1){
+                               Error (
+                                       196,
+                                       "A pointer must be indexed by a single value");
+                               return null;
+                       }
+                       Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr,
+                                                             t, loc);
+                       return new Indirection (p, loc);
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       //
+                       // We perform some simple tests, and then to "split" the emit and store
+                       // code we create an instance of a different class, and return that.
+                       //
+                       // I am experimenting with this pattern.
+                       //
+                       Type t = Expr.Type;
+
+                       if (t.IsArray)
+                               return (new ArrayAccess (this, loc)).Resolve (ec);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
+                       else
+                               return (new IndexerAccess (this, loc)).Resolve (ec);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       Type t = Expr.Type;
+                       if (t.IsArray)
+                               return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
+                       else
+                               return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be reached");
+               }
+       }
+
+       /// <summary>
+       ///   Implements array access 
+       /// </summary>
+       public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
+               //
+               // Points to our "data" repository
+               //
+               ElementAccess ea;
+
+               LocalTemporary [] cached_locations;
+
+               public ArrayAccess (ElementAccess ea_data, Location l)
+               {
+                       ea = ea_data;
+                       eclass = ExprClass.Variable;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       ExprClass eclass = ea.Expr.eclass;
+
+#if false
+                       // As long as the type is valid
+                       if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
+                             eclass == ExprClass.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){
+                               ea.Error (22,
+                                         "Incorrect number of indexes for array " +
+                                         " expected: " + t.GetArrayRank () + " got: " +
+                                         ea.Arguments.Count);
+                               return null;
+                       }
+                       type = TypeManager.TypeToCoreType (t.GetElementType ());
+                       if (type.IsPointer && !ec.InUnsafe){
+                               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;
+
+                       return this;
+               }
+
+               /// <summary>
+               ///    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_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 || type == TypeManager.char_type)
+                               ig.Emit (OpCodes.Ldelem_U2);
+                       else if (type == TypeManager.int32_type)
+                               ig.Emit (OpCodes.Ldelem_I4);
+                       else if (type == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Ldelem_U4);
+                       else if (type == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Ldelem_I8);
+                       else if (type == TypeManager.int64_type)
+                               ig.Emit (OpCodes.Ldelem_I8);
+                       else if (type == TypeManager.float_type)
+                               ig.Emit (OpCodes.Ldelem_R4);
+                       else if (type == TypeManager.double_type)
+                               ig.Emit (OpCodes.Ldelem_R8);
+                       else if (type == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Ldelem_I);
+                       else if (type.IsValueType){
+                               ig.Emit (OpCodes.Ldelema, type);
+                               ig.Emit (OpCodes.Ldobj, type);
+                       } else 
+                               ig.Emit (OpCodes.Ldelem_Ref);
+               }
+
+               /// <summary>
+               ///    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);
+                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type || t == TypeManager.char_type)
+                               ig.Emit (OpCodes.Stelem_I2);
+                       else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Stelem_I4);
+                       else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Stelem_I8);
+                       else if (t == TypeManager.float_type)
+                               ig.Emit (OpCodes.Stelem_R4);
+                       else if (t == TypeManager.double_type)
+                               ig.Emit (OpCodes.Stelem_R8);
+                       else if (t == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Stelem_I);
+                       else if (t.IsValueType){
+                               ig.Emit (OpCodes.Stobj, t);
+                       } else
+                               ig.Emit (OpCodes.Stelem_Ref);
+               }
+
+               MethodInfo FetchGetMethod ()
+               {
+                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       int arg_count = ea.Arguments.Count;
+                       Type [] args = new Type [arg_count];
+                       MethodInfo get;
+                       
+                       for (int i = 0; i < arg_count; i++){
+                               //args [i++] = a.Type;
+                               args [i] = TypeManager.int32_type;
+                       }
+                       
+                       get = mb.GetArrayMethod (
+                               ea.Expr.Type, "Get",
+                               CallingConventions.HasThis |
+                               CallingConventions.Standard,
+                               type, args);
+                       return get;
+               }
+                               
+
+               MethodInfo FetchAddressMethod ()
+               {
+                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       int arg_count = ea.Arguments.Count;
+                       Type [] args = new Type [arg_count];
+                       MethodInfo address;
+                       string ptr_type_name;
+                       Type ret_type;
+                       
+                       ptr_type_name = type.FullName + "&";
+                       ret_type = Type.GetType (ptr_type_name);
+                       
+                       //
+                       // It is a type defined by the source code we are compiling
+                       //
+                       if (ret_type == null){
+                               ret_type = mb.GetType (ptr_type_name);
+                       }
+
+                       for (int i = 0; i < arg_count; i++){
+                               //args [i++] = a.Type;
+                               args [i] = TypeManager.int32_type;
+                       }
+                       
+                       address = mb.GetArrayMethod (
+                               ea.Expr.Type, "Address",
+                               CallingConventions.HasThis |
+                               CallingConventions.Standard,
+                               ret_type, args);
+
+                       return address;
+               }
+
+               //
+               // Load the array arguments into the stack.
+               //
+               // If we have been requested to cache the values (cached_locations array
+               // initialized), then load the arguments the first time and store them
+               // in locals.  otherwise load from local variables.
+               //
+               void LoadArrayAndArguments (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (cached_locations == null){
+                               ea.Expr.Emit (ec);
+                               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;
+                       }
+
+                       if (cached_locations [0] == null){
+                               cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
+                               ea.Expr.Emit (ec);
+                               ig.Emit (OpCodes.Dup);
+                               cached_locations [0].Store (ec);
+                               
+                               int j = 1;
+                               
+                               foreach (Argument a in ea.Arguments){
+                                       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++;
+                               }
+                               return;
+                       }
+
+                       foreach (LocalTemporary lt in cached_locations)
+                               lt.Emit (ec);
+               }
+
+               public new void CacheTemporaries (EmitContext ec)
+               {
+                       cached_locations = new LocalTemporary [ea.Arguments.Count + 1];
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+
+                       LoadArrayAndArguments (ec);
+                       
+                       if (rank == 1)
+                               EmitLoadOpcode (ig, type);
+                       else {
+                               MethodInfo method;
+                               
+                               method = FetchGetMethod ();
+                               ig.Emit (OpCodes.Call, method);
+                       }
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+                       Type t = source.Type;
+
+                       LoadArrayAndArguments (ec);
+
+                       //
+                       // The stobj opcode used by value types will need
+                       // an address on the stack, not really an array/array
+                       // pair
+                       //
+                       if (rank == 1){
+                               if (t == TypeManager.enum_type || t == TypeManager.decimal_type ||
+                                   (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t)))
+                                       ig.Emit (OpCodes.Ldelema, t);
+                       }
+                       
+                       source.Emit (ec);
+
+                       if (rank == 1)
+                               EmitStoreOpcode (ig, t);
+                       else {
+                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               int arg_count = ea.Arguments.Count;
+                               Type [] args = new Type [arg_count + 1];
+                               MethodInfo set;
+                               
+                               for (int i = 0; i < arg_count; i++){
+                                       //args [i++] = a.Type;
+                                       args [i] = TypeManager.int32_type;
+                               }
+
+                               args [arg_count] = type;
+                               
+                               set = mb.GetArrayMethod (
+                                       ea.Expr.Type, "Set",
+                                       CallingConventions.HasThis |
+                                       CallingConventions.Standard,
+                                       TypeManager.void_type, args);
+                               
+                               ig.Emit (OpCodes.Call, set);
+                       }
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+
+                       LoadArrayAndArguments (ec);
+
+                       if (rank == 1){
+                               ig.Emit (OpCodes.Ldelema, type);
+                       } else {
+                               MethodInfo address = FetchAddressMethod ();
+                               ig.Emit (OpCodes.Call, address);
+                       }
+               }
+       }
+
+       
+       class Indexers {
+               public ArrayList getters, setters;
+               static Hashtable map;
+
+               static Indexers ()
+               {
+                       map = new Hashtable ();
+               }
+
+               Indexers (MemberInfo [] mi)
+               {
+                       foreach (PropertyInfo property in mi){
+                               MethodInfo get, set;
+                               
+                               get = property.GetGetMethod (true);
+                               if (get != null){
+                                       if (getters == null)
+                                               getters = new ArrayList ();
+
+                                       getters.Add (get);
+                               }
+                               
+                               set = property.GetSetMethod (true);
+                               if (set != null){
+                                       if (setters == null)
+                                               setters = new ArrayList ();
+                                       setters.Add (set);
+                               }
+                       }
+               }
+
+               static private Indexers GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
+               {
+                       Indexers ix = (Indexers) map [lookup_type];
+                       
+                       if (ix != null)
+                               return ix;
+
+                       string p_name = TypeManager.IndexerPropertyName (lookup_type);
+
+                       MemberInfo [] mi = TypeManager.MemberLookup (
+                               caller_type, lookup_type, MemberTypes.Property,
+                               BindingFlags.Public | BindingFlags.Instance, p_name);
+
+                       if (mi == null || mi.Length == 0)
+                               return null;
+
+                       ix = new Indexers (mi);
+                       map [lookup_type] = ix;
+
+                       return ix;
+               }
+               
+               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
+               {
+                       Indexers ix = (Indexers) map [lookup_type];
+                       
+                       if (ix != null)
+                               return ix;
+
+                       ix = GetIndexersForTypeOrInterface (caller_type, lookup_type);
+                       if (ix != null)
+                               return ix;
+
+                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+                       if (ifaces != null) {
+                               foreach (Type itype in ifaces) {
+                                       ix = GetIndexersForTypeOrInterface (caller_type, itype);
+                                       if (ix != null)
+                                               return ix;
+                               }
+                       }
+
+                       Report.Error (21, loc,
+                                     "Type '" + TypeManager.MonoBASIC_Name (lookup_type) +
+                                     "' does not have any indexers defined");
+                       return null;
+               }
+       }
+
+       /// <summary>
+       ///   Expressions that represent an indexer call.
+       /// </summary>
+       public class IndexerAccess : Expression, IAssignMethod {
+               //
+               // Points to our "data" repository
+               //
+               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, Location loc)
+                       : this (ea.Expr, false, loc)
+               {
+                       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)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       //
+                       // 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 (
+                                       current_type, indexer_type, loc);
+
+                       //
+                       // Step 2: find the proper match
+                       //
+                       if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)
+                               get = (MethodInfo) Invocation.OverloadResolve (
+                                       ec, new MethodGroupExpr (ilist.getters, loc), arguments, loc);
+
+                       if (get == null){
+                               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 (loc);
+                               return null;
+                       }
+                       
+                       eclass = ExprClass.IndexerAccess;
+                       return this;
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       Type right_type = right_side.Type;
+
+                       if (ilist == null)
+                               ilist = Indexers.GetIndexersForType (
+                                       current_type, indexer_type, loc);
+
+                       if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
+                               set_arguments = (ArrayList) arguments.Clone ();
+                               set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
+
+                               set = (MethodInfo) Invocation.OverloadResolve (
+                                       ec, new MethodGroupExpr (ilist.setters, loc), set_arguments, loc);
+                       }
+                       
+                       if (set == null){
+                               Error (200, "indexer X.this [" + TypeManager.MonoBASIC_Name (right_type) +
+                                      "] lacks a 'set' accessor");
+                               return null;
+                       }
+
+                       type = TypeManager.void_type;
+                       eclass = ExprClass.IndexerAccess;
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       Invocation.EmitCall (ec, false, false, instance_expr, get, arguments, loc);
+               }
+
+               //
+               // source is ignored, because we already have a copy of it from the
+               // LValue resolution and we have already constructed a pre-cached
+               // version of the arguments (ea.set_arguments);
+               //
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       Invocation.EmitCall (ec, false, false, instance_expr, set, set_arguments, loc);
+               }
+       }
+
+       /// <summary>
+       ///   The base operator for method names
+       /// </summary>
+       public class BaseAccess : Expression {
+               public string member;
+               
+               public BaseAccess (string member, Location l)
+               {
+                       this.member = member;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression member_lookup;
+                       Type current_type = ec.ContainerType;
+                       Type base_type = current_type.BaseType;
+                       Expression e;
+
+                       if (ec.IsStatic){
+                               Error (1511, "Keyword MyBase is not allowed in static method");
+                               return null;
+                       }
+                       
+                       if (member == "New")
+                               member = ".ctor";
+                       
+                       member_lookup = MemberLookup (ec, base_type, base_type, member,
+                                                     AllMemberTypes, AllBindingFlags, loc);
+
+                       if (member_lookup == null) {
+                               Error (30456,
+                                             TypeManager.MonoBASIC_Name (base_type) + " does not " +
+                                             "contain a definition for '" + member + "'");
+                               return null;
+                       }
+
+                       Expression left;
+                       
+                       if (ec.IsStatic)
+                               left = new TypeExpr (base_type, loc);
+                       else
+                               left = ec.This;
+                       
+                       e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
+
+                       if (e is PropertyExpr){
+                               PropertyExpr pe = (PropertyExpr) e;
+
+                               pe.IsBase = true;
+                       }
+
+                       return e;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be called"); 
+               }
+       }
+
+       /// <summary>
+       ///   The base indexer operator
+       /// </summary>
+       public class BaseIndexerAccess : IndexerAccess {
+               public BaseIndexerAccess (ArrayList args, Location loc)
+                       : base (null, true, loc)
+               {
+                       arguments = new ArrayList ();
+                       foreach (Expression tmp in args)
+                               arguments.Add (new Argument (tmp, Argument.AType.Expression));
+               }
+
+               protected override bool CommonResolve (EmitContext ec)
+               {
+                       instance_expr = ec.This;
+
+                       current_type = ec.ContainerType.BaseType;
+                       indexer_type = current_type;
+
+                       foreach (Argument a in arguments){
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                       }
+
+                       return true;
+               }
+       }
+       
+       /// <summary>
+       ///   This class exists solely to pass the Type around and to be a dummy
+       ///   that can be passed to the conversion functions (this is used by
+       ///   foreach implementation to typecast the object return value from
+       ///   get_Current into the proper type.  All code has been generated and
+       ///   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).
+       /// </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)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // nothing, as we only exist to not do anything.
+               }
+
+               //
+               // This is just because we might want to reuse this bad boy
+               // instead of creating gazillions of EmptyExpressions.
+               // (CanConvertImplicit uses it)
+               //
+               public void SetType (Type t)
+               {
+                       type = t;
+               }
+       }
+
+       public class UserCast : Expression {
+               MethodBase 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)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       source.Emit (ec);
+                       
+                       if (method is MethodInfo)
+                               ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       else
+                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+
+               }
+       }
+
+       // <summary>
+       //   This class is used to "construct" the type during a typecast
+       //   operation.  Since the Type.GetType class in .NET can parse
+       //   the type specification, we just use this to construct the type
+       //   one bit at a time.
+       // </summary>
+       public class ComposedCast : Expression, ITypeExpression {
+               Expression left;
+               string dim;
+               
+               public ComposedCast (Expression left, string dim, Location l)
+               {
+                       this.left = left;
+                       this.dim = dim;
+                       loc = l;
+               }
+
+               public Expression DoResolveType (EmitContext ec)
+               {
+                       Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
+                       if (ltype == null)
+                               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;
+                       }
+
+                       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;
+               }
+       }
+
+       //
+       // This class is used to represent the address of an array, used
+       // only by the Fixed statement, this is like the C "&a [0]" construct.
+       //
+       public class ArrayPtr : Expression {
+               Expression array;
+               
+               public ArrayPtr (Expression array, Location l)
+               {
+                       Type array_type = array.Type.GetElementType ();
+
+                       this.array = array;
+                       
+                       string array_ptr_type_name = array_type.FullName + "*";
+                       
+                       type = Type.GetType (array_ptr_type_name);
+                       if (type == null){
+                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               
+                               type = mb.GetType (array_ptr_type_name);
+                       }
+
+                       eclass = ExprClass.Value;
+                       loc = l;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       array.Emit (ec);
+                       IntLiteral.EmitInt (ig, 0);
+                       ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+       }
+
+       //
+       // Used by the fixed statement
+       //
+       public class StringPtr : Expression {
+               LocalBuilder b;
+               
+               public StringPtr (LocalBuilder b, Location l)
+               {
+                       this.b = b;
+                       eclass = ExprClass.Value;
+                       type = TypeManager.char_ptr_type;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldloc, b);
+                       ig.Emit (OpCodes.Conv_I);
+                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
+                       ig.Emit (OpCodes.Add);
+               }
+       }
+       
+       //
+       // Implements the 'stackalloc' keyword
+       //
+       public class StackAlloc : Expression {
+               Type otype;
+               Expression t;
+               Expression count;
+               
+               public StackAlloc (Expression type, Expression count, Location l)
+               {
+                       t = type;
+                       this.count = count;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       count = count.Resolve (ec);
+                       if (count == null)
+                               return null;
+                       
+                       if (count.Type != TypeManager.int32_type){
+                               count = ConvertImplicitRequired (ec, count, TypeManager.int32_type, loc);
+                               if (count == null)
+                                       return null;
+                       }
+
+                       if (ec.InCatch || ec.InFinally){
+                               Error (255,
+                                             "stackalloc can not be used in a catch or finally block");
+                               return null;
+                       }
+
+                       otype = ec.DeclSpace.ResolveType (t, false, loc);
+
+                       if (otype == null)
+                               return null;
+
+                       if (!TypeManager.VerifyUnManaged (otype, loc))
+                               return null;
+
+                       string ptr_name = otype.FullName + "*";
+                       type = Type.GetType (ptr_name);
+                       if (type == null){
+                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               
+                               type = mb.GetType (ptr_name);
+                       }
+                       eclass = ExprClass.Value;
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int size = GetTypeSize (otype);
+                       ILGenerator ig = ec.ig;
+                               
+                       if (size == 0)
+                               ig.Emit (OpCodes.Sizeof, otype);
+                       else
+                               IntConstant.EmitInt (ig, size);
+                       count.Emit (ec);
+                       ig.Emit (OpCodes.Mul);
+                       ig.Emit (OpCodes.Localloc);
+               }
+       }
+}