2001-09-17 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 071f75a7d52e11076ae654dc7f2ddb92d97b7b9a..eb2f6b2c7e4a3cce411b7778ab8a9e73daee8dad 100755 (executable)
@@ -74,14 +74,11 @@ namespace CIR {
                static Expression ExprClassFromMemberInfo (MemberInfo mi)
                {
                        if (mi is EventInfo){
-                               // FIXME: Implement
-                               return null;
+                               return new EventExpr ((EventInfo) mi);
                        } else if (mi is FieldInfo){
-                               // FIXME: Implement
-                               return null;
+                               return new FieldExpr ((FieldInfo) mi);
                        } else if (mi is PropertyInfo){
-                               // FIXME: implement
-                               return null;
+                               return new PropertyExpr ((PropertyInfo) mi);
                        } else if (mi is Type)
                                return new TypeExpr ((Type) mi);
 
@@ -101,43 +98,71 @@ namespace CIR {
                //
                // Return values:
                //     If the return value is an Array, then it is an array of
-               //     MethodInfos
+               //     MethodBases
                //   
                //     If the return value is an MemberInfo, it is anything, but a Method
                //
                //     null on error.
                //
-               static Expression MemberLookup (Report r, Type t, string name, bool same_type)
-               {
-                       MemberTypes mt =
-                               // MemberTypes.Constructor |
-                               MemberTypes.Event       |
-                               MemberTypes.Field       |
-                               MemberTypes.Method      |
-                               MemberTypes.NestedType  |
-                               MemberTypes.Property;
-                       
-                       BindingFlags bf =
-                               BindingFlags.Public |
-                               BindingFlags.Static |
-                               BindingFlags.Instance;
-                       
+               // FIXME: When calling MemberLookup inside an `Invocation', we should pass
+               // the arguments here and have MemberLookup return only the methods that
+               // match the argument count/type, unlike we are doing now (we delay this
+               // decision).
+               //
+               // This is so we can catch correctly attempts to invoke instance methods
+               // from a static body (scan for error 120 in ResolveSimpleName).
+               //
+               public static Expression MemberLookup (RootContext rc, Type t, string name,
+                                                         bool same_type, MemberTypes mt, BindingFlags bf)
+               {
                        if (same_type)
                                bf |= BindingFlags.NonPublic;
-                       
-                       MemberInfo [] mi = t.FindMembers (mt, bf, Type.FilterName, name);
 
-                       if (mi.Length == 1 && !(mi [0] is MethodInfo))
+                       MemberInfo [] mi = rc.TypeManager.FindMembers (t, mt, bf, Type.FilterName, name);
+
+                       if (mi == null)
+                               return null;
+                       
+                       if (mi.Length == 1 && !(mi [0] is MethodBase))
                                return Expression.ExprClassFromMemberInfo (mi [0]);
 
                        for (int i = 0; i < mi.Length; i++)
-                               if (!(mi [i] is MethodInfo)){
-                                       r.Error (-5, "Do not know how to reproduce this case: Methods and non-Method with the same name, report this please");
-                                       
+                               if (!(mi [i] is MethodBase)){
+                                       rc.Report.Error (-5, "Do not know how to reproduce this case: " + 
+                                                        "Methods and non-Method with the same name, report this please");
+
+                                       for (i = 0; i < mi.Length; i++){
+                                               Type tt = mi [i].GetType ();
+
+                                               Console.WriteLine (i + ": " + mi [i]);
+                                               while (tt != TypeManager.object_type){
+                                                       Console.WriteLine (tt);
+                                                       tt = tt.BaseType;
+                                               }
+                                       }
                                }
 
                        return new MethodGroupExpr (mi);
                }
+
+               public const MemberTypes AllMemberTypes =
+                       MemberTypes.Constructor |
+                       MemberTypes.Event       |
+                       MemberTypes.Field       |
+                       MemberTypes.Method      |
+                       MemberTypes.NestedType  |
+                       MemberTypes.Property;
+               
+               public const BindingFlags AllBindingsFlags =
+                       BindingFlags.Public |
+                       BindingFlags.Static |
+                       BindingFlags.Instance;
+
+               public static Expression MemberLookup (RootContext rc, Type t, string name,
+                                                         bool same_type)
+               {
+                       return MemberLookup (rc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
+               }
                
                // <summary>
                //   Resolves the E in `E.I' side for a member_access
@@ -174,7 +199,7 @@ namespace CIR {
 
                        switch (left_e.ExprClass){
                        case ExprClass.Type:
-                               return  MemberLookup (tc.RootContext.Report,
+                               return  MemberLookup (tc.RootContext,
                                                      left_e.Type, right,
                                                      left_e.Type == tc.TypeBuilder);
                                
@@ -195,9 +220,294 @@ namespace CIR {
                        
                        return null;
                }
+
+               static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+                       
+                       if (target_type == TypeManager.object_type) {
+                               if (expr_type.IsClass)
+                                       return new EmptyCast (expr, target_type);
+                               if (expr_type.IsValueType)
+                                       return new BoxedCast (expr, target_type);
+                       } else if (expr_type.IsSubclassOf (target_type))
+                               return new EmptyCast (expr, target_type);
+                       else 
+                               // FIXME: missing implicit reference conversions:
+                               // 
+                               // from any class-type S to any interface-type T.
+                               // from any interface type S to interface-type T.
+                               // from an array-type S to an array-type of type T
+                               // from an array-type to System.Array
+                               // from any delegate type to System.Delegate
+                               // from any array-type or delegate type into System.ICloneable.
+                               // from the null type to any reference-type.
+                                    
+                               return null;
+
+                       return null;
+               }
+                      
+               // <summary>
+               //   Converts implicitly the resolved expression `expr' into the
+               //   `target_type'.  It returns a new expression that can be used
+               //   in a context that expects a `target_type'. 
+               // </summary>
+               static public Expression ConvertImplicit (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       if (expr_type == target_type){
+                               Console.WriteLine ("Hey, ConvertImplicit was called with no job to do");
+                               return expr;
+                       }
+
+                       //
+                       // Step 1: Perform implicit conversions as found on expr.Type
+                       //
+
+                       //
+                       // Step 2: Built-in conversions.
+                       //
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to short, int, long, float, double.
+                               //
+                               if (target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (target_type == TypeManager.short_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to short, ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type))
+                                       return new EmptyCast (expr, target_type);
+
+                               if (target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to int, long, float, double
+                               // 
+                               if (target_type == TypeManager.int32_type)
+                                       return new EmptyCast (expr, target_type);
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to int, uint, long, ulong, float, double
+                               //
+                               if ((target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type))
+                                       return new EmptyCast (expr, target_type);
+                                       
+                               if (target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to long, float, double
+                               //
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to long, ulong, float, double
+                               //
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R4);
+                       } else if ((expr_type == TypeManager.uint64_type) ||
+                                  (expr_type == TypeManager.int64_type)){
+                               //
+                               // From long to float, double
+                               //
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R4);        
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type))
+                                       return new EmptyCast (expr, target_type);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                       } else
+                               return ImplicitReferenceConversion (expr, target_type);
+
+                       
+
+                       //
+                       //  Could not find an implicit cast.
+                       //
+                       return null;
+               }
+
+               // <summary>
+               //   Performs an explicit conversion of the expression `expr' whose
+               //   type is expr.Type to `target_type'.
+               // </summary>
+               static public Expression ConvertExplicit (Expression expr, Type target_type)
+               {
+                       return expr;
+               }
                
        }
 
+       // <summary>
+       //   This kind of cast is used to encapsulate the child
+       //   whose type is child.Type into an expression that is
+       //   reported to return "return_type".  This is used to encapsulate
+       //   expressions which have compatible types, but need to be dealt
+       //   at higher levels with.
+       //
+       //   For example, a "byte" expression could be encapsulated in one
+       //   of these as an "unsigned int".  The type for the expression
+       //   would be "unsigned int".
+       //
+       // </summary>
+       
+       public class EmptyCast : Expression {
+               protected Expression child;
+
+               public EmptyCast (Expression child, Type return_type)
+               {
+                       ExprClass = child.ExprClass;
+                       type = return_type;
+                       this.child = child;
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       child.Emit (ec);
+               }                       
+       }
+
+       public class BoxedCast : EmptyCast {
+
+               public BoxedCast (Expression expr, Type target_type)
+                       : base (expr, target_type)
+               {
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       ec.ig.Emit (OpCodes.Box, child.Type);
+               }
+       }
+       
+
+       // <summary>
+       //   This kind of cast is used to encapsulate a child expression
+       //   that can be trivially converted to a target type using one or 
+       //   two opcodes.  The opcodes are passed as arguments.
+       // </summary>
+       public class OpcodeCast : EmptyCast {
+               OpCode op, op2;
+               bool second_valid;
+               
+               public OpcodeCast (Expression child, Type return_type, OpCode op)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+                       second_valid = false;
+               }
+
+               public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+                       this.op2 = op2;
+                       second_valid = true;
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       ec.ig.Emit (op);
+
+                       if (second_valid)
+                               ec.ig.Emit (op2);
+               }                       
+               
+       }
+       
        public class Unary : Expression {
                public enum Operator {
                        Plus, Minus, Negate, BitComplement,
@@ -329,9 +639,9 @@ namespace CIR {
        public class Binary : Expression {
                public enum Operator {
                        Multiply, Divide, Modulo,
-                       Add, Substract,
+                       Add, Subtract,
                        ShiftLeft, ShiftRight,
-                       LessThan, GreatherThan, LessOrEqual, GreatherOrEqual, 
+                       LessThan, GreaterThan, LessOrEqual, GreaterOrEqual, 
                        Equal, NotEqual,
                        BitwiseAnd,
                        ExclusiveOr,
@@ -342,7 +652,9 @@ namespace CIR {
 
                Operator oper;
                Expression left, right;
-               
+               MethodBase method;
+               ArrayList  Arguments;
+
                public Binary (Operator oper, Expression left, Expression right)
                {
                        this.oper = oper;
@@ -377,113 +689,559 @@ namespace CIR {
                        }
                }
 
-               public override Expression Resolve (TypeContainer tc)
-               {
-                       // FIXME: implement me
-                       return this;
+
+               // <summary>
+               //   Retruns a stringified representation of the Operator
+               // </summary>
+               string OperName ()
+               {
+                       switch (oper){
+                       case Operator.Multiply:
+                               return "*";
+                       case Operator.Divide:
+                               return "/";
+                       case Operator.Modulo:
+                               return "%";
+                       case Operator.Add:
+                               return "+";
+                       case Operator.Subtract:
+                               return "-";
+                       case Operator.ShiftLeft:
+                               return "<<";
+                       case Operator.ShiftRight:
+                               return ">>";
+                       case Operator.LessThan:
+                               return "<";
+                       case Operator.GreaterThan:
+                               return ">";
+                       case Operator.LessOrEqual:
+                               return "<=";
+                       case Operator.GreaterOrEqual:
+                               return ">=";
+                       case Operator.Equal:
+                               return "==";
+                       case Operator.NotEqual:
+                               return "!=";
+                       case Operator.BitwiseAnd:
+                               return "&";
+                       case Operator.BitwiseOr:
+                               return "|";
+                       case Operator.ExclusiveOr:
+                               return "^";
+                       case Operator.LogicalOr:
+                               return "||";
+                       case Operator.LogicalAnd:
+                               return "&&";
+                       }
+
+                       return oper.ToString ();
                }
 
-               public override void Emit (EmitContext ec)
+               Expression ForceConversion (Expression expr, Type target_type)
                {
-               }
-       }
+                       if (expr.Type == target_type)
+                               return expr;
 
-       public class Conditional : Expression {
-               Expression expr, trueExpr, falseExpr;
+                       return ConvertImplicit (expr, target_type);
+               }
                
-               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
+               //
+               // Note that handling the case l == Decimal || r == Decimal
+               // is taken care of by the Step 1 Operator Overload resolution.
+               //
+               void DoNumericPromotions (TypeContainer tc, Type l, Type r)
                {
-                       this.expr = expr;
-                       this.trueExpr = trueExpr;
-                       this.falseExpr = falseExpr;
-               }
+                       if (l == TypeManager.double_type || r == TypeManager.double_type){
+                               //
+                               // If either operand is of type double, the other operand is
+                               // conveted to type double.
+                               //
+                               if (r != TypeManager.double_type)
+                                       right = ConvertImplicit (right, TypeManager.double_type);
+                               if (l != TypeManager.double_type)
+                                       left = ConvertImplicit (left, TypeManager.double_type);
+                               
+                               type = TypeManager.double_type;
+                       } else if (l == TypeManager.float_type || r == TypeManager.float_type){
+                               //
+                               // if either operand is of type float, th eother operand is
+                               // converd to type float.
+                               //
+                               if (r != TypeManager.double_type)
+                                       right = ConvertImplicit (right, TypeManager.float_type);
+                               if (l != TypeManager.double_type)
+                                       left = ConvertImplicit (left, TypeManager.float_type);
+                               type = TypeManager.float_type;
+                       } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
+                               //
+                               // 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
+                               //
+                               Type other = null;
+                               
+                               if (l == TypeManager.uint64_type)
+                                       other = r;
+                               else if (r == TypeManager.uint64_type)
+                                       other = l;
+
+                               if ((other == TypeManager.sbyte_type) ||
+                                   (other == TypeManager.short_type) ||
+                                   (other == TypeManager.int32_type) ||
+                                   (other == TypeManager.int64_type)){
+                                       string oper = OperName ();
+                                       
+                                       tc.RootContext.Report.Error (34, "Operator `" + OperName ()
+                                                                    + "' is ambiguous on operands of type `"
+                                                                    + TypeManager.CSharpName (l) + "' "
+                                                                    + "and `" + TypeManager.CSharpName (r)
+                                                                    + "'");
+                               }
+                               type = TypeManager.uint64_type;
+                       } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
+                               //
+                               // If either operand is of type long, the other operand is converted
+                               // to type long.
+                               //
+                               if (l != TypeManager.int64_type)
+                                       left = ConvertImplicit (left, TypeManager.int64_type);
+                               if (r != TypeManager.int64_type)
+                                       right = ConvertImplicit (right, TypeManager.int64_type);
 
-               public Expression Expr {
-                       get {
-                               return expr;
+                               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)
+                                       other = r;
+                               else if (r == TypeManager.uint32_type)
+                                       other = l;
+
+                               if ((other == TypeManager.sbyte_type) ||
+                                   (other == TypeManager.short_type) ||
+                                   (other == TypeManager.int32_type)){
+                                       left = ForceConversion (left, TypeManager.int64_type);
+                                       right = ForceConversion (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 (left, TypeManager.uint32_type);
+                                       right = ForceConversion (left, TypeManager.uint32_type);
+                                       type = TypeManager.uint32_type;
+                               } 
+                       } else {
+                               left = ForceConversion (left, TypeManager.int32_type);
+                               right = ForceConversion (right, TypeManager.int32_type);
+                               type = TypeManager.int32_type;
                        }
                }
 
-               public Expression TrueExpr {
-                       get {
-                               return trueExpr;
-                       }
+               void error19 (TypeContainer tc)
+               {
+                       tc.RootContext.Report.Error (
+                               19,
+                               "Operator " + OperName () + " cannot be applied to operands of type `" +
+                               TypeManager.CSharpName (left.Type) + "' and `" +
+                               TypeManager.CSharpName (right.Type) + "'");
+                                                    
                }
+               
+               Expression CheckShiftArguments (TypeContainer tc)
+               {
+                       Expression e;
+                       Type l = left.Type;
+                       Type r = right.Type;
 
-               public Expression FalseExpr {
-                       get {
-                               return falseExpr;
+                       e = ForceConversion (right, TypeManager.int32_type);
+                       if (e == null){
+                               error19 (tc);
+                               return null;
                        }
-               }
+                       right = e;
 
-               public override Expression Resolve (TypeContainer tc)
-               {
-                       // FIXME: Implement;
-                       return this;
-               }
+                       if (((e = ConvertImplicit (left, TypeManager.int32_type)) != null) ||
+                           ((e = ConvertImplicit (left, TypeManager.uint32_type)) != null) ||
+                           ((e = ConvertImplicit (left, TypeManager.int64_type)) != null) ||
+                           ((e = ConvertImplicit (left, TypeManager.uint64_type)) != null)){
+                               left = e;
 
-               public override void Emit (EmitContext ec)
-               {
+                               return this;
+                       }
+                       error19 (tc);
+                       return null;
                }
-       }
-
-       public class SimpleName : Expression {
-               string name;
                
-               public SimpleName (string name)
+               Expression ResolveOperator (TypeContainer tc)
                {
-                       this.name = name;
-               }
+                       Type l = left.Type;
+                       Type r = right.Type;
 
-               public string Name {
-                       get {
-                               return name;
+                       //
+                       // Step 1: Perform Operator Overload location
+                       //
+                       Expression left_expr, right_expr;
+                       
+                       string op = "Operator" + oper;
+
+                       left_expr = MemberLookup (tc.RootContext, l, op, false);
+
+                       if (!(left_expr is MethodGroupExpr)){
+                               // FIXME: Find proper error
+                               tc.RootContext.Report.Error (118, "Did find something that is not a method");
+                               return null;
                        }
-               }
 
-               Expression ResolveSimpleName (TypeContainer tc)
-               {
+                       right_expr = MemberLookup (tc.RootContext, r, op, false);
+
+                       if (!(right_expr is MethodGroupExpr)){
+                               // FIXME: Find proper error
+                               tc.RootContext.Report.Error (118, "Did find something that is not a method");
+                               return null;
+                       }
+
+                       if (left_expr != null || right_expr != null) {
+                               //
+                               // Now we need to form the union of these two sets and
+                               // then call OverloadResolve
+                               // on that.
+                               //
+                               MethodGroupExpr left_set = null, right_set = null;
+                               int length1 = 0, length2 = 0;
+                               
+                               if (left_expr != null) {
+                                       left_set = (MethodGroupExpr) left_expr;
+                                       length1 = left_set.Methods.Length;
+                               }
+
+                               if (right_expr != null) {
+                                       right_set = (MethodGroupExpr) right_expr;
+                                       length2 = right_set.Methods.Length;
+                               }
+                               
+                               MemberInfo [] mi = new MemberInfo [length1 + length2];
+                               if (left_set != null)
+                                       left_set.Methods.CopyTo (mi, 0);
+                               if (right_set != null)
+                                       right_set.Methods.CopyTo (mi, length1);
+                               
+                               MethodGroupExpr union = new MethodGroupExpr (mi);
+                               
+                               Arguments = new ArrayList ();
+                               Arguments.Add (new Argument (left, Argument.AType.Expression));
+                               Arguments.Add (new Argument (right, Argument.AType.Expression));
+                               
+                               method = Invocation.OverloadResolve (union, Arguments);
+                               if (method != null)
+                                       return this;
+
+                       }
+
+                       //
+                       // Step 2: Default operations on CLI native types.
+                       //
+                       
+                       // Only perform numeric promotions on:
+                       // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
+                       //
+                       if (oper == Operator.ShiftLeft || oper == Operator.ShiftRight){
+                               return CheckShiftArguments (tc);
+                       } else if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
+
+                               if (l != TypeManager.bool_type || r != TypeManager.bool_type)
+                                       error19 (tc);
+                       } else
+                               DoNumericPromotions (tc, l, r);
+
+                       if (left == null || right == null)
+                               return null;
+
+                       if (oper == Operator.BitwiseAnd ||
+                           oper == Operator.BitwiseOr ||
+                           oper == Operator.ExclusiveOr){
+                               if (!((l == TypeManager.int32_type) ||
+                                     (l == TypeManager.uint32_type) ||
+                                     (l == TypeManager.int64_type) ||
+                                     (l == TypeManager.uint64_type))){
+                                       error19 (tc);
+                                       return null;
+                               }
+                       }
+
+                       if (oper == Operator.Equal ||
+                           oper == Operator.NotEqual ||
+                           oper == Operator.LessOrEqual ||
+                           oper == Operator.LessThan ||
+                           oper == Operator.GreaterOrEqual ||
+                           oper == Operator.GreaterThan){
+                               type = TypeManager.bool_type;
+                       }
+                       
                        return this;
                }
                
-               //
-               // SimpleName needs to handle a multitude of cases:
-               //
-               // simple_names and qualified_identifiers are placed on
-               // the tree equally.
-               //
                public override Expression Resolve (TypeContainer tc)
                {
-                       if (name.IndexOf (".") != -1)
-                               return ResolveMemberAccess (tc, name);
-                       else
-                               return ResolveSimpleName (tc);
+                       left = left.Resolve (tc);
+                       right = right.Resolve (tc);
+
+                       if (left == null || right == null)
+                               return null;
+
+                       return ResolveOperator (tc);
                }
 
-               public override void Emit (EmitContext ec)
+               public bool IsBranchable ()
                {
+                       if (oper == Operator.Equal ||
+                           oper == Operator.NotEqual ||
+                           oper == Operator.LessThan ||
+                           oper == Operator.GreaterThan ||
+                           oper == Operator.LessOrEqual ||
+                           oper == Operator.GreaterOrEqual){
+                               return true;
+                       } else
+                               return false;
                }
-       }
-       
-       public class LocalVariableReference : Expression {
-               string name;
-               Block block;
-               
-               public LocalVariableReference (Block block, string name)
+
+               // <summary>
+               //   This entry point is used by routines that might want
+               //   to emit a brfalse/brtrue after an expression, and instead
+               //   they could use a more compact notation.
+               //
+               //   Typically the code would generate l.emit/r.emit, followed
+               //   by the comparission and then a brtrue/brfalse.  The comparissions
+               //   are sometimes inneficient (there are not as complete as the branches
+               //   look for the hacks in Emit using double ceqs).
+               //
+               //   So for those cases we provide EmitBranchable that can emit the
+               //   branch with the test
+               // </summary>
+               public void EmitBranchable (EmitContext ec, int target)
                {
-                       this.block = block;
-                       this.name = name;
+                       OpCode opcode;
+                       bool close_target = false;
+                       
+                       left.Emit (ec);
+                       right.Emit (ec);
+                       
+                       switch (oper){
+                       case Operator.Equal:
+                               if (close_target)
+                                       opcode = OpCodes.Beq_S;
+                               else
+                                       opcode = OpCodes.Beq;
+                               break;
+
+                       case Operator.NotEqual:
+                               if (close_target)
+                                       opcode = OpCodes.Bne_Un_S;
+                               else
+                                       opcode = OpCodes.Bne_Un;
+                               break;
+
+                       case Operator.LessThan:
+                               if (close_target)
+                                       opcode = OpCodes.Blt_S;
+                               else
+                                       opcode = OpCodes.Blt;
+                               break;
+
+                       case Operator.GreaterThan:
+                               if (close_target)
+                                       opcode = OpCodes.Bgt_S;
+                               else
+                                       opcode = OpCodes.Bgt;
+                               break;
+
+                       case Operator.LessOrEqual:
+                               if (close_target)
+                                       opcode = OpCodes.Ble_S;
+                               else
+                                       opcode = OpCodes.Ble;
+                               break;
+
+                       case Operator.GreaterOrEqual:
+                               if (close_target)
+                                       opcode = OpCodes.Bge_S;
+                               else
+                                       opcode = OpCodes.Ble;
+                               break;
+
+                       default:
+                               throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
+                                                    + oper.ToString ());
+                       }
+
+                       ec.ig.Emit (opcode, target);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Type l = left.Type;
+                       Type r = right.Type;
+                       OpCode opcode;
+
+                       if (method != null) {
+                               if (method is MethodInfo) {
+                                       Invocation.EmitArguments (ec, Arguments);
+                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
+                                       return;
+                               }
+                       }
+                       
+                       left.Emit (ec);
+                       right.Emit (ec);
+
+                       switch (oper){
+                       case Operator.Multiply:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Mul_Ovf;
+                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
+                                               opcode = OpCodes.Mul_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Mul;
+                               } else
+                                       opcode = OpCodes.Mul;
+
+                               break;
+
+                       case Operator.Divide:
+                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
+                                       opcode = OpCodes.Div_Un;
+                               else
+                                       opcode = OpCodes.Div;
+                               break;
+
+                       case Operator.Modulo:
+                               if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
+                                       opcode = OpCodes.Rem_Un;
+                               else
+                                       opcode = OpCodes.Rem;
+                               break;
+
+                       case Operator.Add:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Add_Ovf;
+                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
+                                               opcode = OpCodes.Add_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Mul;
+                               } else
+                                       opcode = OpCodes.Add;
+                               break;
+
+                       case Operator.Subtract:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Sub_Ovf;
+                                       else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
+                                               opcode = OpCodes.Sub_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Sub;
+                               } else
+                                       opcode = OpCodes.Sub;
+                               break;
+
+                       case Operator.ShiftRight:
+                               opcode = OpCodes.Shr;
+                               break;
+                               
+                       case Operator.ShiftLeft:
+                               opcode = OpCodes.Shl;
+                               break;
+
+                       case Operator.Equal:
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.NotEqual:
+                               ec.ig.Emit (OpCodes.Ceq);
+                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.LessThan:
+                               opcode = OpCodes.Clt;
+                               break;
+
+                       case Operator.GreaterThan:
+                               opcode = OpCodes.Cgt;
+                               break;
+
+                       case Operator.LessOrEqual:
+                               ec.ig.Emit (OpCodes.Cgt);
+                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.GreaterOrEqual:
+                               ec.ig.Emit (OpCodes.Clt);
+                               ec.ig.Emit (OpCodes.Ldc_I4_1);
+                               
+                               opcode = OpCodes.Sub;
+                               break;
+
+                       case Operator.LogicalOr:
+                       case Operator.BitwiseOr:
+                               opcode = OpCodes.Or;
+                               break;
+
+                       case Operator.LogicalAnd:
+                       case Operator.BitwiseAnd:
+                               opcode = OpCodes.And;
+                               break;
+
+                       case Operator.ExclusiveOr:
+                               opcode = OpCodes.Xor;
+                               break;
+
+                       default:
+                               throw new Exception ("This should not happen: Operator = "
+                                                    + oper.ToString ());
+                       }
+
+                       ec.ig.Emit (opcode);
                }
+       }
 
-               public Block Block {
+       public class Conditional : Expression {
+               Expression expr, trueExpr, falseExpr;
+               
+               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
+               {
+                       this.expr = expr;
+                       this.trueExpr = trueExpr;
+                       this.falseExpr = falseExpr;
+               }
+
+               public Expression Expr {
                        get {
-                               return block;
+                               return expr;
                        }
                }
 
-               public string Name {
+               public Expression TrueExpr {
                        get {
-                               return name;
+                               return trueExpr;
+                       }
+               }
+
+               public Expression FalseExpr {
+                       get {
+                               return falseExpr;
                        }
                }
 
@@ -498,13 +1256,11 @@ namespace CIR {
                }
        }
 
-       public class ParameterReference : Expression {
-               Parameters pars;
+       public class SimpleName : Expression {
                string name;
                
-               public ParameterReference (Parameters pars, string name)
+               public SimpleName (string name)
                {
-                       this.pars = pars;
                        this.name = name;
                }
 
@@ -514,14 +1270,174 @@ namespace CIR {
                        }
                }
 
+               //
+               // Checks whether we are trying to access an instance
+               // property, method or field from a static body.
+               //
+               Expression MemberStaticCheck (Report r, Expression e)
+               {
+                       if (e is FieldExpr){
+                               FieldInfo fi = ((FieldExpr) e).FieldInfo;
+                               
+                               if (!fi.IsStatic){
+                                       r.Error (120,
+                                                "An object reference is required " +
+                                                "for the non-static field `"+name+"'");
+                                       return null;
+                               }
+                       } else if (e is MethodGroupExpr){
+                               // FIXME: Pending reorganization of MemberLookup
+                               // Basically at this point we should have the
+                               // best match already selected for us, and
+                               // we should only have to check a *single*
+                               // Method for its static on/off bit.
+                               return e;
+                       } else if (e is PropertyExpr){
+                               if (!((PropertyExpr) e).IsStatic){
+                                       r.Error (120,
+                                                "An object reference is required " +
+                                                "for the non-static property access `"+
+                                                name+"'");
+                                       return null;
+                               }
+                       }
+
+                       return e;
+               }
+               
+               //
+               // 7.5.2: Simple Names. 
+               //
+               // Local Variables and Parameters are handled at
+               // parse time, so they never occur as SimpleNames.
+               //
+               Expression ResolveSimpleName (TypeContainer tc)
+               {
+                       Expression e;
+                       Report r = tc.RootContext.Report;
+
+                       e = MemberLookup (tc.RootContext, tc.TypeBuilder, name, true);
+                       if (e != null){
+                               if (e is TypeExpr)
+                                       return e;
+                               if ((tc.ModFlags & Modifiers.STATIC) != 0)
+                                       return MemberStaticCheck (r, e);
+                               else
+                                       return e;
+                       }
+
+                       //
+                       // Do step 3 of the Simple Name resolution.
+                       //
+                       // FIXME: implement me.
+                       
+                       return this;
+               }
+               
+               //
+               // SimpleName needs to handle a multitude of cases:
+               //
+               // simple_names and qualified_identifiers are placed on
+               // the tree equally.
+               //
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       if (name.IndexOf (".") != -1)
+                               return ResolveMemberAccess (tc, name);
+                       else
+                               return ResolveSimpleName (tc);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+       }
+       
+       public class LocalVariableReference : Expression {
+               public readonly string Name;
+               public readonly Block Block;
+               
+               public LocalVariableReference (Block block, string name)
+               {
+                       Block = block;
+                       Name = name;
+                       eclass = ExprClass.Variable;
+               }
+
+               public VariableInfo VariableInfo {
+                       get {
+                               return Block.GetVariableInfo (Name);
+                       }
+               }
+               
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       VariableInfo vi = Block.GetVariableInfo (Name);
+
+                       type = vi.VariableType;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       VariableInfo vi = VariableInfo;
+                       ILGenerator ig = ec.ig;
+                       int idx = vi.Idx;
+                       
+                       switch (idx){
+                       case 0:
+                               ig.Emit (OpCodes.Ldloc_0);
+                               break;
+                               
+                       case 1:
+                               ig.Emit (OpCodes.Ldloc_1);
+                               break;
+
+                       case 2:
+                               ig.Emit (OpCodes.Ldloc_2);
+                               break;
+
+                       case 3:
+                               ig.Emit (OpCodes.Ldloc_3);
+                               break;
+
+                       default:
+                               if (idx < 255)
+                                       ig.Emit (OpCodes.Ldloc_S, idx);
+                               else
+                                       ig.Emit (OpCodes.Ldloc, idx);
+                               break;
+                       }
+               }
+       }
+
+       public class ParameterReference : Expression {
+               public readonly Parameters Pars;
+               public readonly String Name;
+               public readonly int Idx;
+               
+               public ParameterReference (Parameters pars, int idx, string name)
+               {
+                       Pars = pars;
+                       Idx  = idx;
+                       Name = name;
+               }
+
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
+                       Type [] types = Pars.GetParameterInfo (tc);
+
+                       type = types [Idx];
+                       
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       if (Idx < 255)
+                               ec.ig.Emit (OpCodes.Ldarg_S, Idx);
+                       else
+                               ec.ig.Emit (OpCodes.Ldarg, Idx);
                }
        }
        
@@ -553,6 +1469,7 @@ namespace CIR {
                public bool Resolve (TypeContainer tc)
                {
                        expr = expr.Resolve (tc);
+
                        return expr != null;
                }
 
@@ -568,8 +1485,15 @@ namespace CIR {
        public class Invocation : Expression {
                public readonly ArrayList Arguments;
                Expression expr;
-               MethodInfo method = null;
+               MethodBase method = null;
                
+               static Hashtable method_parameter_cache;
+
+               static Invocation ()
+               {
+                       method_parameter_cache = new Hashtable ();
+               }
+                       
                //
                // arguments is an ArrayList, but we do not want to typecast,
                // as it might be null.
@@ -598,9 +1522,13 @@ namespace CIR {
                ///   -1  represents a type mismatch.
                ///   -2  represents a ref/out mismatch.
                /// </summary>
-               static int Badness (Argument a, ParameterInfo pi)
+               static int Badness (Argument a, Type t)
                {
-                       if (pi.ParameterType == a.Expr.Type)
+                       if (a.Expr.Type == null){
+                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+                       }
+                       
+                       if (t == a.Expr.Type)
                                return 0;
 
                        // FIXME: Implement implicit conversions here.
@@ -608,68 +1536,93 @@ namespace CIR {
                        
                        return -1;
                }
-               
-               public override Expression Resolve (TypeContainer tc)
+
+               // <summary>
+               //   Returns the Parameters (a ParameterData interface) for the
+               //   Method `mb'
+               // </summary>
+               static ParameterData GetParameterData (MethodBase mb)
                {
-                       //
-                       // First, resolve the expression that is used to
-                       // trigger the invocation
-                       //
-                       this.expr = expr.Resolve (tc);
-                       if (this.expr == null)
-                               return null;
+                       object pd = method_parameter_cache [mb];
 
-                       if (!(this.expr is MethodGroupExpr)){
-                               tc.RootContext.Report.Error (118,
-                                      "Denotes an " + this.expr.ExprClass + " while a method was expected");
-                               return null;
-                       }
+                       if (pd != null)
+                               return (ParameterData) pd;
 
-                       //
-                       // Next, evaluate all the expressions in the argument list
-                       //
-                       if (Arguments != null){
-                               for (int i = Arguments.Count; i > 0;){
-                                       --i;
-                                       Argument a = (Argument) Arguments [i];
+                       if (mb is MethodBuilder || mb is ConstructorBuilder){
+                               MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
 
-                                       if (!a.Resolve (tc))
-                                               return null;
-                               }
-                       }
+                               InternalParameters ip = mc.ParameterInfo;
+                               method_parameter_cache [mb] = ip;
 
-                       //
-                       // Find the Applicable Function Members (7.4.2.1)
-                       //
-                       MethodGroupExpr me = (MethodGroupExpr) this.expr;
+                               return (ParameterData) ip;
+                       } else {
+                               ParameterInfo [] pi = mb.GetParameters ();
+                               ReflectionParameters rp = new ReflectionParameters (pi);
+                               method_parameter_cache [mb] = rp;
+
+                               return (ParameterData) rp;
+                       }
+               }
+               
+               // <summary>
+               //   Find the Applicable Function Members (7.4.2.1)
+               //
+               //   me: Method Group expression with the members to select.
+               //       it might contain constructors or methods (or anything
+               //       that maps to a method).
+               //
+               //   Arguments: ArrayList containing resolved Argument objects.
+               //
+               //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
+               //            that is the best match of me on Arguments.
+               //
+               // </summary>
+               public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
+               {
                        ArrayList afm = new ArrayList ();
                        int best_match = 10000;
                        int best_match_idx = -1;
-                       
+                       MethodBase method = null;
+                       int argument_count;
+
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+
                        for (int i = me.Methods.Length; i > 0; ){
                                i--;
-                               ParameterInfo [] pi = me.Methods [i].GetParameters ();
+                               MethodBase mb = me.Methods [i];
+                               ParameterData pd;
+
+                               pd = GetParameterData (mb);
+
+                               // If this is the case, we have a method with no args - presumably
+                               if (pd == null && argument_count == 0)
+                                       return me.Methods [0];
 
                                //
                                // Compute how good this is
                                //
-                               if (pi.Length == Arguments.Count){
+                               if (pd.Count == argument_count){
                                        int badness = 0;
                                        
-                                       for (int j = Arguments.Count; j > 0;){
+                                       for (int j = argument_count; j > 0;){
                                                int x;
                                                j--;
-
+                                               
                                                Argument a = (Argument) Arguments [j];
 
-                                               x = Badness (a, pi [j]);
-
+                                               x = Badness (a, pd.ParameterType (j));
+                                               
                                                if (x < 0){
-                                                       // FIXME: report nice error.
-                                               } else
-                                                       badness += x;
+                                                       badness = best_match;
+                                                       continue;
+                                               }
+                                               
+                                               badness += x;
                                        }
-
+                                       
                                        if (badness < best_match){
                                                best_match = badness;
                                                method = me.Methods [i];
@@ -678,28 +1631,101 @@ namespace CIR {
                                }
                        }
 
+                       if (best_match_idx == -1)
+                               return null;
+                       
+                       return method;
+               }
+
+                       
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       //
+                       // First, resolve the expression that is used to
+                       // trigger the invocation
+                       //
+                       this.expr = expr.Resolve (tc);
+                       if (this.expr == null)
+                               return null;
+
+                       if (!(this.expr is MethodGroupExpr)){
+                               tc.RootContext.Report.Error (118,
+                                      "Denotes a non-method (Detail: ExprClass=" + this.expr.ExprClass+")");
+                               return null;
+                       }
+
+                       //
+                       // Next, evaluate all the expressions in the argument list
+                       //
+                       if (Arguments != null){
+                               for (int i = Arguments.Count; i > 0;){
+                                       --i;
+                                       Argument a = (Argument) Arguments [i];
+
+                                       if (!a.Resolve (tc))
+                                               return null;
+                               }
+                       }
+
+                       method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
+
                        if (method == null){
                                tc.RootContext.Report.Error (-6,
                                "Figure out error: Can not find a good function for this argument list");
                                return null;
                        }
 
-                       Console.WriteLine ("Found a method! " + method);
+                       if (method is MethodInfo)
+                               type = ((MethodInfo)method).ReturnType;
 
                        return this;
                }
 
-               public override void Emit (EmitContext ec)
+               public static void EmitArguments (EmitContext ec, ArrayList Arguments)
                {
-                       int top = Arguments.Count;
+                       int top;
+
+                       if (Arguments != null)
+                               top = Arguments.Count;
+                       else
+                               top = 0;
 
                        for (int i = 0; i < top; i++){
                                Argument a = (Argument) Arguments [i];
 
                                a.Emit (ec);
                        }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       bool is_static = method.IsStatic;
+
+                       if (!is_static){
+                               MethodGroupExpr mg = (MethodGroupExpr) this.expr;
+
+                               if (mg.InstanceExpression == null){
+                                       Console.WriteLine ("Internal compiler error.  Should check in the method groups for static/instance");
+                               }
+
+                               mg.InstanceExpression.Emit (ec);
+                       }
+
+                       if (Arguments != null)
+                               EmitArguments (ec, Arguments);
+
+                       if (method.IsStatic){
+                               if (method is MethodInfo)
+                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               else
+                                       ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                       } else {
+                               if (method is MethodInfo)
+                                       ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                               else
+                                       ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+                       } 
 
-                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
                }
        }
 
@@ -718,6 +1744,7 @@ namespace CIR {
                public readonly ArrayList Indices;
                public readonly ArrayList Initializers;
                
+               MethodBase method = null;
 
                public New (string requested_type, ArrayList arguments)
                {
@@ -737,12 +1764,49 @@ namespace CIR {
                
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
+                       type = tc.LookupType (RequestedType, false);
+
+                       if (type == null)
+                               return null;
+
+                       Expression ml;
+
+                       ml = MemberLookup (tc.RootContext, type, ".ctor", false,
+                                          MemberTypes.Constructor, AllBindingsFlags);
+
+                       if (! (ml is MethodGroupExpr)){
+                               //
+                               // FIXME: Find proper error
+                               //
+                               tc.RootContext.Report.Error (118, "Did find something that is not a method");
+                               return null;
+                       }
+                       
+                       if (Arguments != null){
+                               for (int i = Arguments.Count; i > 0;){
+                                       --i;
+                                       Argument a = (Argument) Arguments [i];
+
+                                       if (!a.Resolve (tc))
+                                               return null;
+                               }
+                       }
+
+                       method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
+
+                       if (method == null){
+                               tc.RootContext.Report.Error (-6,
+                               "New invocation: Can not find a constructor for this argument list");
+                               return null;
+                       }
+
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       Invocation.EmitArguments (ec, Arguments);
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
                }
        }
 
@@ -799,6 +1863,7 @@ namespace CIR {
        public class MemberAccess : Expression {
                public readonly string Identifier;
                Expression expr;
+               Expression member_lookup;
                
                public MemberAccess (Expression expr, string id)
                {
@@ -814,8 +1879,37 @@ namespace CIR {
                
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
-                       return this;
+                       Expression new_expression = expr.Resolve (tc);
+
+                       if (new_expression == null)
+                               return null;
+
+                       Console.WriteLine ("This is what I figured: " + expr.Type + "/" + expr.ExprClass);
+
+                       member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
+
+                       if (member_lookup is MethodGroupExpr){
+                               MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
+
+                               //
+                               // Bind the instance expression to it
+                               //
+                               // FIXME: This is a horrible way of detecting if it is
+                               // an instance expression.  Figure out how to fix this.
+                               //
+                               Console.WriteLine ("FIXME: Horrible way of figuring if something is an isntance");
+
+                               if (expr is LocalVariableReference)
+                                       mg.InstanceExpression = expr;
+                                       
+                               return member_lookup;
+                       } else
+                               //
+                               // FIXME: This should generate the proper node
+                               // ie, for a Property Access, it should like call it
+                               // and stuff.
+
+                               return null;
                }
 
                public override void Emit (EmitContext ec)
@@ -872,18 +1966,34 @@ namespace CIR {
        }
 
        // <summary>
-       //   Fully resolved expression that evaluates to a type
+       //   MethodGroup Expression.
+       //  
+       //   This is a fully resolved expression that evaluates to a type
        // </summary>
        public class MethodGroupExpr : Expression {
-               public readonly MethodInfo [] Methods;
+               public readonly MethodBase [] Methods;
+               Expression instance_expression = null;
                
                public MethodGroupExpr (MemberInfo [] mi)
                {
-                       Methods = new MethodInfo [mi.Length];
+                       Methods = new MethodBase [mi.Length];
                        mi.CopyTo (Methods, 0);
                        eclass = ExprClass.MethodGroup;
                }
 
+               //
+               // `A method group may have associated an instance expression' 
+               // 
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expression;
+                       }
+
+                       set {
+                               instance_expression = value;
+                       }
+               }
+               
                override public Expression Resolve (TypeContainer tc)
                {
                        return this;
@@ -917,4 +2027,182 @@ namespace CIR {
                }
        }
 
+
+       //   Fully resolved expression that evaluates to a Field
+       // </summary>
+       public class FieldExpr : Expression {
+               public readonly FieldInfo FieldInfo;
+
+               public FieldExpr (FieldInfo fi)
+               {
+                       FieldInfo = fi;
+                       eclass = ExprClass.Variable;
+                       type = fi.FieldType;
+               }
+
+               override public Expression Resolve (TypeContainer tc)
+               {
+                       // We are born in resolved state. 
+                       return this;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       // FIXME: Assert that this should not be reached?
+               }
+       }
+       
+       // <summary>
+       //   Fully resolved expression that evaluates to a Property
+       // </summary>
+       public class PropertyExpr : Expression {
+               public readonly PropertyInfo PropertyInfo;
+               public readonly bool IsStatic;
+               
+               public PropertyExpr (PropertyInfo pi)
+               {
+                       PropertyInfo = pi;
+                       eclass = ExprClass.PropertyAccess;
+                       IsStatic = false;
+                               
+                       MethodBase [] acc = pi.GetAccessors ();
+
+                       for (int i = 0; i < acc.Length; i++)
+                               if (acc [i].IsStatic)
+                                       IsStatic = true;
+
+                       type = pi.PropertyType;
+               }
+
+               override public Expression Resolve (TypeContainer tc)
+               {
+                       // We are born in resolved state. 
+                       return this;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       // FIXME: Implement.
+               }
+       }
+
+       // <summary>
+       //   Fully resolved expression that evaluates to a Property
+       // </summary>
+       public class EventExpr : Expression {
+               public readonly EventInfo EventInfo;
+               
+               public EventExpr (EventInfo ei)
+               {
+                       EventInfo = ei;
+                       eclass = ExprClass.EventAccess;
+               }
+
+               override public Expression Resolve (TypeContainer tc)
+               {
+                       // We are born in resolved state. 
+                       return this;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       // FIXME: Implement.
+               }
+       }
+       
+       public class CheckedExpr : Expression {
+
+               public readonly Expression Expr;
+
+               public CheckedExpr (Expression e)
+               {
+                       Expr = e;
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME : Implement !
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+               
+       }
+
+       public class UnCheckedExpr : Expression {
+
+               public readonly Expression Expr;
+
+               public UnCheckedExpr (Expression e)
+               {
+                       Expr = e;
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME : Implement !
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+               
+       }
+       
+       public class ElementAccess : Expression {
+               
+               public readonly ArrayList  Arguments;
+               public readonly Expression Expr;
+               
+               public ElementAccess (Expression e, ArrayList e_list)
+               {
+                       Expr = e;
+                       Arguments = e_list;
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME : Implement
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       // FIXME : Implement !
+               }
+               
+       }
+       
+       public class BaseAccess : Expression {
+
+               public enum BaseAccessType {
+                       Member,
+                       Indexer
+               };
+               
+               public readonly BaseAccessType BAType;
+               public readonly string         Member;
+               public readonly ArrayList      Arguments;
+
+               public BaseAccess (BaseAccessType t, string member, ArrayList args)
+               {
+                       BAType = t;
+                       Member = member;
+                       Arguments = args;
+                       
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME : Implement !
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+       }
 }