fix for different results message
[mono.git] / mcs / mbas / expression.cs
index fa4e2f9983f693a5eae12c508f81349dabe297cb..8a9c2bbc3c0c49ef297ab18053b8519123f152dd 100644 (file)
@@ -3,6 +3,8 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Manjula GHM (mmanjula@novell.com)
+//   Satya Sudha K (ksathyasudha@novell.com)
 //
 // (C) 2001 Ximian, Inc.
 //
@@ -112,11 +114,11 @@ namespace Mono.MonoBASIC {
                        case Operator.UnaryNegation:
                                return "-";
                        case Operator.LogicalNot:
-                               return "!";
+                               return "Not";
                        case Operator.OnesComplement:
                                return "~";
                        case Operator.AddressOf:
-                               return "&";
+                               return "AddressOf";
                        case Operator.Indirection:
                                return "*";
                        }
@@ -141,7 +143,7 @@ namespace Mono.MonoBASIC {
                void Error23 (Type t)
                {
                        Error (
-                               23, "Operator " + OperName (Oper) +
+                               30311, "Operator " + OperName (Oper) +
                                " cannot be applied to operand of type '" +
                                TypeManager.MonoBASIC_Name (t) + "'");
                }
@@ -271,12 +273,27 @@ namespace Mono.MonoBASIC {
                {
                        Type expr_type = Expr.Type;
 
+                       Expression mg;
+                       string op_name;
+                       if (Oper == Operator.LogicalNot && expr_type != TypeManager.bool_type) 
+                               Oper = Operator.OnesComplement;
+
+
+                       if ((expr_type == TypeManager.string_type) &&
+                           (Oper == Operator.UnaryPlus ||
+                            Oper == Operator.UnaryNegation)) {
+
+                               Expr = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
+                               if (Expr == null) {
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+                               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);
@@ -322,40 +339,39 @@ namespace Mono.MonoBASIC {
                                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;
+                               if (expr_type == TypeManager.string_type ||
+                                   expr_type == TypeManager.decimal_type ||
+                                   expr_type == TypeManager.double_type ||
+                                   expr_type == TypeManager.float_type) {
+                                       if ((Expr = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc)) == null) {
+                                               Error23 (Expr.Type);
+                                               return null;
                                        }
-                                       Error23 (expr_type);
-                                       return null;
+                                       expr_type = Expr.Type;
+                               }
+
+                               if (expr_type == TypeManager.int64_type) {
+                                       type = expr_type;
+                                       return this;
+                               }
+                               if (expr_type == TypeManager.byte_type ||
+                                   expr_type == TypeManager.short_type ||
+                                   expr_type == TypeManager.int32_type) {
+                                       type = TypeManager.int32_type;
+                                       return this;
+                               }
+
+                               if (expr_type == TypeManager.object_type) {
+                                       Expression etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.ObjectType.NotObj", Location.Null);
+                                       ArrayList arguments = new ArrayList ();
+                                       arguments.Add (new Argument (Expr, Argument.AType.Expression));
+                                       Expression e = new Invocation (etmp, arguments, loc);
+                                       return e.Resolve (ec);
                                }
-                               type = expr_type;
-                               return this;
 
+                               break;
                        case Operator.AddressOf:
+                               // Not required in VB ??
                                if (Expr.eclass != ExprClass.Variable){
                                        Error (211, "Cannot take the address of non-variables");
                                        return null;
@@ -398,6 +414,22 @@ namespace Mono.MonoBASIC {
                                //
                                // A plus in front of something is just a no-op, so return the child.
                                //
+                               if (expr_type == TypeManager.string_type) {
+                                       Expression e = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.double_type;
+                                               return e;
+                                       }
+                               }
+
+                               if (expr_type == TypeManager.bool_type) {
+                                       Expression e = ConvertImplicit (ec, Expr, TypeManager.short_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.int32_type;
+                                               return e;
+                                       }
+                               }
+
                                return Expr;
 
                        case Operator.UnaryNegation:
@@ -409,7 +441,6 @@ namespace Mono.MonoBASIC {
                                // double  operator- (double d)
                                // decimal operator- (decimal d)
                                //
-                               Expression expr = null;
 
                                //
                                // transform - - expr into expr
@@ -432,51 +463,40 @@ namespace Mono.MonoBASIC {
                                // 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.string_type) {
+                                       Expression e = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
+                                       if (e != null){
+                                               Expr = e;
+                                               type = TypeManager.double_type;
+                                               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.bool_type) {
+                                       Expression e = ConvertImplicit (ec, Expr, TypeManager.short_type, loc);
+                                       if (e != null){
+                                               Expr = e;
+                                               type = TypeManager.int32_type;
+                                               return this;
+                                       }
                                }
 
-                               if (expr_type == TypeManager.float_type){
+                               if (expr_type == TypeManager.float_type || 
+                                   expr_type == TypeManager.double_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;
+                               if (expr_type == TypeManager.short_type ||
+                                   expr_type == TypeManager.byte_type) { 
+                                       type = TypeManager.int32_type;
                                        return this;
                                }
 
-                               expr = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
-                               if (expr != null){
-                                       Expr = expr;
-                                       type = expr.Type;
-                                       return this;
+                               if (expr_type == TypeManager.int32_type || 
+                                   expr_type == TypeManager.int64_type) {
+                                       Expression e = new Binary (Binary.Operator.Subtraction, new IntLiteral (0), Expr, loc);
+                                       return e.Resolve (ec);
                                }
                                
                                Error23 (expr_type);
@@ -498,8 +518,26 @@ namespace Mono.MonoBASIC {
                        if (Expr == null)
                                return null;
 
+                       Type init_type = Expr.Type;
+
                        eclass = ExprClass.Value;
-                       return ResolveOperator (ec);
+                       Expression etmp = ResolveOperator (ec);
+                       // Convert the result to byte/short if operands are of type byte/short/boolean
+                       if (etmp.Type != init_type && 
+                           (init_type == TypeManager.byte_type || 
+                            init_type == TypeManager.short_type || 
+                            init_type == TypeManager.bool_type)) {
+                               Expression conv_exp = null;
+                               if (init_type == TypeManager.byte_type && Oper != Operator.UnaryNegation) {
+                                       return new OpcodeCast (etmp, TypeManager.byte_type, OpCodes.Conv_U1);
+                               }
+                               else
+                                       conv_exp = ConvertImplicit (ec, etmp, TypeManager.short_type, loc);
+
+                               if (conv_exp != null)
+                                       return conv_exp;
+                       }
+                       return etmp;
                }
 
                public override void Emit (EmitContext ec)
@@ -573,9 +611,11 @@ namespace Mono.MonoBASIC {
                        loc = l;
                }
 
+/*
                void LoadExprValue (EmitContext ec)
                {
                }
+*/
                
                public override void Emit (EmitContext ec)
                {
@@ -686,14 +726,6 @@ namespace Mono.MonoBASIC {
                                "++" : "--";
                }
                
-               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
@@ -974,7 +1006,7 @@ namespace Mono.MonoBASIC {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
+                        probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
 
                        if (probe_type == null)
                                return null;
@@ -1497,21 +1529,131 @@ namespace Mono.MonoBASIC {
                }
        }
 
+        public class StringConcat : Expression {
+
+               Expression left, right;
+               ArrayList Arguments; 
+               protected MethodBase method;
+       
+               public StringConcat(Location loc, Expression left, Expression right) {
+                       this.left = left;
+                       this.right = right;
+                       this.loc = loc;
+               }
+
+               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 StringConstant && right is StringConstant){
+                               return new StringConstant (
+                                                          ((StringConstant) left).Value +
+                                                          ((StringConstant) right).Value);
+                       }
+                       
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       if (l == TypeManager.string_type && r == TypeManager.string_type) {
+                               type = TypeManager.string_type;
+                               method = TypeManager.string_concat_string_string;
+                               Arguments = new ArrayList ();
+                               Arguments.Add (new Argument (left, Argument.AType.Expression));
+                               Arguments.Add (new Argument (right, Argument.AType.Expression));
+                               return this;
+                       }
+
+                       if (l != TypeManager.string_type) {
+                               method = TypeManager.string_concat_object_object;
+                               left = ConvertImplicit (ec, left, TypeManager.string_type, loc);
+                               if (left == null){
+                                       Error_OperatorCannotBeApplied (loc, "&", 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;
+                       }
+
+                       if (r != TypeManager.string_type) {
+                               method = TypeManager.string_concat_object_object;
+                               right = ConvertImplicit (ec, right, TypeManager.string_type, loc);
+                               if (right == null){
+                                       Error_OperatorCannotBeApplied (loc, "&", 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;
+                       }
+                       return this;
+               }
+
+                public override void Emit (EmitContext ec)
+                {
+                        ILGenerator ig = ec.ig;
+                        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);
+
+                                return;
+                        }
+               }
+
+                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) + "'");
+                }
+
+        }
+
+
        /// <summary>
        ///   Binary operators
        /// </summary>
        public class Binary : Expression {
                public enum Operator : byte {
-                       Multiply, Division, Modulus,
-                       Addition, Subtraction,
+                       Exponentiation,
+                       Multiply, Division, IntDivision, Modulus,
+                       Addition, Subtraction, Concat,
                        LeftShift, RightShift,
                        LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
                        Equality, Inequality,
+                       Like,
                        BitwiseAnd,
                        ExclusiveOr,
                        BitwiseOr,
                        LogicalAnd,
                        LogicalOr,
+                       Is,
                        TOP
                }
 
@@ -1536,6 +1678,7 @@ namespace Mono.MonoBASIC {
 
                        oper_names [(int) Operator.Multiply] = "op_Multiply";
                        oper_names [(int) Operator.Division] = "op_Division";
+                       oper_names [(int) Operator.IntDivision] = "op_Division";
                        oper_names [(int) Operator.Modulus] = "op_Modulus";
                        oper_names [(int) Operator.Addition] = "op_Addition";
                        oper_names [(int) Operator.Subtraction] = "op_Subtraction";
@@ -1552,10 +1695,13 @@ namespace Mono.MonoBASIC {
                        oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
                        oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
                        oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
+                       oper_names [(int) Operator.Is] = "op_Is";
                }
 
                public Binary (Operator oper, Expression left, Expression right, Location loc)
                {
+                       left = Parser.SetValueRequiredFlag (left);
+                       right = Parser.SetValueRequiredFlag (right);
                        this.oper = oper;
                        this.left = left;
                        this.right = right;
@@ -1596,12 +1742,16 @@ namespace Mono.MonoBASIC {
                static string OperName (Operator oper)
                {
                        switch (oper){
+                       case Operator.Exponentiation:
+                               return "^";
                        case Operator.Multiply:
                                return "*";
                        case Operator.Division:
                                return "/";
+                       case Operator.IntDivision:
+                               return "\\";
                        case Operator.Modulus:
-                               return "%";
+                               return "Mod";
                        case Operator.Addition:
                                return "+";
                        case Operator.Subtraction:
@@ -1619,19 +1769,21 @@ namespace Mono.MonoBASIC {
                        case Operator.GreaterThanOrEqual:
                                return ">=";
                        case Operator.Equality:
-                               return "==";
+                               return "=";
                        case Operator.Inequality:
-                               return "!=";
+                               return "<>";
                        case Operator.BitwiseAnd:
-                               return "&";
+                               return "And";
                        case Operator.BitwiseOr:
-                               return "|";
+                               return "Or";
                        case Operator.ExclusiveOr:
                                return "^";
                        case Operator.LogicalOr:
-                               return "||";
+                               return "Or";
                        case Operator.LogicalAnd:
-                               return "&&";
+                               return "And";
+                       case Operator.Is:
+                               return "Is";
                        }
 
                        return oper.ToString ();
@@ -1662,167 +1814,103 @@ namespace Mono.MonoBASIC {
                }
 
                //
-               // Note that handling the case l == Decimal || r == Decimal
-               // is taken care of by the Step 1 Operator Overload resolution.
+               // Handles boolean types also
                //
-               bool DoNumericPromotions (EmitContext ec, Type l, Type r)
+               bool DoNumericPromotions (EmitContext ec, Type l, Type r, Operator oper)
                {
-                       if (l == TypeManager.double_type || r == TypeManager.double_type){
+
+                       Type conv_left_as = null;
+                       Type conv_right_as = null;
+                       if (left is NullLiteral)
+                               conv_left_as = r;
+                       if (right is NullLiteral)
+                               conv_right_as = l;
+
+                       // Need not do anything for shift operators, as this will be handled by the
+                       // 'CheckShiftArguments' method
+                       if (oper == Operator.LeftShift || oper == Operator.RightShift)
+                               return true;
+                       if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
+                               if (IsArithmaticOperator (oper) && oper != Operator.Division) {
+                                       type = TypeManager.int32_type;
+                                       conv_left_as = conv_right_as = TypeManager.short_type;
+                               }
+                       }
+
+                       if (IsBitwiseOperator (oper)) {
+
+                               if (l == TypeManager.decimal_type || 
+                                   l == TypeManager.double_type ||
+                                   l == TypeManager.float_type) {
+                                       conv_left_as = type = TypeManager.int64_type;
+                                       l = conv_left_as;
+                               }
+                               if (r == TypeManager.decimal_type || 
+                                   r == TypeManager.double_type ||
+                                   r == TypeManager.float_type) {
+                                       conv_right_as = type = TypeManager.int64_type;
+                                       r = conv_right_as;
+                               }
+                       }
+
+                       if (oper == Operator.IntDivision) {
+                               if (l == TypeManager.decimal_type || r == TypeManager.decimal_type ||
+                                   l == TypeManager.float_type || r == TypeManager.float_type ||
+                                   l == TypeManager.double_type || r == TypeManager.double_type) 
+                                       conv_left_as = conv_right_as = TypeManager.int64_type;
+                                       l = r = TypeManager.int64_type;
+                       }
+
+                       if (IsLogicalOperator (oper)) {
+                               if (l == TypeManager.decimal_type)
+                                       conv_left_as = TypeManager.bool_type;
+                               else if (r == TypeManager.decimal_type)
+                                       conv_right_as = TypeManager.bool_type;
+                       } else if ((l == TypeManager.double_type || r == TypeManager.double_type) ||
+                                  (oper == Operator.Exponentiation) ||
+                                  (oper == Operator.Division && 
+                                  !(l == TypeManager.decimal_type || r == TypeManager.decimal_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 = conv_left_as = conv_right_as = TypeManager.double_type;
                                
-                               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;
+                               type = conv_left_as = conv_right_as = TypeManager.float_type;
+                       } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
+                               type = conv_left_as = conv_right_as = TypeManager.decimal_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;
+                               type = conv_left_as = conv_right_as = TypeManager.int64_type;
+                       } else if (l == TypeManager.int32_type || r == TypeManager.int32_type){
+                               type = conv_left_as = conv_right_as = TypeManager.int32_type;
+                       } else if (l == TypeManager.short_type || r == TypeManager.short_type){
+                               conv_left_as = conv_right_as = TypeManager.short_type;
+                               type = TypeManager.int32_type;
                        } else {
-                               left = ForceConversion (ec, left, TypeManager.int32_type);
-                               right = ForceConversion (ec, right, TypeManager.int32_type);
-
                                type = TypeManager.int32_type;
                        }
 
+                       if (conv_left_as != null)
+                               left = ConvertImplicit (ec, left, conv_left_as, loc);
+                       if (conv_right_as != null)
+                               right = ConvertImplicit (ec, right, conv_right_as, loc);
+
                        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 '" +
+                              "Operator '" + name + "' cannot be applied to operands of type '" +
                               TypeManager.MonoBASIC_Name (l) + "' and '" +
                               TypeManager.MonoBASIC_Name (r) + "'");
                }
@@ -1853,430 +1941,679 @@ namespace Mono.MonoBASIC {
                                Error_OperatorCannotBeApplied ();
                                return null;
                        }
+
+                       type = left.Type;
+                       if (left is NullLiteral) {
+                               type = right.Type; 
+                               if (right.Type != TypeManager.bool_type) {
+                                       left =  ConvertImplicit (ec, left, right.Type, loc);
+                                       if (left == null) {
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
+                                               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;
+                       if (type == TypeManager.bool_type) {
+                               left = ConvertImplicit (ec, left, TypeManager.short_type, loc);
+                               if (left == null) {
+                                       Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
+                                       return null;
+                               }
+                               type = left.Type;
+                       }
+
+                       int mask = 0;
+                       if ( type == TypeManager.byte_type)
+                               mask = 7;
+                       else if (type == TypeManager.short_type || type == TypeManager.bool_type)
+                               mask = 15;
+                       else if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
+                               mask = 31;
+                       else 
+                               mask = 63;
+                       if (mask != 0) {
+                               right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (mask), loc);
+                               right = right.DoResolve (ec);
+                       }
+
+                       if (type == TypeManager.byte_type || 
+                           type == TypeManager.short_type ||
+                           type == TypeManager.int32_type) {
+                               type = TypeManager.int32_type;
+                               return this;
+                       }
 
+                       if (type == TypeManager.int64_type)
+                               return this;
+                       if ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) {
+                               left = e;
+                               type = TypeManager.int64_type;
                                return this;
                        }
+
                        Error_OperatorCannotBeApplied ();
                        return null;
                }
 
+               bool IsRelationalOperator (Binary.Operator oper) {
+                       return (oper == Operator.Equality ||
+                               oper == Operator.Inequality ||  
+                               oper == Operator.LessThan ||    
+                               oper == Operator.LessThanOrEqual ||     
+                               oper == Operator.GreaterThan || 
+                               oper == Operator.GreaterThanOrEqual);
+               }
+
+               bool IsArithmaticOperator (Binary.Operator oper) {
+                       return (oper == Operator.Addition ||
+                               oper == Operator.Subtraction || 
+                               oper == Operator.Multiply ||    
+                               oper == Operator.Division ||    
+                               oper == Operator.IntDivision || 
+                               oper == Operator.Exponentiation ||      
+                               oper == Operator.Modulus);
+               }
+
+               bool IsShiftOperator (Binary.Operator oper) {
+                       return (oper == Operator.LeftShift ||
+                               oper == Operator.RightShift);
+               }
+
+               bool IsLogicalOperator (Binary.Operator oper) {
+                       return (oper == Operator.LogicalOr ||
+                               oper == Operator.LogicalAnd);
+               }
+
+               bool IsBitwiseOperator (Binary.Operator oper) {
+                       return (oper == Operator.BitwiseOr ||
+                               oper == Operator.BitwiseAnd ||
+                               oper == Operator.ExclusiveOr);
+               }
+
                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;
+                       left_expr = right_expr = null;
+
+                       if (oper == Operator.Addition && right is Unary) {
+                               Unary unary_right = (Unary) right;
+                               if (unary_right.Oper == Unary.Operator.UnaryNegation) {
+                                       oper = Operator.Subtraction;
+                                       right = unary_right.Expr;
+                                       r = right.Type;
                                }
-                       }       
-                       
-                       //
-                       // 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 ();
+                       if (TypeManager.IsEnumType (l)) 
+                               l = TypeManager.EnumToUnderlying (l);
+                       if (TypeManager.IsEnumType (r)) 
+                               r = TypeManager.EnumToUnderlying (r);
+
+                       Type conv_left_as = null;
+                       Type conv_right_as = null;
+
+                       if ((left is NullLiteral ||(Type.GetTypeCode(l)==TypeCode.DBNull)) && (r.IsValueType || r == TypeManager.string_type)) {
+                               // Just treat nothing as the other type, implicit conversion 
+                               // will return the default value
+                               conv_left_as = r;
+                               l = r;
+                               //incase of DBNull set to NullLiteral
+                               left = NullLiteral.Null;
+                       }
+
+                       if ((right is NullLiteral ||(Type.GetTypeCode(r)==TypeCode.DBNull)) && (l.IsValueType || l == TypeManager.string_type)) {
+                               // Just treat nothing as the other type, implicit conversion 
+                               // will return the default value
+                               conv_right_as = l;
+                               r = l;
+                               right = NullLiteral.Null;
+                       }
+
+                       // deal with objects and reference types first
+                       if (l == TypeManager.object_type || r == TypeManager.object_type) {
+
+                               //
+                                // 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 other type is a value type, convert it to object
+                               if (r == TypeManager.object_type &&
+                                   (l.IsValueType || l == TypeManager.string_type))
+                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
+                               if (l == TypeManager.object_type &&
+                                   (r.IsValueType || r == TypeManager.string_type))
+                                       right = ConvertImplicit (ec, right, TypeManager.object_type, loc);
+                               if (left == null || right == null) {
+                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                       return null;
+                               }
+
+                               l = left.Type;
+                               r = right.Type;
+
+                               if (l == TypeManager.object_type && r == TypeManager.object_type) {
+                                       string fqn = null;
+                                       switch (oper) {
+                                       case Operator.Addition :
+                                               fqn = "ObjectType.AddObj";
+                                               break;
+                                       case Operator.Subtraction :
+                                               fqn = "ObjectType.SubObj";
+                                               break;
+                                       case Operator.Multiply :
+                                               fqn = "ObjectType.MulObj";
+                                               break;
+                                       case Operator.Division :
+                                               fqn = "ObjectType.DivObj";
+                                               break;
+                                       case Operator.IntDivision :
+                                               fqn = "ObjectType.IDivObj";
+                                               break;
+                                       case Operator.Modulus :
+                                               fqn = "ObjectType.ModObj";
+                                               break;
+                                       case Operator.Exponentiation :
+                                               fqn = "ObjectType.PowObj";
+                                               break;
+                                       case Operator.Like :
+                                               fqn = "ObjectType.LikeObj";
+                                               break;
+                                       case Operator.Equality :
+                                       case Operator.Inequality :
+                                       case Operator.LessThan :
+                                       case Operator.LessThanOrEqual :
+                                       case Operator.GreaterThan :
+                                       case Operator.GreaterThanOrEqual :
+                                               fqn = "ObjectType.ObjTst";
+                                               break;
+                                       case Operator.BitwiseAnd:
+                                               fqn = "ObjectType.BitAndObj";
+                                               break;
+                                       case Operator.BitwiseOr:
+                                               fqn = "ObjectType.BitOrObj";
+                                               break;
+                                       case Operator.ExclusiveOr:
+                                               fqn = "ObjectType.BitXorObj";
+                                               break;
+                                       case Operator.LeftShift:
+                                               fqn = "ObjectType.ShiftLeftObj";
+                                               break;
+                                       case Operator.RightShift:
+                                               fqn = "ObjectType.ShiftRightObj";
+                                               break;
+                                       case Operator.Is:
+                                               eclass = ExprClass.Value;
+                                               type = TypeManager.bool_type;
+                                               return this;
+                                       }
+                       
+                                       if (fqn == null) {
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                                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){
+
+                                       if (oper == Operator.LeftShift || oper == Operator.RightShift) {
+                                               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
+                                       Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI (
+                                                               "Microsoft.VisualBasic.CompilerServices." + fqn, 
+                                                               Location.Null);
+
+                                       ArrayList args = new ArrayList ();
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
+                                       if (IsRelationalOperator (oper)) 
+                                               args.Add (new Argument (new BoolConstant (false), Argument.AType.Expression));
+                                       if (oper == Operator.Like) 
+                                               args.Add (new Argument(new IntLiteral (0), Argument.AType.Expression));
+                                       Expression e = new Invocation (etmp, args, loc);
+                                       if (IsRelationalOperator (oper)) {
+                                               e = new Binary (oper, e.Resolve(ec), new IntConstant (0), loc);
+                                       }
+                                       return e.Resolve (ec);
+                               } else if (!l.IsValueType || !r.IsValueType) {
+
+                                       // If one of the operands are reference types and other is object, support for 'Is' operator
+                                       if (oper == Operator.Is) {
+                                               eclass = ExprClass.Value;
+                                               type = TypeManager.bool_type;
+                                               return this;
+                                       }
+                               }
 
-                                       if (l == TypeManager.void_type) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
+               
+                       } else if (!l.IsValueType || !r.IsValueType) {
+                               
+                               if (!l.IsValueType && !r.IsValueType) {
+                                       // If both the operands are reference types, support for 'Is' operator
+                                       if (oper == Operator.Is) {
+                                                       eclass = ExprClass.Value;
+                                               type = TypeManager.bool_type;
+                                               return this;
+                                       }
+                               }
+                               // Either of the operands are reference types
+                               if (l.IsSubclassOf (TypeManager.delegate_type) && 
+                                   r.IsSubclassOf (TypeManager.delegate_type)) {
+                                       if (oper == Operator.Addition || oper == Operator.Subtraction) {
+                                               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;
                                        }
-                                       
-                                       method = TypeManager.string_concat_object_object;
-                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
-                                       if (left == null){
+
+                                       if (oper != Operator.Equality) {
                                                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;
+                               bool left_is_string = (left.Type == TypeManager.string_type);
+                               bool right_is_string = (right.Type == TypeManager.string_type);
 
-                                       if (right_unary.Oper == Unary.Operator.UnaryNegation){
-                                               oper = Operator.Subtraction;
-                                               right = right_unary.Expr;
-                                               r = right.Type;
+                               if (left_is_string || right_is_string) {
+       
+                                       if (left is NullLiteral) {
+                                               left_is_string = true;
+                                               l = r;
                                        }
-                               }
-                       }
-
-                       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;
+                                       if (right is NullLiteral) {
+                                               right_is_string = true;
+                                               r = l;
                                        }
-                                       
-                                       type = TypeManager.bool_type;
-                                       return this;
-                               }
+                                       if (left_is_string && right_is_string) {
+                                               if (oper == Operator.Addition) {
+                                               // Both operands are string 
+                                                       Expression e = new StringConcat (loc, left, right);
+                                                       return e.Resolve(ec);
+                                               }
 
-                               //
-                               // 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 (IsRelationalOperator (oper)) {
+       
+                                                       Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.StringType.StrCmp", Location.Null);
+                                                       eclass = ExprClass.Value;
+                                                       type = TypeManager.bool_type;
+                                                       ArrayList args = new ArrayList ();
+                                                       args.Add (new Argument(left, Argument.AType.Expression));
+                                                       args.Add (new Argument(right, Argument.AType.Expression));
+                                                       args.Add (new Argument(new BoolConstant(false), Argument.AType.Expression));
+                                                       Expression e = (Expression) new Invocation (etmp, args, loc);
+                                                       e = new Binary (oper, e.Resolve(ec), new IntConstant(0), loc);
+                                                       return e.Resolve(ec);
+                                               }
 
-                                       if (l == r)
-                                               return this;
-                                       
-                                       if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
-                                               return this;
+                                               if (oper == Operator.Like) {
+                                                       Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.StringType.StrLike", Location.Null);
+                                                       type = TypeManager.bool_type;
+                                                       ArrayList args = new ArrayList ();
+                                                       args.Add (new Argument(left, Argument.AType.Expression));
+                                                       args.Add (new Argument(right, Argument.AType.Expression));
+                                                       args.Add (new Argument(new IntLiteral (0), Argument.AType.Expression));
+                                                       Expression e = (Expression) new Invocation (etmp, args, loc);
+                                                       return e.Resolve (ec);
+                                               }
+                                       }
 
+                                       Expression other = right_is_string ? left: right;
+                                       Type other_type = other.Type;
+       
                                        //
-                                       // Also, a standard conversion must exist from either one
+                                       // Disallow arithmatic / shift / logical operators on dates and characters
                                        //
-                                       if (!(StandardConversionExists (left, r) ||
-                                             StandardConversionExists (right, l))){
-                                               Error_OperatorCannotBeApplied ();
+                                       if (other_type == TypeManager.date_type || other_type == TypeManager.char_type) {
+                                               if (!(oper == Operator.Addition || IsRelationalOperator (oper) || oper == Operator.Like)) {
+                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                                       return null;
+                                               }
+                                       }
+       
+                                       if (oper == Operator.Addition) {
+                                               if (other_type == TypeManager.void_type) {
+                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                                       return null;
+                                               }
+                                               if (other_type == TypeManager.date_type || 
+                                               other_type == TypeManager.char_type || 
+                                               other_type == typeof (System.Char[])) {
+                                                       conv_left_as = conv_right_as = TypeManager.string_type;
+                                                       type = TypeManager.string_type;
+                                               }  else {
+                                                       // numeric operand
+                                                       conv_right_as = conv_left_as = TypeManager.double_type;
+                                                       type = TypeManager.double_type;
+                                               }
+                                       } else if (IsRelationalOperator (oper)) {
+                                               if (other_type == TypeManager.char_type || other_type == typeof (System.Char[])) {
+                                                       conv_left_as = conv_right_as = TypeManager.string_type;
+                                               } else if (other_type == TypeManager.date_type) {
+                                                       conv_right_as = conv_left_as = other_type;
+                                               } else if (other_type == TypeManager.bool_type) {
+                                                       conv_right_as = conv_left_as = other_type;
+                                               } else if (! other_type.IsValueType) {
+                                                       // Do Nothing, just return
+                                                       type = TypeManager.bool_type;
+                                                       return this;
+                                               } else {
+                                                       conv_right_as = conv_left_as = TypeManager.double_type;
+                                               }
+                                               type = TypeManager.bool_type;
+       
+                                       } else if (oper == Operator.Like) {
+                                               conv_left_as = conv_right_as = TypeManager.string_type;
+                                       } else if (oper == Operator.LeftShift || oper == Operator.RightShift) {
+       
+                                               conv_left_as = TypeManager.int64_type;
+                                               conv_right_as = TypeManager.int32_type;
+                                               type = TypeManager.int64_type;
+       
+                                       } else if ( IsLogicalOperator (oper)) {
+                                               type = conv_right_as = conv_left_as = TypeManager.bool_type;
+                                       } else if ( IsBitwiseOperator (oper)) {
+       
+                                               if (other_type == TypeManager.bool_type) {
+                                                       conv_right_as = conv_left_as = TypeManager.bool_type;
+                                                       type = TypeManager.bool_type;
+                                               } else {
+                                                       conv_left_as = conv_right_as = TypeManager.int64_type;
+                                                       type = TypeManager.int64_type;
+                                               }
+                                       } else if (oper == Operator.Exponentiation) {
+                                               conv_left_as = conv_right_as = TypeManager.double_type;
+                                       } else if (oper == Operator.IntDivision) {
+                                               conv_left_as = conv_right_as = TypeManager.int64_type;
+                                       } else {
+                                               // Arithmatic operators
+                                               conv_right_as = conv_left_as = TypeManager.double_type;
+                                               type = TypeManager.double_type;
+                                       }
+                               } else {
+                                       // Both are not of type string
+                                       if (oper == Operator.Equality || oper == Operator.Inequality || oper == Operator.Is) {
+                                               if (l.IsValueType || r.IsValueType) {
+                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                                       return null;
+                                               }
+                                               type = TypeManager.bool_type;
+                                               return this;
+                                       } else {
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                                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 ();
+                       } else if (l == TypeManager.date_type || r == TypeManager.date_type) {
+                               // Date with string operations handled above
+                               // Only other possiblity is date with date
+                               if (oper == Operator.Like) {
+                                       conv_right_as = conv_left_as = TypeManager.string_type;
+                                       type = TypeManager.bool_type;
+                               } else if (l == TypeManager.date_type && r == TypeManager.date_type) {
+                                       if (oper == Operator.Addition) {
+                                               conv_left_as = conv_right_as = TypeManager.string_type;
+                                       } else if (IsRelationalOperator (oper)) { 
+                                               Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI ("System.DateTime.Compare", Location.Null);
+                                               eclass = ExprClass.Value;
+                                               type = TypeManager.bool_type;
+                                               ArrayList args = new ArrayList ();
+                                               args.Add (new Argument(left, Argument.AType.Expression));
+                                               args.Add (new Argument(right, Argument.AType.Expression));
+                                               Expression e = (Expression) new Invocation (etmp, args, loc);
+                                               e = new Binary (oper, e.Resolve(ec), new IntConstant(0), loc);
+                                               return e.Resolve(ec);
+                                       } else {
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                               return null;
+                                       }
+                               } else {
+                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                        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));
-                                       
+                       } else if (l == TypeManager.char_type || r == TypeManager.char_type) {
+                               // char op string handled above
+                               if (oper == Operator.Like) {
+                                       conv_right_as = conv_left_as = TypeManager.string_type;
+                                       type = TypeManager.bool_type;
+                               } else if (l == TypeManager.char_type && r == TypeManager.char_type) {
                                        if (oper == Operator.Addition)
-                                               method = TypeManager.delegate_combine_delegate_delegate;
-                                       else
-                                               method = TypeManager.delegate_remove_delegate_delegate;
-
-                                       if (l != r) {
-                                               Error_OperatorCannotBeApplied ();
+                                               conv_left_as = conv_right_as = TypeManager.string_type;
+                                       else if (IsRelationalOperator (oper)) {
+                                               type = TypeManager.bool_type;
+                                       } else {
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                                return null;
                                        }
-
-                                       DelegateOperation = true;
-                                       type = l;
-                                       return this;
+                               } else {
+                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                       return null;
                                }
-
-                               //
-                               // 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 (l.IsPointer || r.IsPointer) {
+                               if (oper == Operator.Addition || oper == Operator.Subtraction) {
+                                       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;
+                                       } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
+                                               return new PointerArithmetic (
+                                                       true, right, left, r, loc);
                                }
-                                       
+
                                //
-                               // operator + (E e, U x)
-                               // operator - (E e, U x)
+                               // Pointer comparison
                                //
-                               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;
+                               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;
                                        }
-
-                                       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;
-                                       }
+                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                               return null;
+
+                       } else if (oper == Operator.Like) {
+                               conv_left_as = conv_right_as = TypeManager.string_type;
+                       } else {
+
+                               // Numeric Types
+                               DoNumericPromotions (ec, l, r, oper);
+                               if (left == null || right == null) {
+                                       Error_OperatorCannotBeApplied (loc, OperName(oper), l, r);
+                                       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;
+                               l = left.Type;
+                               r = right.Type;
+                               // Required conversions done by 'DoNumericPromotions' method
+                               // So Reset 'conv_left_as', 'conv_right_as'
+                               conv_left_as = conv_right_as = null;
+
+                               if (l == TypeManager.decimal_type  && r == TypeManager.decimal_type) {
+                                       if (IsRelationalOperator (oper)) {
+                                               Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI ("System.Decimal.Compare", Location.Null);
+                                               eclass = ExprClass.Value;
+                                               type = TypeManager.bool_type;
+                                               ArrayList args = new ArrayList ();
+                                               args.Add (new Argument(left, Argument.AType.Expression));
+                                               args.Add (new Argument(right, Argument.AType.Expression));
+                                               Expression e = (Expression) new Invocation (etmp, args, loc);
+                                               e = new Binary (oper, e.Resolve(ec), new IntConstant(0), loc);
+                                               return e.Resolve(ec);
+                                       } else if (IsArithmaticOperator (oper)) {
+                                               string fqn = null;
+                                               if (oper == Operator.Addition) 
+                                                       fqn = "System.Decimal.Add";
+                                               else if (oper == Operator.Subtraction) 
+                                                       fqn = "System.Decimal.Subtract";
+                                               else if (oper == Operator.Multiply) 
+                                                       fqn = "System.Decimal.Multiply";
+                                               else if (oper == Operator.Division)
+                                                       fqn = "System.Decimal.Divide";
+                                               else if (oper == Operator.Modulus) 
+                                                       fqn = "System.Decimal.Remainder";
+                                               if (fqn != null) {
+
+                                                       Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI (fqn, Location.Null);
+                                                       eclass = ExprClass.Value;
+                                                       type = TypeManager.decimal_type;
+                                                       ArrayList args = new ArrayList ();
+                                                       args.Add (new Argument(left, Argument.AType.Expression));
+                                                       args.Add (new Argument(right, Argument.AType.Expression));
+                                                       Expression e = (Expression) new Invocation (etmp, args, loc);
+                                                       return e.Resolve (ec);
+                                               }
+                                       }
                                }
+                       }
 
-                               if (oper == Operator.BitwiseAnd ||
-                                   oper == Operator.BitwiseOr ||
-                                   oper == Operator.ExclusiveOr){
-                                       type = l;
-                                       return this;
+                       bool conv_done = false;
+                       if (conv_left_as != null && conv_left_as != l) {
+                               conv_done = true;
+                               left = ConvertImplicit (ec, left, conv_left_as, loc);
+                               if (left == null) {
+                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                       return null;
                                }
-                               Error_OperatorCannotBeApplied ();
-                               return null;
+                               l = left.Type;
                        }
-                       
-                       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 ();
+                       if (conv_right_as != null && conv_right_as != r) {
+                               conv_done = true;
+                               right = ConvertImplicit (ec, right, conv_right_as, loc);
+                               if (right == null) {
+                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                        return null;
                                }
+                               r = right.Type;
+                       }
 
-                               type = TypeManager.bool_type;
-                               return this;
-                       } 
+                       if (conv_done) 
+                               return ResolveOperator (ec);
 
-                       //
-                       // 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;
-                               }
+
+                       if (oper == Operator.Exponentiation) {
+                               Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI("System.Math.Pow", loc);
+                               ArrayList args = new ArrayList();
+                               args.Add (new Argument (left, Argument.AType.Expression));
+                               args.Add (new Argument (right, Argument.AType.Expression));
+                               Expression e = (Expression) new Invocation (etmp, args, loc);
+                               return e.Resolve(ec);
                        }
-                       
-                       //
-                       // 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;
+
+                       bool overload_failed = false;
+                       string op = oper_names [(int) oper];
+                       MethodGroupExpr union = null;
+                       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;
                                }
                        }
-                       
-                       //
-                       // We are dealing with numbers
-                       //
-                       if (overload_failed){
+
+                       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;
+                       if (IsRelationalOperator (oper)) {
+                               type = TypeManager.bool_type;
+                               if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
+                                       // Reverse the operator - to make it consistent with vbc
+                                       if (oper == Operator.LessThan) 
+                                               oper = Operator.GreaterThan;
+                                       else if (oper == Operator.GreaterThan)
+                                               oper = Operator.LessThan;
+                                       else if (oper == Operator.LessThanOrEqual)
+                                               oper = Operator.GreaterThanOrEqual;
+                                       else if (oper == Operator.GreaterThanOrEqual)
+                                               oper = Operator.LessThanOrEqual;
+                               }
                        }
 
-                       //
-                       // 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)))
+                       if (IsLogicalOperator (oper))
+                               type = TypeManager.bool_type;
+                       if (IsBitwiseOperator (oper)) {
+                               if (l == r) {
+                                       if (l == TypeManager.byte_type ||
+                                           l == TypeManager.short_type ||
+                                           l == TypeManager.bool_type ||
+                                           l == TypeManager.int32_type ||
+                                           l == TypeManager.int64_type) 
                                                type = l;
+                                       else {
+                                               Error_OperatorCannotBeApplied();
+                                               return null;
+                                       }
                                } else {
-                                       Error_OperatorCannotBeApplied ();
+                                       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;
+                       if (oper == Operator.LeftShift || oper == Operator.RightShift) {
+                               return CheckShiftArguments (ec);
                        }
 
                        return this;
                }
+               
 
                public override Expression DoResolve (EmitContext ec)
                {
+                       if (oper == Operator.Concat) {
+                               Expression e = new StringConcat (loc, left, right);
+                               return e.Resolve (ec);
+                       }
                        left = left.Resolve (ec);
                        right = right.Resolve (ec);
 
@@ -2293,6 +2630,16 @@ namespace Mono.MonoBASIC {
                                        right + ") at Line: "+ loc.Row);
 
                        eclass = ExprClass.Value;
+                       
+                       // To support  'Or' argument of AttributeTargets in AttributeUsage
+
+                       if (left is EnumConstant && oper != Operator.BitwiseOr) {
+                               left = ((EnumConstant) left).WidenToCompilerConstant();
+                       }
+
+                       if (right is EnumConstant && oper != Operator.BitwiseOr) {
+                               right = ((EnumConstant) right).WidenToCompilerConstant();
+                       }
 
                        if (left is Constant && right is Constant){
                                Expression e = ConstantFold.BinaryFold (
@@ -2301,7 +2648,28 @@ namespace Mono.MonoBASIC {
                                        return e;
                        }
 
-                       return ResolveOperator (ec);
+                       Expression etmp = ResolveOperator (ec);
+                       Type l = left.Type;
+                       
+                       // if the operands are of type byte/short, convert the result back to short/byte
+                       if (l == TypeManager.bool_type || l == TypeManager.short_type || l == TypeManager.byte_type) {
+                               if (l == TypeManager.bool_type)
+                                       l = TypeManager.short_type;
+                               if (IsArithmaticOperator (oper) && oper != Operator.Division) {
+                                       Expression conv_exp = ConvertImplicit (ec, etmp, l, loc);
+                                       if (conv_exp != null)
+                                               return conv_exp;
+                               } 
+                               if (IsShiftOperator (oper)) {
+                                       // No overflow checks are needed
+                                       if (l == TypeManager.byte_type)
+                                               return new OpcodeCast (etmp, l, OpCodes.Conv_U1);
+                                       else 
+                                               return new OpcodeCast (etmp, l, OpCodes.Conv_I2);
+                               }
+                       }
+
+                       return etmp;
                }
 
                /// <remarks>
@@ -2325,7 +2693,7 @@ namespace Mono.MonoBASIC {
                        // 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){
+                       if (oper == Operator.Equality || oper == Operator.Inequality || oper == Operator.Is){
                                bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
                                
                                if (left is NullLiteral){
@@ -2346,7 +2714,8 @@ namespace Mono.MonoBASIC {
                        } else if (!(oper == Operator.LessThan ||
                                      oper == Operator.GreaterThan ||
                                      oper == Operator.LessThanOrEqual ||
-                                     oper == Operator.GreaterThanOrEqual))
+                                     oper == Operator.GreaterThanOrEqual ||
+                                     oper == Operator.Is))
                                return false;
                        
 
@@ -2424,6 +2793,13 @@ namespace Mono.MonoBASIC {
                                                ig.Emit (OpCodes.Blt, target);
                                break;
 
+                       case Operator.Is:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Beq, target); //Check this
+                               else
+                                       ig.Emit (OpCodes.Bne_Un_S, target);
+                               break;
+
                        default:
                                return false;
                        }
@@ -2435,6 +2811,7 @@ namespace Mono.MonoBASIC {
                {
                        ILGenerator ig = ec.ig;
                        Type l = left.Type;
+                       Type r = right.Type;
                        //Type r = right.Type;
                        OpCode opcode;
 
@@ -2460,25 +2837,59 @@ namespace Mono.MonoBASIC {
                        // Handle short-circuit operators differently
                        // than the rest
                        //
-                       if (oper == Operator.LogicalAnd){
+                       if (IsLogicalOperator (oper)) {
                                Label load_zero = ig.DefineLabel ();
+                               Label load_one = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
                                
                                left.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, load_zero);
+                               if (l != TypeManager.bool_type) {
+                                       if (l == TypeManager.int64_type) {
+                                               ec.ig.Emit (OpCodes.Ldc_I8, 0L);
+                                               ec.ig.Emit (OpCodes.Cgt_Un);
+                                       } else if (l == TypeManager.float_type) {
+                                               ec.ig.Emit (OpCodes.Ldc_R4, 0.0F);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                       } else if (l == TypeManager.double_type) {
+                                               ec.ig.Emit (OpCodes.Ldc_R8, 0.0);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                       } else  {
+                                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                                               ec.ig.Emit (OpCodes.Cgt_Un);
+                                       }
+                               }
+                               if (oper == Operator.LogicalAnd) 
+                                       ig.Emit (OpCodes.Brfalse, load_zero);
+                               else 
+                                       ig.Emit (OpCodes.Brtrue, load_one);
+                               
                                right.Emit (ec);
-                               ig.Emit (OpCodes.Br, end);
+                               if (r != TypeManager.bool_type) {
+                                       if (r == TypeManager.int64_type) {
+                                               ec.ig.Emit (OpCodes.Ldc_I8, 0L);
+                                               ec.ig.Emit (OpCodes.Cgt_Un);
+                                       } else if (r == TypeManager.float_type) {
+                                               ec.ig.Emit (OpCodes.Ldc_R4, 0.0F);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                       } else if (r == TypeManager.double_type) {
+                                               ec.ig.Emit (OpCodes.Ldc_R8, 0.0);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                                               ec.ig.Emit (OpCodes.Ceq);
+                                       } else  {
+                                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                                               ec.ig.Emit (OpCodes.Cgt_Un);
+                                       }
+                               }
+                               ig.Emit (OpCodes.Brtrue, load_one);
                                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);
@@ -2504,6 +2915,7 @@ namespace Mono.MonoBASIC {
                                break;
 
                        case Operator.Division:
+                       case Operator.IntDivision:
                                if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
                                        opcode = OpCodes.Div_Un;
                                else
@@ -2553,6 +2965,7 @@ namespace Mono.MonoBASIC {
                                break;
 
                        case Operator.Equality:
+                       case Operator.Is:
                                opcode = OpCodes.Ceq;
                                break;
 
@@ -2895,8 +3308,9 @@ namespace Mono.MonoBASIC {
                {
                        VariableInfo vi = VariableInfo;
 
-                       if (ec.DoFlowAnalysis)
+                       if (ec.DoFlowAnalysis) {
                                ec.SetVariableAssigned (vi);
+                       }
 
                        Expression e = DoResolve (ec);
 
@@ -2916,7 +3330,24 @@ namespace Mono.MonoBASIC {
                        VariableInfo vi = VariableInfo;
                        ILGenerator ig = ec.ig;
 
-                       ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+                       if (vi.Alias != null && vi.Static) {
+                               ArrayList fields = ec.TypeContainer.Fields;
+                               FieldBase fb = null;
+                               for (int i = 0; i < fields.Count; i++) {
+                                       if (((Field) fields[i]).Name == vi.Alias) {
+                                               fb = (Field) fields[i];
+                                               break;
+                                       }
+                               }
+                               if ((fb.ModFlags & Modifiers.STATIC) != 0)
+                                       ig.Emit (OpCodes.Ldsfld, fb.FieldBuilder);
+                               else {
+                                       ig.Emit (OpCodes.Ldarg_0);              
+                                       ig.Emit (OpCodes.Ldfld, fb.FieldBuilder);
+                               }
+                       } else
+                               ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+
                        vi.Used = true;
                }
                
@@ -2927,16 +3358,52 @@ namespace Mono.MonoBASIC {
 
                        vi.Assigned = true;
 
-                       source.Emit (ec);
-                       
-                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                       if (vi.Alias != null && vi.Static) {
+                               ArrayList fields = ec.TypeContainer.Fields;
+                               FieldBase fb = null;
+                               for (int i = 0; i < fields.Count; i++) {
+                                       if (((Field) fields[i]).Name == vi.Alias) {
+                                               fb = (Field) fields[i];
+                                               break;
+                                       }
+                               }
+                               if ((fb.ModFlags & Modifiers.STATIC) != 0) {
+                                       source.Emit (ec);
+                                       ig.Emit (OpCodes.Stsfld, fb.FieldBuilder);
+                               }
+                               else {
+                                       ig.Emit (OpCodes.Ldarg_0);
+                                       source.Emit (ec);
+                                       ig.Emit (OpCodes.Stfld, fb.FieldBuilder);
+                               }
+                       }
+                       else {
+                               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);
+                       if (vi.Alias != null && vi.Static) {
+                               ArrayList fields = ec.TypeContainer.Fields;
+                               FieldBase fb = null;
+                               for (int i = 0; i < fields.Count; i++) {
+                                       if (((Field) fields[i]).Name == vi.Alias) {
+                                               fb = (Field) fields[i];
+                                               break;
+                                       }
+                               }
+                               if ((fb.ModFlags & Modifiers.STATIC) != 0)
+                                       ec.ig.Emit (OpCodes.Ldsflda, fb.FieldBuilder);
+                               else {
+                                       ec.ig.Emit (OpCodes.Ldarg_0);
+                                       ec.ig.Emit (OpCodes.Ldflda, fb.FieldBuilder);
+                               }
+                       } else
+                               ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);
                }
        }
 
@@ -3019,12 +3486,12 @@ namespace Mono.MonoBASIC {
                {
                        type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
                        is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
-                       is_out = (mod & Parameter.Modifier.OUT) != 0;
+                       // is_out = (mod & Parameter.Modifier.OUT) != 0;
                        eclass = ExprClass.Variable;
 
-                       if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
+                       /*  if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
                                return null;
-
+                       */
                        return this;
                }
 
@@ -3032,12 +3499,12 @@ namespace Mono.MonoBASIC {
                {
                        type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
                        is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
-                       is_out = (mod & Parameter.Modifier.OUT) != 0;
+                       // is_out = (mod & Parameter.Modifier.OUT) != 0;
                        eclass = ExprClass.Variable;
-
+                       /*
                        if (is_out && ec.DoFlowAnalysis)
                                ec.SetParameterAssigned (idx);
-
+                       */
                        return this;
                }
 
@@ -3146,9 +3613,15 @@ namespace Mono.MonoBASIC {
                public Expression expr;
                MethodBase method = null;
                bool is_base;
+               bool is_latebinding;
                bool is_left_hand; // Needed for late bound calls
+               bool is_retval_required; // Needed for late bound calls
                static Hashtable method_parameter_cache;
-               static MemberFilter CompareName;
+               //static MemberFilter CompareName;
+
+               static ArrayList tempvars; // For ByRef - different parameter and argument type
+               static bool is_byref_conversion = false; //For ByRef when it is converted 
+               static string errorMsg = "";
 
                static Invocation ()
                {
@@ -3165,9 +3638,15 @@ namespace Mono.MonoBASIC {
                public Invocation (Expression expr, ArrayList arguments, Location l)
                {
                        this.expr = expr;
+                       if (this.expr is MemberAccess)
+                               ((MemberAccess) this.expr).IsInvocation = true;
+                       if (this.expr is SimpleName)
+                               ((SimpleName) this.expr).IsInvocation = true;
+                       this.is_retval_required = false;
+                       this.is_left_hand = false;
                        Arguments = arguments;
                        loc = l;
-                       CompareName = new MemberFilter (compare_name_filter);
+                       //CompareName = new MemberFilter (compare_name_filter);
                }
 
                public Expression Expr {
@@ -3176,6 +3655,33 @@ namespace Mono.MonoBASIC {
                        }
                }
 
+               public bool IsLeftHand {
+                       get {
+                               return is_left_hand;
+                       }
+                       set {
+                               is_left_hand = value;
+                       }
+               }
+
+               public bool IsRetvalRequired {
+                       get {
+                               return is_retval_required;
+                       }
+                       set {
+                               is_retval_required = value;
+                       }
+               }
+
+               public bool IsLateBinding {
+                       get {
+                               return is_latebinding;
+                       }
+                       set {
+                               is_latebinding = value;
+                       }
+               }
+
                /// <summary>
                ///   Returns the Parameters (a ParameterData interface) for the
                ///   Method 'mb'
@@ -3345,102 +3851,34 @@ namespace Mono.MonoBASIC {
                        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;
-               }
-
 
                protected enum ConversionType { None, Widening, Narrowing };
 
                static ConversionType CheckParameterAgainstArgument (EmitContext ec, ParameterData pd, int i, Argument a, Type ptype)
                {
+                       if (a.ArgType == Argument.AType.NoArg)  {
+                               return ConversionType.Widening;
+                       }
+
                        Parameter.Modifier a_mod = a.GetParameterModifier () &
-                               ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               ~(Parameter.Modifier.REF);
                        Parameter.Modifier p_mod = pd.ParameterModifier (i) &
-                               ~(Parameter.Modifier.OUT | Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
+                               ~(Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
 
                        if (a_mod == p_mod ||
                                (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
-                               if (a_mod == Parameter.Modifier.NONE) {
+                               // if (a_mod == Parameter.Modifier.NONE) {
                                        if (! WideningConversionExists (a.Expr, ptype) ) {
+
                                                if (! NarrowingConversionExists (ec, a.Expr, ptype) )
                                                        return ConversionType.None;
                                                else
                                                        return ConversionType.Narrowing;
                                        } else
-                                                       return ConversionType.Widening;
-                               }
+                                               return ConversionType.Widening;
+                                // }
                                
+/*
                                if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
                                        Type pt = pd.ParameterType (i);
                                        
@@ -3451,6 +3889,7 @@ namespace Mono.MonoBASIC {
                                                return ConversionType.None;
                                }
                                return ConversionType.Widening;
+*/
                        } else
                                return ConversionType.None;                                     
                }
@@ -3472,16 +3911,26 @@ namespace Mono.MonoBASIC {
                        return count;
                }
 
+               static ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate,
+                                                   out bool expanded)
+               {
+                       bool objectArgsPresent;
+                       return IsApplicable (ec, arguments, candidate, out expanded, out objectArgsPresent);
+               }
+
                /// <summary>
                ///  Determines if the candidate method is applicable (section 14.4.2.1)
                ///  to the given set of arguments
                /// </summary>
-               static ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate, out bool expanded)
+               static ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate,
+                                                   out bool expanded, out bool objectArgsPresent)
                {
                        int arg_count;
                        Type param_type;
 
-                       expanded = false;
+                       expanded = objectArgsPresent = false;
+                       int num_narr_conv = 0;          // Count the narrowing conversion not involving object
+                                                       // arguments
                        
                        if (arguments == null)
                                arg_count = 0;
@@ -3503,8 +3952,8 @@ namespace Mono.MonoBASIC {
                                if (!HasArrayParameter (pd) && arg_count > pd_count)
                                        return ConversionType.None;
                        }       
+
                        ConversionType result = ConversionType.Widening;
-                       ArrayList newarglist = new ArrayList();
                        if (arg_count > 0) {
                                result = ConversionType.None;
                                int array_param_index = -1;
@@ -3541,7 +3990,7 @@ namespace Mono.MonoBASIC {
                                                        return ConversionType.None;
                                        }
 
-                                       if ((mod & Parameter.Modifier.REF) != 0) {
+                                       if (a.ArgType != Argument.AType.NoArg && (mod & Parameter.Modifier.REF) != 0) {
                                                a = new Argument (a.Expr, Argument.AType.Ref);
                                                if (!a.Resolve(ec,Location.Null))
                                                        return ConversionType.None;
@@ -3556,84 +4005,93 @@ namespace Mono.MonoBASIC {
                                        }
                                        if (match == ConversionType.None)
                                                match = CheckParameterAgainstArgument (ec, pd, i, a, param_type);
-                                       newarglist.Add (a);
                                        if (match == ConversionType.None)
                                                return ConversionType.None;
-                                       if (result == ConversionType.None)
+
+                                       if (match == ConversionType.Narrowing) {
+                                               result = match;
+                                               if (a.Expr.Type == TypeManager.object_type)
+                                                       objectArgsPresent = true;
+                                               else {
+                                                       objectArgsPresent = false;
+                                                       num_narr_conv ++;
+                                               }
+                                       } else if (result == ConversionType.None)
                                                result = match;
-                                       else if (match == ConversionType.Narrowing)
-                                               result = ConversionType.Narrowing;                                      
                                }
                        }
 
-#if false
-                       // We've found a candidate, so we exchange the dummy NoArg arguments
-                       // with new arguments containing the default value for that parameter
-
-                       ArrayList newarglist = new ArrayList();
-                       for (int i = 0; i < arg_count; i++) {
-                               Argument a = (Argument) arguments [i];
-                               Parameter p = null;
-
-                               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 (num_narr_conv > 0)  // There were narrowing conversions other than those for object arguments
+                               objectArgsPresent = false;
 
-                                       if (del_temp == null)
-                                               return ConversionType.None;
+                       return result;
+               }
 
-                                       a = new Argument (del_temp, Argument.AType.Expression);
-                                       if (!a.Resolve(ec, Location.Null))
-                                               return ConversionType.None;
+               internal static ArrayList ReorderArguments (MethodBase mb,
+                                                           ArrayList Arguments,
+                                                           CaseInsensitiveHashtable namedArgs,
+                                                           ref string ErrMsg,
+                                                           Location loc)
+               {
+                       ArrayList orderedArgs = new ArrayList ();
+                       ParameterData pd = GetParameterData (mb);
+                       bool error = false;
+                       for (int index = 0; index < pd.Count; index ++) {
+                               string paramName = pd.ParameterName (index);
+                               if (namedArgs.Contains (paramName)) {
+                                       if ((pd.ParameterModifier (index) & Parameter.Modifier.PARAMS) == Parameter.Modifier.PARAMS) {
+                                               error = true;
+                                               ErrMsg += "\n\t'" + FullMethodDesc (mb) + "': Named argument cannot match a ParamArray parameter";
+                                               continue;
+                                       }
+                                       int argIndex = (int) namedArgs [paramName];
+                                       orderedArgs.Add (Arguments [argIndex]);
+                               } else {
+                                       Parameter.Modifier p_mod = pd.ParameterModifier (index) & Parameter.Modifier.OPTIONAL;
+                                       if (p_mod == Parameter.Modifier.OPTIONAL)
+                                               orderedArgs.Add (new Argument (pd.ParameterName (index), new EmptyExpression (), Argument.AType.NoArg));
+                                        else {
+                                               error = true;
+                                               ErrMsg += "\n\t'" + FullMethodDesc (mb) + "': Argument not specified for parameter '" + paramName + "'";
+                                       }
                                }
+                       }
 
-                               if ((p != null) && ((p.ModFlags & Parameter.Modifier.REF) != 0)) {
-                                       a.ArgType = Argument.AType.Ref;
-                                       a.Resolve(ec, Location.Null);
-                               } else if ((pd.ParameterModifier (i) & Parameter.Modifier.REF) != 0) {
-                                       a.ArgType = Argument.AType.Ref;
-                                       a.Resolve(ec, Location.Null);
-                               }       
-                               newarglist.Add(a);
-                               int n = pd_count - arg_count;
-                               if (n > 0) {
-                                       for (int x = 0; x < n; x++) {
-                                               Parameter op = (Parameter) ps.FixedParameters[x + arg_count];
-                                               Argument b = new Argument (op.ParameterInitializer, Argument.AType.Expression);
-                                               b.Resolve(ec, Location.Null);
-                                               newarglist.Add (b);
+                       if (Arguments.Count > orderedArgs.Count) {
+                               for (int argIndex = 0; argIndex < Arguments.Count; argIndex ++) {
+                                       string argName = ((Argument) Arguments [argIndex]).ParamName;
+                                       bool found = false;
+                                       for (int paramIndex = 0; paramIndex < pd.Count; paramIndex ++) {
+                                               string paramName = pd.ParameterName (paramIndex);
+                                               if (String.Compare (argName, paramName, true) == 0) {
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               error = true;
+                                               ErrMsg += "\n\t'" + FullMethodDesc (mb) + "': '" + argName + "' is not a parameter";
                                        }
                                }
                        }
-#endif
-                       return result;
+                       if (error)
+                               return null;
+                       return orderedArgs;
                }
                
+/*
                static bool compare_name_filter (MemberInfo m, object filterCriteria)
                {
                        return (m.Name == ((string) filterCriteria));
                }
+*/
+
+               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
+                                                         ref ArrayList Arguments, Location loc)
+               {
+                       bool isLateBindingRequired;
+                       return OverloadResolve (ec, me, ref Arguments, loc, out isLateBindingRequired); 
+               }
 
                // We need an overload for OverloadResolve because Invocation.DoResolve
                // must pass Arguments by reference, since a later call to IsApplicable
@@ -3646,6 +4104,7 @@ namespace Mono.MonoBASIC {
                        return OverloadResolve (ec, me, ref a, loc);    
                }
 
+/*
                static string ToString(MethodBase mbase)
                {
                        if (mbase == null)
@@ -3667,6 +4126,7 @@ namespace Mono.MonoBASIC {
 
                        return mbase.ToString();
                }
+*/
                
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
@@ -3680,28 +4140,61 @@ namespace Mono.MonoBASIC {
                ///   loc: The location if we want an error to be reported, or a Null
                ///        location for "probing" purposes.
                ///
+               ///   isLateBindingRequired : Flag to indicate that this method call is
+               ///                           is a candidate for late binding. Set to true if
+               ///                           there is atleast one object argument and we get
+               ///                           * Two or more candidates that require widening conv
+               ///                           * Two or more candidates require narrowing conversions
+               ///                             (for object arguments **only**)
                ///   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)
+                                                         ref ArrayList Arguments, Location loc,
+                                                         out bool isLateBindingRequired)
                {
                        MethodBase method = null;
                        int argument_count;
                        ArrayList candidates = new ArrayList ();
+                       ArrayList lateBindingCandidates = new ArrayList ();
                        Hashtable expanded_candidates = new Hashtable();
                        int narrow_count = 0;
                        bool narrowing_candidate = false;
+                       errorMsg = "";
+                       isLateBindingRequired = false;
+                       CaseInsensitiveHashtable namedArgs = new CaseInsensitiveHashtable ();
+
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+
+                       if (!CheckNamedArguments (Arguments, loc))
+                               return null;
 
+                       if (!GetNamedArgPos (Arguments, ref namedArgs, loc))
+                               return null;
+
+                       ArrayList newarglist = Arguments;
                        foreach (MethodBase candidate in me.Methods){
-                               bool candidate_expanded;
-                               ConversionType m = IsApplicable (ec, Arguments, candidate, out candidate_expanded);
+                               bool candidate_expanded, object_args_present;
+                               newarglist = Arguments;
+                               if (argument_count > 0 && namedArgs.Count != 0) {
+                                       newarglist = ReorderArguments (candidate, Arguments, namedArgs, ref errorMsg, loc);
+                                       if (newarglist == null)
+                                               continue;
+                               }
+
+                               ConversionType m = IsApplicable (ec, newarglist, candidate, out candidate_expanded, out object_args_present);
                                if (candidate_expanded)
                                        expanded_candidates [candidate] = candidate;
                                if (m == ConversionType.None)
                                        continue;
                                else if (m == ConversionType.Narrowing) {
+                                       if (object_args_present)   // if the narrowing conversion was due 
+                                                                  // to the argument being an object
+                                               lateBindingCandidates.Add (candidate);
                                        if (method == null) {
                                                method = candidate;
                                                narrowing_candidate = true;
@@ -3723,22 +4216,24 @@ namespace Mono.MonoBASIC {
                        }
 
                        if (candidates.Count == 0) {
-                               if (narrow_count > 1)
-                                       method = null;
-                               else if (narrow_count == 1)
+                               if (lateBindingCandidates.Count > 1) {
+                                       isLateBindingRequired = true;
+                                       return null;
+                               }
+
+                               if (narrow_count > 1) {
+                                       if (lateBindingCandidates.Count == 1)
+                                               method = (MethodBase) lateBindingCandidates [0];
+                                       else 
+                                               method = null;
+                               } else if (narrow_count == 1)
                                        candidates = null;
                        } else if (candidates.Count == 1) {
                                method = (MethodBase)candidates [0];
                                candidates = null;
                        } else
-                               narrow_count = 0;
-
-                       if (Arguments == null)
-                               argument_count = 0;
-                       else
-                               argument_count = Arguments.Count;
+                               narrow_count  = 0;
 
-                       
                        if (method == null) {
                                //
                                // Okay so we have failed to find anything so we
@@ -3754,7 +4249,7 @@ namespace Mono.MonoBASIC {
 
                                        bool dummy;
                                        if (narrow_count != 0) {
-                                               if (IsApplicable (ec, Arguments, c, out dummy) == ConversionType.None)
+                                               if (IsApplicable (ec, Arguments, c, out dummy) == ConversionType.None)
                                                        continue;
                                                Report.Error (1502, loc,
                                                        "Overloaded match for method '" +
@@ -3776,16 +4271,17 @@ namespace Mono.MonoBASIC {
 
                        if (candidates != null) {
                                foreach (MethodBase candidate in candidates){
-                                       if (candidate == method)
-                                               continue;
+                                       if (candidate == method)
+                                               continue;
+
 
                                        if (BetterFunction (ec, Arguments, candidate, method,
                                                                false, loc) == Applicability.Better) {
-                                               Report.Error (
-                                                       121, loc,
-                                                       "Ambiguous call of '" + me.Name + "' when selecting function due to implicit casts");
+                                               Report.Error (
+                                                       121, loc,
+                                                       "Ambiguous call of '" + me.Name + "' when selecting function due to implicit casts");
                                                return null;
-                                       }
+                                       }
                                }
                        }
 
@@ -3798,7 +4294,14 @@ namespace Mono.MonoBASIC {
 
                        bool chose_params_expanded = expanded_candidates.Contains (method);
 
-                       Arguments = ConstructArgumentList(ec, Arguments, method);
+                       newarglist = Arguments;
+                       if (argument_count > 0 && namedArgs.Count != 0) {
+                               string err = "";
+                               newarglist = ReorderArguments (method, Arguments, namedArgs, ref err, loc);
+                               if (newarglist == null)
+                                       return null;
+                       }
+                       Arguments = ConstructArgumentList(ec, newarglist, namedArgs, method);
                        if (VerifyArgumentsCompat (ec, Arguments, argument_count, method,
                                                   chose_params_expanded, null, loc))
                        {
@@ -3808,19 +4311,70 @@ namespace Mono.MonoBASIC {
                                return null;
                }
 
-               public static ArrayList ConstructArgumentList (EmitContext ec, ArrayList Arguments,     MethodBase method)
+               internal static bool CheckNamedArguments (ArrayList Arguments, Location loc) 
+               {
+                       if (Arguments == null || Arguments.Count == 0)
+                               return true;
+                       
+                       bool namedArgFound = false;
+                       for (int index = 0; index < Arguments.Count; index ++) {
+                               Argument a = (Argument) Arguments [index];
+                               if (a.ParamName == null || a.ParamName == "") {
+                                       if (namedArgFound) {
+                                               Report.Error (30241, loc,
+                                                       "Named argument expected");
+                                               return false;
+                                       }
+                               } else
+                                       namedArgFound = true;
+                       }
+
+                       return true;
+               }
+
+               internal static bool GetNamedArgPos (ArrayList Arguments, ref CaseInsensitiveHashtable namedArgs, Location loc) 
+               {
+                       namedArgs.Clear ();
+                       if (Arguments == null || Arguments.Count == 0)
+                               return true;
+                       for (int index = 0; index < Arguments.Count; index ++) {
+                               Argument a = (Argument) Arguments [index];
+                               if (a.ParamName == null || a.ParamName == "")
+                                       // none of the args are named
+                                       return true;
+                               if (namedArgs.Contains (a.ParamName)) {
+                                       Report.Error (30274, loc, "Parameter '" + a.ParamName +"'already has a matching argument");
+                                       return false;
+                               }
+                               namedArgs.Add (a.ParamName, index);
+                       }
+                       return true;
+               }
+
+               public static ArrayList ConstructArgumentList (EmitContext ec, ArrayList Arguments, CaseInsensitiveHashtable namedArgs, MethodBase method)
                {
                        ArrayList newarglist = new ArrayList();
                        int arg_count = Arguments == null ? 0 : Arguments.Count;
 
                        ParameterData pd = GetParameterData (method);
-                       
-
+                       bool argNamesGiven = (namedArgs.Count > 0);
                        for (int i = 0; i < arg_count; i++) {
                                Argument a = (Argument) Arguments [i];
                                Type param_type = pd.ParameterType (i);
 
                                bool IsDelegate = TypeManager.IsDelegateType (param_type);
+                               if (a.ArgType == Argument.AType.NoArg) {
+                                       Expression pdvalue = pd.DefaultValue (i);
+                                       pdvalue.Resolve (ec);
+                                       if (pdvalue != NullLiteral.Null)
+                                               pdvalue = ConvertImplicit (ec, pdvalue, param_type, Location.Null);;
+                                       if (argNamesGiven)
+                                               a = new Argument (pd.ParameterName (i), pdvalue, Argument.AType.Expression);
+                                       else
+                                               a = new Argument (pdvalue, Argument.AType.Expression);
+                                       a.Resolve (ec, Location.Null);
+                               }
+
                                if (IsDelegate) {       
                                        if (a.ArgType == Argument.AType.AddressOf) {
                                                a = new Argument ((Expression) a.Expr, Argument.AType.Expression);
@@ -3847,11 +4401,18 @@ namespace Mono.MonoBASIC {
                                return newarglist;
 
                        for (int i = arg_count; i < pd.Count; i++) {
+                               Type param_type = pd.ParameterType (i);
                                Expression e = pd.DefaultValue (i);
-                               Argument a = new Argument (e, Argument.AType.Expression);
+                               e.Resolve (ec);
+                               if (e != NullLiteral.Null)
+                                       e = ConvertImplicit (ec, e, param_type, Location.Null);
+                               Argument a = null;
+                               if (argNamesGiven)
+                                       a = new Argument (e, Argument.AType.Expression);
+                               else
+                                       a = new Argument (pd.ParameterName (i), e, Argument.AType.Expression);
                                if ((pd.ParameterModifier (i) & Parameter.Modifier.REF) != 0)
                                        a.ArgType = Argument.AType.Ref;
-                               e.Resolve (ec);
                                a.Resolve (ec, Location.Null);
                                newarglist.Add (a);
                        }
@@ -3893,9 +4454,11 @@ namespace Mono.MonoBASIC {
                                        return false;   
                                }
                                if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS &&
-                               chose_params_expanded)
+                               chose_params_expanded)
                                        parameter_type = TypeManager.TypeToCoreType (parameter_type.GetElementType ());
-                               if (a.Type != parameter_type){
+                               // By pass conversion for foll. case and handle it in EmitArguments()
+
+                               if (a.ArgType != Argument.AType.Ref && a.Type != parameter_type){
                                        Expression conv;
                                        
                                        conv = ConvertImplicit (ec, a_expr, parameter_type, loc);
@@ -3934,9 +4497,9 @@ namespace Mono.MonoBASIC {
                                }
 
                                Parameter.Modifier a_mod = a.GetParameterModifier () &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                                       ~(Parameter.Modifier.REF);
                                Parameter.Modifier p_mod = pd.ParameterModifier (j) &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
+                                       ~(Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
 
                                if (a_mod != p_mod &&
                                    pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
@@ -3956,13 +4519,48 @@ namespace Mono.MonoBASIC {
 
                        return true;
                }
-       
+               
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        this.is_left_hand = true;
                        Expression expr_to_return = DoResolve (ec);
+                       if (expr_to_return is PropertyGroupExpr) {
+                               PropertyGroupExpr pe = expr_to_return as PropertyGroupExpr;
+                               pe = (PropertyGroupExpr) pe.ResolveLValue (ec, right_side);
+                               if (pe == null)
+                                       return null;
+                               if (pe.IndexerAccessRequired) {
+                                       if (pe.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_to_return, idxs, expr.Location);
+                                               ArrayAccess aa = new ArrayAccess (ea, expr_to_return.Location);
+                                               expr_to_return = aa.DoResolve(ec);
+                                               expr_to_return.eclass = ExprClass.Variable;
+                                       } else {
+                                               //
+                                               // check whether this is a indexer
+                                               //
+                                               ArrayList idxs = new ArrayList();
+                                               foreach (Argument a in Arguments) {
+                                                       idxs.Add (a.Expr);
+                                               }
+                                               ElementAccess ea = new ElementAccess (expr_to_return, idxs, expr.Location);
+                                               IndexerAccess ia = new IndexerAccess (ea, expr_to_return.Location);
+                                               if (is_left_hand)
+                                                       expr_to_return = ia.DoResolveLValue (ec, right_side);
+                                               else
+                                                       expr_to_return = ia.DoResolve(ec);
+                                       }
+                                       return expr_to_return;
+                               }
+                       }
 
-                       if (expr_to_return is IndexerAccess) {
+                       if (expr_to_return is IndexerAccess && is_left_hand) {
                                IndexerAccess ia = expr_to_return as IndexerAccess;
                                expr_to_return = ia.DoResolveLValue (ec, right_side);
                        }
@@ -3977,29 +4575,53 @@ namespace Mono.MonoBASIC {
                        // trigger the invocation
                        //
                        Expression expr_to_return = null;
+                       Expression temp = null;
 
                        if (expr is BaseAccess)
                                is_base = true;
 
+                       ResolveFlags flags;
                        if ((ec.ReturnType != null) && (expr.ToString() == ec.BlockName)) {
                                ec.InvokingOwnOverload = true;
-                               expr = expr.Resolve (ec, ResolveFlags.MethodGroup);
+                               flags = ResolveFlags.MethodGroup;
+                               temp = expr.Resolve (ec, flags);
                                ec.InvokingOwnOverload = false;
                        }
                        else                            
                        {
                                ec.InvokingOwnOverload = false;
-                               expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
-                       }       
-                       if (expr == null)
+                               flags = ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup;
+                               temp = expr.Resolve (ec, flags);
+                       }
+
+                       if (temp == null) {
+                               if (is_left_hand)
+                                       return null;
+                       
+                               if (expr is MemberAccess) {
+                                       MemberAccess m = expr as MemberAccess;
+                                       if (m.Expr.Type == TypeManager.object_type) {
+                                               StatementSequence etmp = new StatementSequence (ec.CurrentBlock, 
+                                                                               loc, expr, Arguments, 
+                                                                               is_retval_required, is_left_hand);
+                                               if (!etmp.ResolveArguments (ec))
+                                                       return null;
+                                               etmp.GenerateLateBindingStatements();
+                                               this.is_latebinding = true;
+                                               return etmp.Resolve (ec);
+                                       }
+                               }
                                return null;
+                       }
+       
+                       expr = temp;
 
                        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)) 
+                       if (!(expr is MethodGroupExpr || expr is PropertyGroupExpr)) 
                        {
                                Type expr_type = expr.Type;
 
@@ -4030,12 +4652,22 @@ namespace Mono.MonoBASIC {
                        if (expr is MethodGroupExpr) 
                        {
                                MethodGroupExpr mg = (MethodGroupExpr) expr;
-                               method = OverloadResolve (ec, mg, ref Arguments, loc);
-
+                               bool isLateBindingRequired = false;
+                               method = OverloadResolve (ec, mg, ref Arguments, loc, out isLateBindingRequired);
                                if (method == null)
                                {
+                                       if (isLateBindingRequired) {
+                                               Expression type_expr = new TypeOf (Parser.DecomposeQI (mg.DeclaringType.Name, loc), loc);
+                                               StatementSequence etmp = new StatementSequence (ec.CurrentBlock, 
+                                                                       loc, null, mg.Name, type_expr, 
+                                                                       Arguments, is_retval_required, is_left_hand);
+                                               if (! etmp.ResolveArguments (ec))
+                                                       return null;
+                                               etmp.GenerateLateBindingStatements ();
+                                               return etmp.Resolve (ec);
+                                       }
                                        Error (30455,
-                                               "Could not find any applicable function to invoke for this argument list");
+                                               "Could not find any applicable function to invoke for this argument list" + errorMsg);
                                        return null;
                                }
 
@@ -4065,101 +4697,86 @@ namespace Mono.MonoBASIC {
                                }
                                eclass = ExprClass.Value;
                                expr_to_return = this;
+                               return expr_to_return;
                        }
 
-                       if (expr is PropertyExpr) 
+                       if (expr is PropertyGroupExpr) 
                        {
-                               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());
+                               PropertyGroupExpr pe = ((PropertyGroupExpr) expr);
+                               if (pe.Arguments != null)
+                                       goto skip_already_resolved_property;
+                               if (Arguments != null)
+                                       pe.Arguments = (ArrayList) Arguments.Clone ();
+                               if (is_left_hand)
+                                       return pe;
+                               string name = pe.Name;
+                               pe = (PropertyGroupExpr) pe.Resolve (ec);
+                               if (pe == null) {
+                                       Error (30057, "Property '" + name + "' cannot be invoked with given arguments");
+                                       return null;
                                }
-                       }
-
-                       if (expr is FieldExpr || expr is LocalVariableReference || expr is ParameterReference) {
-                               if (expr.Type.IsArray) {
-                                       // If we are here, expr must be an ArrayAccess
-                                       ArrayList idxs = new ArrayList();
-                                       foreach (Argument a in Arguments)
-                                       {
-                                               idxs.Add (a.Expr);
-                                       }
-                                       ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
-                                       ArrayAccess aa = new ArrayAccess (ea, expr.Location);
-                                       expr_to_return = aa.DoResolve(ec);
-                                       expr_to_return.eclass = ExprClass.Variable;
-                               } else {
-                                       //
-                                       // check whether this is a indexer
-                                       //
-                                       ArrayList idxs = new ArrayList();
-                                       foreach (Argument a in Arguments) {
-                                               idxs.Add (a.Expr);
-                                       }
-                                       ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
-                                       IndexerAccess ia = new IndexerAccess (ea, expr.Location);
-                                       if (!is_left_hand)
-                        expr_to_return = ia.DoResolve(ec);
-                                       else
-                                               expr_to_return = ia.DoResolve(ec);
-                                       //
-                                       // Since all the above are failed we need to do
-                                       // late binding
-                                       //
-                                       if (expr_to_return == null) {
-
-                                               // 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));
+                               if (!pe.IndexerAccessRequired)
+                                       return pe;
+                               expr = pe;
+                       }
 
-                                               Expression lig_call = new Invocation (lig_call_expr, args, Location.Null);
-                                               expr_to_return = lig_call.Resolve(ec);
-                                               expr_to_return.eclass = ExprClass.Variable;
+                       skip_already_resolved_property:
+                       if (expr.Type.IsArray) {
+                               // If we are here, expr must be an ArrayAccess
+                               ArrayList idxs = new ArrayList();
+                               foreach (Argument a in Arguments)
+                               {
+                                       idxs.Add (a.Expr);
+                               }
+                               ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
+                               ArrayAccess aa = new ArrayAccess (ea, expr.Location);
+                               expr_to_return = aa.DoResolve(ec);
+                               expr_to_return.eclass = ExprClass.Variable;
+                       } else {
+                               //
+                               // check whether this is a indexer
+                               //
+                               ArrayList idxs = new ArrayList();
+                               foreach (Argument a in Arguments) {
+                                       idxs.Add (a.Expr);
+                               }
+                               ElementAccess ea = new ElementAccess (expr, idxs, expr.Location);
+                               IndexerAccess ia = new IndexerAccess (ea, expr.Location);
+                               if (!is_left_hand)
+                                       expr_to_return = ia.DoResolve(ec);
+                               else
+                                       expr_to_return = ia.DoResolve(ec);
+                               //
+                               // Since all the above are failed we need to do
+                               // late binding
+                               //
+                               if (expr_to_return == null) {
+
+                                       // We can't resolve now, but we
+                                       // have to try to access the array with a call
+                                       // to LateIndexGet/Set in the runtime
+                                       if (! is_left_hand) {
+                                               StatementSequence etmp = new StatementSequence (ec.CurrentBlock, 
+                                                                       loc, ia, Arguments, 
+                                                                       true, false);
+                                               if (!etmp.ResolveArguments (ec))
+                                                       return null;
+                                               etmp.GenerateLateBindingStatements();
+                                               return etmp.Resolve (ec);
                                        }
+                                       return null;
                                }
                        }
 
                        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 `" +
+               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
@@ -4198,7 +4815,6 @@ namespace Mono.MonoBASIC {
                public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
                {
                        ParameterData pd = GetParameterData (mb);
-
                        //
                        // If we are calling a params method with no arguments, special case it
                        //
@@ -4217,6 +4833,9 @@ namespace Mono.MonoBASIC {
 
                        for (int i = 0; i < top; i++){
                                Argument a = (Argument) arguments [i];
+                               Type parameter_type = pd.ParameterType(i);
+                               Type argtype = a.Type;
+                               Type arg_expr_type = a.Expr.Type;
 
                                if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
                                        //
@@ -4229,18 +4848,48 @@ namespace Mono.MonoBASIC {
                                                EmitParams (ec, i, arguments);
                                        return;
                                }
-
-                               if ((a.ArgType == Argument.AType.Ref || a.ArgType == Argument.AType.Out) &&
-                                       !(a.Expr is IMemoryLocation)) {
-                                       LocalTemporary tmp = new LocalTemporary (ec, pd.ParameterType (i));
+                               if ((a.ArgType == Argument.AType.Ref ) &&
+                                       (parameter_type != arg_expr_type ||
+                                        ! (a.Expr is IMemoryLocation))) {
                                        
-                                       a.Expr.Emit (ec);
-                                       tmp.Store (ec);
-                                       a = new Argument (tmp, a.ArgType);
+                                        LocalTemporary localtmp = new LocalTemporary (ec, parameter_type ); 
+
+                                       if((arg_expr_type != parameter_type) && (a.ArgType == Argument.AType.Ref)) {                                     
+                                               Expression e = ConvertImplicit (ec, a.Expr, parameter_type, Location.Null);
+                                               is_byref_conversion = true;
+                                               e.Emit (ec);
+                                       } else 
+                                               a.Expr.Emit (ec);
+                                       
+
+
+                                       if (tempvars == null)
+                                               tempvars = new ArrayList ();
+                                       if (a.Expr is IMemoryLocation && is_byref_conversion ) {
+                                               Expression conv;
+                                               if(argtype.IsByRef)
+                                                       argtype = argtype.GetElementType();
+                                               conv = ConvertImplicit (ec, localtmp, argtype, Location.Null);
+                                               tempvars.Add (new Assign (a.Expr, conv, Location.Null));
+
+                                       } else if (a.Expr is PropertyGroupExpr) {
+                                               // FIXME: We shouldnt be doing Resolve from inside 'Emit'. 
+                                               // Have to find a way to push this up to 'Resolve'
+                                               Expression conv;
+                                               if(argtype.IsByRef)
+                                                       argtype = argtype.GetElementType();
+                                               conv = ConvertImplicit (ec, localtmp, argtype, Location.Null);
+                                               Assign assgn = new Assign (a.Expr, conv, Location.Null);
+                                               Expression e = assgn.Resolve (ec);
+                                               tempvars.Add (e);
+                                       }
+                                               localtmp.Store (ec);
+                                       a = new Argument (localtmp, a.ArgType);
                                }
-                                           
-                               a.Emit (ec);
-                       }
+                                a.Emit (ec);
+                        }
+
+
 
                        if (pd.Count > top &&
                            pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
@@ -4279,6 +4928,10 @@ namespace Mono.MonoBASIC {
                {
                        ILGenerator ig = ec.ig;
                        bool struct_call = false;
+                       bool is_myclass = false;
+
+                       if (instance_expr is This && ((This) instance_expr).AccessType == This.TypeOfAccess.MyClass) 
+                               is_myclass = true;
 
                        Type decl_type = method.DeclaringType;
 
@@ -4385,7 +5038,7 @@ namespace Mono.MonoBASIC {
 
                        EmitArguments (ec, method, Arguments);
 
-                       if (is_static || struct_call || is_base)
+                       if (is_static || struct_call || is_base || is_myclass)
                        {
                                if (method is MethodInfo) 
                                {
@@ -4403,6 +5056,7 @@ namespace Mono.MonoBASIC {
                        }
                }
                
+/*
                static void EmitPropertyArgs (EmitContext ec, ArrayList prop_args)
                {
                        int top = prop_args.Count;
@@ -4413,11 +5067,12 @@ namespace Mono.MonoBASIC {
                                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);
                }
@@ -4431,8 +5086,20 @@ namespace Mono.MonoBASIC {
                        //
                        if (method is MethodInfo){
                                Type ret = ((MethodInfo)method).ReturnType;
-                               if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
+                               if ((TypeManager.TypeToCoreType (ret) != TypeManager.void_type) && !this.is_latebinding) {
                                        ec.ig.Emit (OpCodes.Pop);
+
+                                       if (tempvars != null) {
+                                               foreach (Expression s in tempvars) {
+                                                       if (s is ExpressionStatement)
+                                                               ((ExpressionStatement) s).EmitStatement (ec);
+                                                       else
+                                                               s.Emit (ec);
+                                               }
+                                               tempvars.Clear ();
+                                       }
+                               }
+                               
                        }
                }
        }
@@ -4537,7 +5204,7 @@ namespace Mono.MonoBASIC {
                                        "or classes marked as MustInherit");
                                return null;
                        }
-                       
+
                        bool is_struct = false;
                        is_struct = type.IsValueType;
                        eclass = ExprClass.Value;
@@ -4890,6 +5557,7 @@ namespace Mono.MonoBASIC {
                        }
                }
 
+/*
                void Error_NegativeArrayIndex ()
                {
                        Error (284, "Can not create array with a negative size");
@@ -4941,6 +5609,7 @@ namespace Mono.MonoBASIC {
 
                        return target;
                }
+*/
 
                //
                // Creates the type of the array
@@ -5399,18 +6068,36 @@ namespace Mono.MonoBASIC {
        /// </summary>
        public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
 
+               public enum TypeOfAccess : byte {
+                       Me, MyClass
+               }
+
                Block block;
                VariableInfo vi;
+               TypeOfAccess access_type;
                
+               public This (TypeOfAccess access_type, Block block, Location loc)
+               {
+                       this.loc = loc;
+                       this.block = block;
+                       this.access_type = access_type;
+               }
+
                public This (Block block, Location loc)
                {
                        this.loc = loc;
                        this.block = block;
+                       this.access_type = TypeOfAccess.Me;
                }
 
                public This (Location loc)
                {
                        this.loc = loc;
+                       this.access_type = TypeOfAccess.Me;
+               }
+
+               public TypeOfAccess AccessType { 
+                       get { return access_type; }
                }
 
                public bool IsAssigned (EmitContext ec, Location loc)
@@ -5600,6 +6287,9 @@ namespace Mono.MonoBASIC {
                public readonly string Identifier;
                Expression expr;
                Expression member_lookup;
+               bool is_invocation = false;
+               bool is_left_hand;
+               bool is_addressof = false;
                
                public MemberAccess (Expression expr, string id, Location l)
                {
@@ -5608,6 +6298,38 @@ namespace Mono.MonoBASIC {
                        loc = l;
                }
 
+               public MemberAccess (Expression expr, string id, Location l, bool isInvocation)
+               {
+                       this.expr = expr;
+                       Identifier = id;
+                       loc = l;
+                       is_invocation = isInvocation;
+               }
+
+               public bool IsInvocation {
+                       get {
+                               return is_invocation;
+                       }
+                       set {
+                               is_invocation = value;
+                       }
+               }
+
+               public bool IsAddressOf {
+                       set {
+                               is_addressof = value;
+                       }
+               }
+
+               public bool IsLeftHand {
+                       get {
+                               return is_left_hand;
+                       }
+                       set {
+                               is_left_hand = value;
+                       }
+               }
+
                public Expression Expr {
                        get {
                                return expr;
@@ -5643,7 +6365,8 @@ namespace Mono.MonoBASIC {
                                                              Expression left, Location loc,
                                                              Expression left_original)
                {
-                       bool left_is_type, left_is_explicit;
+                        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.
@@ -5666,14 +6389,27 @@ namespace Mono.MonoBASIC {
                                
                                if (fi is FieldBuilder) {
                                        Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
-                                       
                                        if (c != null) {
-                                               //object o = c.LookupConstantValue (ec);
+                                        object o;
+                                        if (!c.LookupConstantValue (out o, ec))
+                                                return null;
+                                       
                                                object real_value = ((Constant) c.Expr).GetValue ();
+                                         Expression exp = Constantify (real_value, fi.FieldType);
 
-                                               return Constantify (real_value, fi.FieldType);
-                                       }
+                                        return exp;
+                                       }
                                }
+                               
+                                 // IsInitOnly is because of MS compatibility, I don't know why but they emit decimal constant as InitOnly
+                        
+                       if (fi.IsInitOnly && !(fi is FieldBuilder) && fi.FieldType == TypeManager.decimal_type) {
+                                object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false);
+                                if (attrs.Length == 1)
+                                        return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
+                        }
+
+
 
                                if (fi.IsLiteral) {
                                        Type t = fi.FieldType;
@@ -5727,17 +6463,31 @@ namespace Mono.MonoBASIC {
                        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;
+                               if (left_is_type) {
+                                       if (me is PropertyGroupExpr) {
+                                               PropertyGroupExpr mg = me as PropertyGroupExpr;
+                                               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 {
+                                               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 {
@@ -5810,6 +6560,7 @@ namespace Mono.MonoBASIC {
                                SimpleName child_expr = (SimpleName) expr;
 
                                Expression new_expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
+                               ((SimpleName) new_expr).IsInvocation = is_invocation;
 
                                if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
                                        return new_expr.Resolve (ec, flags);
@@ -5847,13 +6598,12 @@ namespace Mono.MonoBASIC {
                        }
                        
                        if (expr_type.IsPointer){
-                               Error (23, "The '.' operator can not be applied to pointer operands (" +
+                               Error (30311, "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.
@@ -5868,8 +6618,28 @@ namespace Mono.MonoBASIC {
                                        expr_type, expr_type, AllMemberTypes, AllBindingFlags |
                                        BindingFlags.NonPublic, Identifier);
                                        
-                               if (lookup == null)
-                                       Error (30456, "'" + expr_type + "' does not contain a definition for '" + Identifier + "'");
+                               if (lookup == null) {
+                                       if (expr_type != TypeManager.object_type)
+                                               Error (30456, "'" + expr_type + "' does not contain a definition for '" + Identifier + "'");
+                                       // If this came as a part of Invocation, 
+                                       // Since argumets are not known, return null, 
+                                       // let Invocation's Resolve take care
+                                       if (is_invocation)
+                                               return null;
+
+                                       else if (! is_left_hand) {
+                                               StatementSequence etmp = new StatementSequence (ec.CurrentBlock, 
+                                                                               loc, this, null, 
+                                                                               true, is_left_hand);
+                                               etmp.GenerateLateBindingStatements();
+                                               return etmp.Resolve (ec);
+                                       } 
+
+                                       // if the expression is a left hand side of an assignment,
+                                       // return null, as we dont know the RHS
+                                       // Let assign take care of Late Binding
+                                       return null;
+                               }
                                else
                                {
                                        if ((expr_type != ec.ContainerType) &&
@@ -5929,6 +6699,14 @@ namespace Mono.MonoBASIC {
                        if (member_lookup == null)
                                return null;
 
+                       if ((member_lookup is MethodGroupExpr) && ! is_invocation && !is_addressof) {
+                               Expression inv = new Invocation (this, new ArrayList (), loc);
+                               return inv.Resolve (ec);
+                       }
+
+                       if (member_lookup is PropertyGroupExpr && is_invocation) // As we dont know the arguments yet
+                               return member_lookup;
+
                        // The following DoResolve/DoResolveLValue will do the definite assignment
                        // check.
                        if (right_side != null)
@@ -5936,6 +6714,7 @@ namespace Mono.MonoBASIC {
                        else
                                member_lookup = member_lookup.DoResolve (ec);
 
+
                        return member_lookup;
                }
 
@@ -6596,10 +7375,6 @@ namespace Mono.MonoBASIC {
                                                return ix;
                                }
                        }
-
-                       Report.Error (21, loc,
-                                     "Type '" + TypeManager.MonoBASIC_Name (lookup_type) +
-                                     "' does not have any indexers defined");
                        return null;
                }
        }
@@ -6614,7 +7389,7 @@ namespace Mono.MonoBASIC {
                MethodInfo get, set;
                Indexers ilist;
                ArrayList set_arguments;
-               bool is_base_indexer;
+               //bool is_base_indexer;
 
                protected Type indexer_type;
                protected Type current_type;
@@ -6631,11 +7406,23 @@ namespace Mono.MonoBASIC {
                                         Location loc)
                {
                        this.instance_expr = instance_expr;
-                       this.is_base_indexer = is_base_indexer;
+                       //this.is_base_indexer = is_base_indexer;
                        this.eclass = ExprClass.Value;
                        this.loc = loc;
                }
 
+               public Expression Instance {
+                       get {
+                               return instance_expr;
+                       }
+               }
+
+               public ArrayList Arguments {
+                       get {
+                               return arguments;
+                       }
+               }
+
                protected virtual bool CommonResolve (EmitContext ec)
                {
                        indexer_type = instance_expr.Type;
@@ -6655,10 +7442,18 @@ namespace Mono.MonoBASIC {
                        //
                        // This is a group of properties, piles of them.  
 
-                       if (ilist == null)
+                       if (ilist == null) {
                                ilist = Indexers.GetIndexersForType (
                                        current_type, indexer_type, loc);
 
+                               if (ilist == null && indexer_type != TypeManager.object_type) {
+                                       Report.Error (21, loc,
+                                               "Type '" + TypeManager.MonoBASIC_Name (indexer_type) +
+                                               "' does not have any indexers defined");
+                                       return null;
+                               }
+                       }
+
                        //
                        // Step 2: find the proper match
                        //
@@ -6667,8 +7462,9 @@ namespace Mono.MonoBASIC {
                                        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");
+                               if (instance_expr.Type != TypeManager.object_type)
+                                       Error (30524, "indexer can not be used in this context, because " +
+                                               "it lacks a 'get' accessor");
                                return null;
                        }
 
@@ -6689,9 +7485,16 @@ namespace Mono.MonoBASIC {
 
                        Type right_type = right_side.Type;
 
-                       if (ilist == null)
+                       if (ilist == null) {
                                ilist = Indexers.GetIndexersForType (
                                        current_type, indexer_type, loc);
+                               if (ilist == null && indexer_type != TypeManager.object_type) {
+                                       Report.Error (21, loc,
+                                               "Type '" + TypeManager.MonoBASIC_Name (indexer_type) +
+                                               "' does not have any indexers defined");
+                                       return null;
+                               }
+                       }
 
                        if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
                                set_arguments = (ArrayList) arguments.Clone ();
@@ -6702,7 +7505,7 @@ namespace Mono.MonoBASIC {
                        }
                        
                        if (set == null){
-                               Error (200, "indexer X.this [" + TypeManager.MonoBASIC_Name (right_type) +
+                               Error (30526, "indexer X.this [" + TypeManager.MonoBASIC_Name (right_type) +
                                       "] lacks a 'set' accessor");
                                return null;
                        }