2001-09-18 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 05f15941b079b0846613d658d3c4ef3c037b51eb..713e879928e3646e6cf6b0bc225822f30446311f 100755 (executable)
@@ -10,51 +10,504 @@ namespace CIR {
        using System.Collections;
        using System.Diagnostics;
        using System;
-       
-       public abstract class Expression {
-               string type;
-               bool is_lvalue;
+       using System.Reflection;
+       using System.Reflection.Emit;
+
+       // <remarks>
+       //   The ExprClass class contains the is used to pass the 
+       //   classification of an expression (value, variable, namespace,
+       //   type, method group, property access, event access, indexer access,
+       //   nothing).
+       // </remarks>
+       public enum ExprClass {
+               Invalid,
+               
+               Value, Variable, Namespace, Type,
+               MethodGroup, PropertyAccess,
+               EventAccess, IndexerAccess, Nothing, 
+       }
 
-               public string Type {
+       // <remarks>
+       //   Base class for expressions
+       // </remarks>
+       public abstract class Expression {
+               protected ExprClass eclass;
+               protected Type      type;
+               
+               public Type Type {
                        get {
                                return type;
                        }
+
+                       set {
+                               type = value;
+                       }
                }
 
-               public bool IsLValue {
+               public ExprClass ExprClass {
                        get {
-                               return is_lvalue;
+                               return eclass;
                        }
 
                        set {
-                               is_lvalue = value;
+                               eclass = value;
                        }
                }
 
-               public virtual bool IsLiteral {
-                       get {
-                               return false;
-                       }
-               }
+               public abstract Expression Resolve (TypeContainer tc);
+               public abstract void Emit (EmitContext ec);
                
                // <summary>
                //   Protected constructor.  Only derivate types should
                //   be able to be created
                // </summary>
-               // protected Type (
 
                protected Expression ()
                {
+                       eclass = ExprClass.Invalid;
                        type = null;
                }
+
+               // 
+               // Returns a fully formed expression after a MemberLookup
+               //
+               static Expression ExprClassFromMemberInfo (MemberInfo mi)
+               {
+                       if (mi is EventInfo){
+                               return new EventExpr ((EventInfo) mi);
+                       } else if (mi is FieldInfo){
+                               return new FieldExpr ((FieldInfo) mi);
+                       } else if (mi is PropertyInfo){
+                               return new PropertyExpr ((PropertyInfo) mi);
+                       } else if (mi is Type)
+                               return new TypeExpr ((Type) mi);
+
+                       return null;
+               }
+               
+               //
+               // FIXME: Probably implement a cache for (t,name,current_access_set)?
+               //
+               // FIXME: We need to cope with access permissions here, or this wont
+               // work!
+               //
+               // This code could use some optimizations, but we need to do some
+               // measurements.  For example, we could use a delegate to `flag' when
+               // something can not any longer be a method-group (because it is something
+               // else).
+               //
+               // Return values:
+               //     If the return value is an Array, then it is an array of
+               //     MethodBases
+               //   
+               //     If the return value is an MemberInfo, it is anything, but a Method
+               //
+               //     null on error.
+               //
+               // 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 = 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 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
+               //
+               // This is suboptimal and should be merged with ResolveMemberAccess
+               static Expression ResolvePrimary (TypeContainer tc, string name)
+               {
+                       int dot_pos = name.LastIndexOf (".");
+
+                       if (tc.RootContext.IsNamespace (name))
+                               return new NamespaceExpr (name);
+
+                       if (dot_pos != -1){
+                       } else {
+                               Type t = tc.LookupType (name, false);
+
+                               if (t != null)
+                                       return new TypeExpr (t);
+                       }
+
+                       return null;
+               }
+                       
+               static public Expression ResolveMemberAccess (TypeContainer tc, string name)
+               {
+                       Expression left_e;
+                       int dot_pos = name.LastIndexOf (".");
+                       string left = name.Substring (0, dot_pos);
+                       string right = name.Substring (dot_pos + 1);
+
+                       left_e = ResolvePrimary (tc, left);
+                       if (left_e == null)
+                               return null;
+
+                       switch (left_e.ExprClass){
+                       case ExprClass.Type:
+                               return  MemberLookup (tc.RootContext,
+                                                     left_e.Type, right,
+                                                     left_e.Type == tc.TypeBuilder);
+                               
+                       case ExprClass.Namespace:
+                       case ExprClass.PropertyAccess:
+                       case ExprClass.IndexerAccess:
+                       case ExprClass.Variable:
+                       case ExprClass.Value:
+                       case ExprClass.Nothing:
+                       case ExprClass.EventAccess:
+                       case ExprClass.MethodGroup:
+                       case ExprClass.Invalid:
+                               tc.RootContext.Report.Error (-1000,
+                                                            "Internal compiler error, should have " +
+                                                            "got these handled before");
+                               break;
+                       }
+                       
+                       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;
+               }
                
-               static bool EvaluateType (Expression expr, out string setType)
+       }
+
+       // <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)
                {
-                       setType = null;
-                       return true;
+                       // 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,
@@ -90,10 +543,20 @@ namespace CIR {
                                oper = value;
                        }
                }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME: Implement;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
        }
 
        public class Probe : Expression {
-               string type;
+               string probe_type;
                Expression expr;
                Operator oper;
 
@@ -101,10 +564,10 @@ namespace CIR {
                        Is, As
                }
                
-               public Probe (Operator oper, Expression expr, string type)
+               public Probe (Operator oper, Expression expr, string probe_type)
                {
                        this.oper = oper;
-                       this.type = type;
+                       this.probe_type = probe_type;
                        this.expr = expr;
                }
 
@@ -122,25 +585,34 @@ namespace CIR {
 
                public string ProbeType {
                        get {
-                               return type;
+                               return probe_type;
                        }
                }
-                              
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME: Implement;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
        }
        
        public class Cast : Expression {
-               string type;
+               string target_type;
                Expression expr;
                
-               public Cast (string type, Expression expr)
+               public Cast (string cast_type, Expression expr)
                {
-                       this.type = type;
+                       this.target_type = target_type;
                        this.expr = expr;
                }
 
                public string TargetType {
                        get {
-                               return type;
+                               return target_type;
                        }
                }
 
@@ -152,14 +624,24 @@ namespace CIR {
                                expr = value;
                        }
                }
+               
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME: Implement;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
        }
 
        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,
@@ -170,7 +652,10 @@ namespace CIR {
 
                Operator oper;
                Expression left, right;
+               MethodBase method;
+               ArrayList  Arguments;
                
+
                public Binary (Operator oper, Expression left, Expression right)
                {
                        this.oper = oper;
@@ -204,6 +689,550 @@ namespace CIR {
                                right = value;
                        }
                }
+
+
+               // <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 ();
+               }
+
+               Expression ForceConversion (Expression expr, Type target_type)
+               {
+                       if (expr.Type == target_type)
+                               return expr;
+
+                       return ConvertImplicit (expr, target_type);
+               }
+               
+               //
+               // 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)
+               {
+                       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);
+
+                               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;
+                       }
+               }
+
+               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;
+
+                       e = ForceConversion (right, TypeManager.int32_type);
+                       if (e == null){
+                               error19 (tc);
+                               return null;
+                       }
+                       right = e;
+
+                       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;
+
+                               return this;
+                       }
+                       error19 (tc);
+                       return null;
+               }
+               
+               Expression ResolveOperator (TypeContainer tc)
+               {
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       //
+                       // 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;
+                       }
+
+                       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;
+               }
+               
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       left = left.Resolve (tc);
+                       right = right.Resolve (tc);
+
+                       if (left == null || right == null)
+                               return null;
+
+                       return ResolveOperator (tc);
+               }
+
+               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;
+               }
+
+               // <summary>
+               //   This entry point is used by routines that might want
+               //   to emit a brfalse/brtrue after an expression, and instead
+               //   they could use a more compact notation.
+               //
+               //   Typically the code would generate l.emit/r.emit, followed
+               //   by the comparission and then a brtrue/brfalse.  The comparissions
+               //   are sometimes inneficient (there are not as complete as the branches
+               //   look for the hacks in Emit using double ceqs).
+               //
+               //   So for those cases we provide EmitBranchable that can emit the
+               //   branch with the test
+               // </summary>
+               public void EmitBranchable (EmitContext ec, int target)
+               {
+                       OpCode opcode;
+                       bool close_target = false;
+                       
+                       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) {
+
+                               bool is_static = method.IsStatic;
+
+                               // FIXME : I am just not able to get this right !!
+                               // There's something wrong with this part which causes
+                               // an InvalidProgramException if this code is emitted
+                               
+                               //if (Arguments != null)
+                               //      Invocation.EmitArguments (ec, Arguments);
+                               
+                               //if (is_static){
+                               //      if (method is MethodInfo)
+                               //              ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               //      else
+                               //              ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                               //} else {
+                               //      if (method is MethodInfo)
+                               //              ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                               //      else
+                               //              ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+                               //}
+                               
+                               //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 class Conditional : Expression {
@@ -233,6 +1262,16 @@ namespace CIR {
                                return falseExpr;
                        }
                }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME: Implement;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
        }
 
        public class SimpleName : Expression {
@@ -248,45 +1287,182 @@ namespace CIR {
                                return name;
                        }
                }
-       }
-       
-       public class LocalVariableReference : Expression {
-               string name;
-               Block block;
+
+               //
+               // 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;
+                               else if (e is FieldExpr){
+                                       FieldExpr fe = (FieldExpr) e;
+
+                                       if (!fe.FieldInfo.IsStatic)
+                                               fe.Instance = new This ();
+                               }
+                               
+                               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)
                {
-                       this.block = block;
-                       this.name = name;
+                       Block = block;
+                       Name = name;
+                       eclass = ExprClass.Variable;
                }
 
-               public Block Block {
+               public VariableInfo VariableInfo {
                        get {
-                               return block;
+                               return Block.GetVariableInfo (Name);
                        }
                }
+               
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       VariableInfo vi = Block.GetVariableInfo (Name);
+
+                       type = vi.VariableType;
+                       return this;
+               }
 
-               public string Name {
-                       get {
-                               return name;
+               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 {
-               Parameters pars;
-               string name;
+               public readonly Parameters Pars;
+               public readonly String Name;
+               public readonly int Idx;
                
-               public ParameterReference (Parameters pars, string name)
+               public ParameterReference (Parameters pars, int idx, string name)
                {
-                       this.pars = pars;
-                       this.name = name;
+                       Pars = pars;
+                       Idx  = idx;
+                       Name = name;
                }
 
-               public string Name {
-                       get {
-                               return name;
-                       }
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       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);
                }
        }
        
@@ -300,13 +1476,13 @@ namespace CIR {
                        Out
                };
 
-               AType type;
+               public readonly AType Type;
                Expression expr;
 
                public Argument (Expression expr, AType type)
                {
                        this.expr = expr;
-                       this.type = type;
+                       this.Type = type;
                }
 
                public Expression Expr {
@@ -315,10 +1491,16 @@ namespace CIR {
                        }
                }
 
-               public AType Type {
-                       get {
-                               return type;
-                       }
+               public bool Resolve (TypeContainer tc)
+               {
+                       expr = expr.Resolve (tc);
+
+                       return expr != null;
+               }
+
+               public void Emit (EmitContext ec)
+               {
+                       expr.Emit (ec);
                }
        }
 
@@ -326,9 +1508,17 @@ namespace CIR {
        //   Invocation of methods or delegates.
        // </summary>
        public class Invocation : Expression {
-               ArrayList arguments;
+               public readonly ArrayList Arguments;
                Expression expr;
+               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.
@@ -339,7 +1529,7 @@ namespace CIR {
                public Invocation (Expression expr, ArrayList arguments)
                {
                        this.expr = expr;
-                       this.arguments = arguments;
+                       Arguments = arguments;
                }
 
                public Expression Expr {
@@ -348,77 +1538,374 @@ namespace CIR {
                        }
                }
 
-               public ArrayList Arguments {
-                       get {
-                               return arguments;
+               /// <summary>
+               ///   Computes whether Argument `a' and the ParameterInfo `pi' are
+               ///   compatible, and if so, how good is the match (in terms of
+               ///   "better conversions" (7.4.2.3).
+               ///
+               ///   0   is the best possible match.
+               ///   -1  represents a type mismatch.
+               ///   -2  represents a ref/out mismatch.
+               /// </summary>
+               static int Badness (Argument a, Type t)
+               {
+                       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.
+                       // FIXME: Implement better conversion here.
+                       
+                       return -1;
+               }
+
+               // <summary>
+               //   Returns the Parameters (a ParameterData interface) for the
+               //   Method `mb'
+               // </summary>
+               static ParameterData GetParameterData (MethodBase mb)
+               {
+                       object pd = method_parameter_cache [mb];
+
+                       if (pd != null)
+                               return (ParameterData) pd;
+
+                       if (mb is MethodBuilder || mb is ConstructorBuilder){
+                               MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
+
+                               InternalParameters ip = mc.ParameterInfo;
+                               method_parameter_cache [mb] = ip;
+
+                               return (ParameterData) ip;
+                       } else {
+                               ParameterInfo [] pi = mb.GetParameters ();
+                               ReflectionParameters rp = new ReflectionParameters (pi);
+                               method_parameter_cache [mb] = rp;
+
+                               return (ParameterData) rp;
                        }
                }
+               
+               // <summary>
+               //   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--;
+                               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 (pd.Count == argument_count){
+                                       int badness = 0;
+                                       
+                                       for (int j = argument_count; j > 0;){
+                                               int x;
+                                               j--;
+                                               
+                                               Argument a = (Argument) Arguments [j];
+
+                                               x = Badness (a, pd.ParameterType (j));
+                                               
+                                               if (x < 0){
+                                                       badness = best_match;
+                                                       continue;
+                                               }
+                                               
+                                               badness += x;
+                                       }
+                                       
+                                       if (badness < best_match){
+                                               best_match = badness;
+                                               method = me.Methods [i];
+                                               best_match_idx = i;
+                                       }
+                               }
+                       }
+
+                       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;
+                       }
+
+                       if (method is MethodInfo)
+                               type = ((MethodInfo)method).ReturnType;
+
+                       return this;
+               }
+
+               public static void EmitArguments (EmitContext ec, ArrayList Arguments)
+               {
+                       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 (is_static){
+                               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);
+                       } 
+
+               }
        }
 
        public class New : Expression {
-               ArrayList arguments;
-               string requested_type;
+
+               public enum NType {
+                       Object,
+                       Array
+               };
+
+               public readonly NType     NewType;
+               public readonly ArrayList Arguments;
+               public readonly string    RequestedType;
+               // These are for the case when we have an array
+               public readonly string    Rank;
+               public readonly ArrayList Indices;
+               public readonly ArrayList Initializers;
+               
+               MethodBase method = null;
 
                public New (string requested_type, ArrayList arguments)
                {
-                       this.requested_type = requested_type;
-                       this.arguments = arguments;
+                       RequestedType = requested_type;
+                       Arguments = arguments;
+                       NewType = NType.Object;
                }
-               
-               public ArrayList Arguments{
-                       get {
-                               return arguments;
-                       }
+
+               public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
+               {
+                       RequestedType = requested_type;
+                       Indices       = exprs;
+                       Rank          = rank;
+                       Initializers  = initializers;
+                       NewType       = NType.Array;
                }
                
-               public string RequestedType {
-                       get {
-                               return requested_type;
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       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);
                }
        }
 
+       //
+       // Represents the `this' construct
+       //
        public class This : Expression {
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       eclass = ExprClass.Variable;
+                       type = tc.TypeBuilder;
+                       
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+               }
        }
 
        public class TypeOf : Expression {
-               string queried_type;
+               public readonly string QueriedType;
                
                public TypeOf (string queried_type)
                {
-                       this.queried_type = queried_type;
+                       QueriedType = queried_type;
                }
 
-               public string QueriedType {
-                       get {
-                               return queried_type;
-                       }
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       type = tc.LookupType (QueriedType, false);
+
+                       if (type == null)
+                               return null;
+                       
+                       eclass = ExprClass.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // FIXME: Implement.
                }
        }
 
        public class SizeOf : Expression {
-               string queried_type;
+               public readonly string QueriedType;
                
                public SizeOf (string queried_type)
                {
-                       this.queried_type = queried_type;
+                       this.QueriedType = queried_type;
                }
 
-               public string QueriedType {
-                       get {
-                               return queried_type;
-                       }
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME: Implement;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
                }
        }
 
        public class MemberAccess : Expression {
+               public readonly string Identifier;
                Expression expr;
-               string id;
+               Expression member_lookup;
                
                public MemberAccess (Expression expr, string id)
                {
                        this.expr = expr;
-                       this.id = id;
+                       Identifier = id;
                }
 
                public Expression Expr {
@@ -426,40 +1913,360 @@ namespace CIR {
                                return expr;
                        }
                }
+               
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       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.
+                               //
+
+                               if (expr is LocalVariableReference ||
+                                   expr is ParameterReference ||
+                                   expr is FieldExpr)
+                                       mg.InstanceExpression = expr;
+                                       
+                               return member_lookup;
+                       } else if (member_lookup is FieldExpr){
+                               FieldExpr fe = (FieldExpr) member_lookup;
+
+                               fe.Instance = 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 member_lookup;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+
+       }
+
+       // <summary>
+       //   Nodes of type Namespace are created during the semantic
+       //   analysis to resolve member_access/qualified_identifier/simple_name
+       //   accesses.
+       //
+       //   They are born `resolved'. 
+       // </summary>
+       public class NamespaceExpr : Expression {
+               public readonly string Name;
+               
+               public NamespaceExpr (string name)
+               {
+                       Name = name;
+                       eclass = ExprClass.Namespace;
+               }
+
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+       }
+
+       // <summary>
+       //   Fully resolved expression that evaluates to a type
+       // </summary>
+       public class TypeExpr : Expression {
+               public TypeExpr (Type t)
+               {
+                       Type = t;
+                       eclass = ExprClass.Type;
+               }
+
+               override public Expression Resolve (TypeContainer tc)
+               {
+                       return this;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       
+               }
+       }
+
+       // <summary>
+       //   MethodGroup Expression.
+       //  
+       //   This is a fully resolved expression that evaluates to a type
+       // </summary>
+       public class MethodGroupExpr : Expression {
+               public readonly MethodBase [] Methods;
+               Expression instance_expression = null;
+               
+               public MethodGroupExpr (MemberInfo [] mi)
+               {
+                       Methods = new MethodBase [mi.Length];
+                       mi.CopyTo (Methods, 0);
+                       eclass = ExprClass.MethodGroup;
+               }
 
-               public string Identifier {
+               //
+               // `A method group may have associated an instance expression' 
+               // 
+               public Expression InstanceExpression {
                        get {
-                               return id;
+                               return instance_expression;
+                       }
+
+                       set {
+                               instance_expression = value;
                        }
                }
-       }
+               
+               override public Expression Resolve (TypeContainer tc)
+               {
+                       return this;
+               }
 
+               override public void Emit (EmitContext ec)
+               {
+                       
+               }
+       }
+       
        public class BuiltinTypeAccess : Expression {
-               string access_base;
-               string method;
+               public readonly string AccessBase;
+               public readonly string Method;
                
                public BuiltinTypeAccess (string type, string method)
                {
                        System.Console.WriteLine ("DUDE! This type should be fully resolved!");
-                       this.access_base = access_base;
-                       this.method = method;
+                       AccessBase = type;
+                       Method = method;
                }
 
-               public string AccessBase {
-                       get {
-                               return access_base;
+               public override Expression Resolve (TypeContainer tc)
+               {
+                       // FIXME: Implement;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+       }
+
+
+       //   Fully resolved expression that evaluates to a Field
+       // </summary>
+       public class FieldExpr : Expression {
+               public readonly FieldInfo FieldInfo;
+               public Expression Instance;
+                       
+               public FieldExpr (FieldInfo fi)
+               {
+                       FieldInfo = fi;
+                       eclass = ExprClass.Variable;
+                       type = fi.FieldType;
+               }
+
+               override public Expression Resolve (TypeContainer tc)
+               {
+                       if (!FieldInfo.IsStatic){
+                               if (Instance == null){
+                                       throw new Exception ("non-static FieldExpr without instance var\n" +
+                                                            "You have to assign the Instance variable\n" +
+                                                            "Of the FieldExpr to set this\n");
+                               }
+
+                               Instance = Instance.Resolve (tc);
+                               if (Instance == null)
+                                       return null;
+                               
                        }
+                       return this;
                }
 
-               public string Method {
-                       get {
-                               return method;
+               override public void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       if (FieldInfo.IsStatic)
+                               ig.Emit (OpCodes.Ldsfld, FieldInfo);
+                       else {
+                               Instance.Emit (ec);
+                               
+                               ig.Emit (OpCodes.Ldfld, FieldInfo);
                        }
                }
        }
-}
+       
+       // <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)
+               {
+               }
+       }
+}