2001-09-17 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 086f53f8b4a141fa6dc8f53d4c9c952031ac3c42..eb2f6b2c7e4a3cce411b7778ab8a9e73daee8dad 100755 (executable)
@@ -98,7 +98,7 @@ namespace CIR {
                //
                // Return values:
                //     If the return value is an Array, then it is an array of
-               //     MethodInfos
+               //     MethodBases
                //   
                //     If the return value is an MemberInfo, it is anything, but a Method
                //
@@ -111,22 +111,10 @@ namespace CIR {
                //
                // This is so we can catch correctly attempts to invoke instance methods
                // from a static body (scan for error 120 in ResolveSimpleName).
-               // 
-               protected static Expression MemberLookup (RootContext rc, Type t, string name, bool same_type)
-               {
-                       MemberTypes mt =
-                               // MemberTypes.Constructor |
-                               MemberTypes.Event       |
-                               MemberTypes.Field       |
-                               MemberTypes.Method      |
-                               MemberTypes.NestedType  |
-                               MemberTypes.Property;
-                       
-                       BindingFlags bf =
-                               BindingFlags.Public |
-                               BindingFlags.Static |
-                               BindingFlags.Instance;
-                       
+               //
+               public static Expression MemberLookup (RootContext rc, Type t, string name,
+                                                         bool same_type, MemberTypes mt, BindingFlags bf)
+               {
                        if (same_type)
                                bf |= BindingFlags.NonPublic;
 
@@ -135,18 +123,46 @@ namespace CIR {
                        if (mi == null)
                                return null;
                        
-                       if (mi.Length == 1 && !(mi [0] is MethodInfo))
+                       if (mi.Length == 1 && !(mi [0] is MethodBase))
                                return Expression.ExprClassFromMemberInfo (mi [0]);
 
                        for (int i = 0; i < mi.Length; i++)
-                               if (!(mi [i] is MethodInfo)){
+                               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
@@ -454,13 +470,14 @@ namespace CIR {
        // </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;
-                       this.op2 = OpCodes.Nop;
+                       second_valid = false;
                }
 
                public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
@@ -469,6 +486,7 @@ namespace CIR {
                {
                        this.op = op;
                        this.op2 = op2;
+                       second_valid = true;
                }
 
                public override Expression Resolve (TypeContainer tc)
@@ -483,8 +501,8 @@ namespace CIR {
                {
                        base.Emit (ec);
                        ec.ig.Emit (op);
-                       
-                       if (!op2.Equals (OpCodes.Nop))
+
+                       if (second_valid)
                                ec.ig.Emit (op2);
                }                       
                
@@ -621,9 +639,9 @@ namespace CIR {
        public class Binary : Expression {
                public enum Operator {
                        Multiply, Divide, Modulo,
-                       Add, Substract,
+                       Add, Subtract,
                        ShiftLeft, ShiftRight,
-                       LessThan, GreatherThan, LessOrEqual, GreatherOrEqual, 
+                       LessThan, GreaterThan, LessOrEqual, GreaterOrEqual, 
                        Equal, NotEqual,
                        BitwiseAnd,
                        ExclusiveOr,
@@ -634,6 +652,8 @@ namespace CIR {
 
                Operator oper;
                Expression left, right;
+               MethodBase method;
+               ArrayList  Arguments;
 
                public Binary (Operator oper, Expression left, Expression right)
                {
@@ -684,7 +704,7 @@ namespace CIR {
                                return "%";
                        case Operator.Add:
                                return "+";
-                       case Operator.Substract:
+                       case Operator.Subtract:
                                return "-";
                        case Operator.ShiftLeft:
                                return "<<";
@@ -692,11 +712,11 @@ namespace CIR {
                                return ">>";
                        case Operator.LessThan:
                                return "<";
-                       case Operator.GreatherThan:
+                       case Operator.GreaterThan:
                                return ">";
                        case Operator.LessOrEqual:
                                return "<=";
-                       case Operator.GreatherOrEqual:
+                       case Operator.GreaterOrEqual:
                                return ">=";
                        case Operator.Equal:
                                return "==";
@@ -820,6 +840,7 @@ namespace CIR {
                        } else {
                                left = ForceConversion (left, TypeManager.int32_type);
                                right = ForceConversion (right, TypeManager.int32_type);
+                               type = TypeManager.int32_type;
                        }
                }
 
@@ -866,12 +887,67 @@ namespace CIR {
                        //
                        // 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:
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
@@ -884,6 +960,9 @@ namespace CIR {
                        } else
                                DoNumericPromotions (tc, l, r);
 
+                       if (left == null || right == null)
+                               return null;
+
                        if (oper == Operator.BitwiseAnd ||
                            oper == Operator.BitwiseOr ||
                            oper == Operator.ExclusiveOr){
@@ -894,11 +973,17 @@ namespace CIR {
                                        error19 (tc);
                                        return null;
                                }
-                       } else 
-                       
-                       if (left == null || right == null)
-                               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;
                }
                
@@ -909,7 +994,7 @@ namespace CIR {
 
                        if (left == null || right == null)
                                return null;
-                                       
+
                        return ResolveOperator (tc);
                }
 
@@ -918,9 +1003,9 @@ namespace CIR {
                        if (oper == Operator.Equal ||
                            oper == Operator.NotEqual ||
                            oper == Operator.LessThan ||
-                           oper == Operator.GreatherThan ||
+                           oper == Operator.GreaterThan ||
                            oper == Operator.LessOrEqual ||
-                           oper == Operator.GreatherOrEqual){
+                           oper == Operator.GreaterOrEqual){
                                return true;
                        } else
                                return false;
@@ -969,7 +1054,7 @@ namespace CIR {
                                        opcode = OpCodes.Blt;
                                break;
 
-                       case Operator.GreatherThan:
+                       case Operator.GreaterThan:
                                if (close_target)
                                        opcode = OpCodes.Bgt_S;
                                else
@@ -983,7 +1068,7 @@ namespace CIR {
                                        opcode = OpCodes.Ble;
                                break;
 
-                       case Operator.GreatherOrEqual:
+                       case Operator.GreaterOrEqual:
                                if (close_target)
                                        opcode = OpCodes.Bge_S;
                                else
@@ -991,10 +1076,8 @@ namespace CIR {
                                break;
 
                        default:
-                               Console.WriteLine ("EmitBranchable called for non-EmitBranchable operator: "
-                                                  + oper.ToString ());
-                               opcode = OpCodes.Nop;
-                               break;
+                               throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
+                                                    + oper.ToString ());
                        }
 
                        ec.ig.Emit (opcode, target);
@@ -1006,6 +1089,14 @@ namespace CIR {
                        Type l = left.Type;
                        Type r = right.Type;
                        OpCode opcode;
+
+                       if (method != null) {
+                               if (method is MethodInfo) {
+                                       Invocation.EmitArguments (ec, Arguments);
+                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
+                                       return;
+                               }
+                       }
                        
                        left.Emit (ec);
                        right.Emit (ec);
@@ -1050,7 +1141,7 @@ namespace CIR {
                                        opcode = OpCodes.Add;
                                break;
 
-                       case Operator.Substract:
+                       case Operator.Subtract:
                                if (ec.CheckState){
                                        if (l == TypeManager.int32_type || l == TypeManager.int64_type)
                                                opcode = OpCodes.Sub_Ovf;
@@ -1085,7 +1176,7 @@ namespace CIR {
                                opcode = OpCodes.Clt;
                                break;
 
-                       case Operator.GreatherThan:
+                       case Operator.GreaterThan:
                                opcode = OpCodes.Cgt;
                                break;
 
@@ -1096,7 +1187,7 @@ namespace CIR {
                                opcode = OpCodes.Ceq;
                                break;
 
-                       case Operator.GreatherOrEqual:
+                       case Operator.GreaterOrEqual:
                                ec.ig.Emit (OpCodes.Clt);
                                ec.ig.Emit (OpCodes.Ldc_I4_1);
                                
@@ -1118,9 +1209,8 @@ namespace CIR {
                                break;
 
                        default:
-                               Console.WriteLine ("This should not happen: Operator = " + oper.ToString ());
-                               opcode = OpCodes.Nop;
-                               break;
+                               throw new Exception ("This should not happen: Operator = "
+                                                    + oper.ToString ());
                        }
 
                        ec.ig.Emit (opcode);
@@ -1276,18 +1366,48 @@ namespace CIR {
 
                public VariableInfo VariableInfo {
                        get {
-                               return (VariableInfo) Block.GetVariableInfo (Name);
+                               return Block.GetVariableInfo (Name);
                        }
                }
                
                public override Expression Resolve (TypeContainer tc)
                {
+                       VariableInfo vi = Block.GetVariableInfo (Name);
+
+                       type = vi.VariableType;
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
-                       Console.WriteLine ("Internal compiler error, LocalVariableReference should not be emitted");
+                       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;
+                       }
                }
        }
 
@@ -1305,12 +1425,19 @@ namespace CIR {
 
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
+                       Type [] types = Pars.GetParameterInfo (tc);
+
+                       type = types [Idx];
+                       
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       if (Idx < 255)
+                               ec.ig.Emit (OpCodes.Ldarg_S, Idx);
+                       else
+                               ec.ig.Emit (OpCodes.Ldarg, Idx);
                }
        }
        
@@ -1342,6 +1469,7 @@ namespace CIR {
                public bool Resolve (TypeContainer tc)
                {
                        expr = expr.Resolve (tc);
+
                        return expr != null;
                }
 
@@ -1357,8 +1485,15 @@ namespace CIR {
        public class Invocation : Expression {
                public readonly ArrayList Arguments;
                Expression expr;
-               MethodInfo method = null;
+               MethodBase method = null;
                
+               static Hashtable method_parameter_cache;
+
+               static Invocation ()
+               {
+                       method_parameter_cache = new Hashtable ();
+               }
+                       
                //
                // arguments is an ArrayList, but we do not want to typecast,
                // as it might be null.
@@ -1387,9 +1522,13 @@ namespace CIR {
                ///   -1  represents a type mismatch.
                ///   -2  represents a ref/out mismatch.
                /// </summary>
-               static int Badness (Argument a, ParameterInfo pi)
+               static int Badness (Argument a, Type t)
                {
-                       if (pi.ParameterType == a.Expr.Type)
+                       if (a.Expr.Type == null){
+                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+                       }
+                       
+                       if (t == a.Expr.Type)
                                return 0;
 
                        // FIXME: Implement implicit conversions here.
@@ -1398,40 +1537,92 @@ namespace CIR {
                        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>
-               static MethodInfo OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
+               public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
                {
                        ArrayList afm = new ArrayList ();
                        int best_match = 10000;
                        int best_match_idx = -1;
-                       MethodInfo method = null;
-                       
+                       MethodBase method = null;
+                       int argument_count;
+
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+
                        for (int i = me.Methods.Length; i > 0; ){
                                i--;
-                               ParameterInfo [] pi = me.Methods [i].GetParameters ();
+                               MethodBase mb = me.Methods [i];
+                               ParameterData pd;
+
+                               pd = GetParameterData (mb);
+
+                               // If this is the case, we have a method with no args - presumably
+                               if (pd == null && argument_count == 0)
+                                       return me.Methods [0];
 
                                //
                                // Compute how good this is
                                //
-                               if (pi.Length == Arguments.Count){
+                               if (pd.Count == argument_count){
                                        int badness = 0;
                                        
-                                       for (int j = Arguments.Count; j > 0;){
+                                       for (int j = argument_count; j > 0;){
                                                int x;
                                                j--;
-
+                                               
                                                Argument a = (Argument) Arguments [j];
 
-                                               x = Badness (a, pi [j]);
-
+                                               x = Badness (a, pd.ParameterType (j));
+                                               
                                                if (x < 0){
-                                                       // FIXME: report nice error.
-                                               } else
-                                                       badness += x;
+                                                       badness = best_match;
+                                                       continue;
+                                               }
+                                               
+                                               badness += x;
                                        }
-
+                                       
                                        if (badness < best_match){
                                                best_match = badness;
                                                method = me.Methods [i];
@@ -1459,7 +1650,7 @@ namespace CIR {
 
                        if (!(this.expr is MethodGroupExpr)){
                                tc.RootContext.Report.Error (118,
-                                      "Denotes an " + this.expr.ExprClass + " while a method was expected");
+                                      "Denotes a non-method (Detail: ExprClass=" + this.expr.ExprClass+")");
                                return null;
                        }
 
@@ -1484,22 +1675,57 @@ namespace CIR {
                                return null;
                        }
 
-                       Console.WriteLine ("Found a method! " + method);
+                       if (method is MethodInfo)
+                               type = ((MethodInfo)method).ReturnType;
 
                        return this;
                }
 
-               public override void Emit (EmitContext ec)
+               public static void EmitArguments (EmitContext ec, ArrayList Arguments)
                {
-                       int top = Arguments.Count;
+                       int top;
+
+                       if (Arguments != null)
+                               top = Arguments.Count;
+                       else
+                               top = 0;
 
                        for (int i = 0; i < top; i++){
                                Argument a = (Argument) Arguments [i];
 
                                a.Emit (ec);
                        }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       bool is_static = method.IsStatic;
+
+                       if (!is_static){
+                               MethodGroupExpr mg = (MethodGroupExpr) this.expr;
+
+                               if (mg.InstanceExpression == null){
+                                       Console.WriteLine ("Internal compiler error.  Should check in the method groups for static/instance");
+                               }
+
+                               mg.InstanceExpression.Emit (ec);
+                       }
+
+                       if (Arguments != null)
+                               EmitArguments (ec, Arguments);
+
+                       if (method.IsStatic){
+                               if (method is MethodInfo)
+                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               else
+                                       ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                       } else {
+                               if (method is MethodInfo)
+                                       ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                               else
+                                       ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+                       } 
 
-                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
                }
        }
 
@@ -1518,6 +1744,7 @@ namespace CIR {
                public readonly ArrayList Indices;
                public readonly ArrayList Initializers;
                
+               MethodBase method = null;
 
                public New (string requested_type, ArrayList arguments)
                {
@@ -1537,12 +1764,49 @@ namespace CIR {
                
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
+                       type = tc.LookupType (RequestedType, false);
+
+                       if (type == null)
+                               return null;
+
+                       Expression ml;
+
+                       ml = MemberLookup (tc.RootContext, type, ".ctor", false,
+                                          MemberTypes.Constructor, AllBindingsFlags);
+
+                       if (! (ml is MethodGroupExpr)){
+                               //
+                               // FIXME: Find proper error
+                               //
+                               tc.RootContext.Report.Error (118, "Did find something that is not a method");
+                               return null;
+                       }
+                       
+                       if (Arguments != null){
+                               for (int i = Arguments.Count; i > 0;){
+                                       --i;
+                                       Argument a = (Argument) Arguments [i];
+
+                                       if (!a.Resolve (tc))
+                                               return null;
+                               }
+                       }
+
+                       method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
+
+                       if (method == null){
+                               tc.RootContext.Report.Error (-6,
+                               "New invocation: Can not find a constructor for this argument list");
+                               return null;
+                       }
+
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       Invocation.EmitArguments (ec, Arguments);
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
                }
        }
 
@@ -1599,6 +1863,7 @@ namespace CIR {
        public class MemberAccess : Expression {
                public readonly string Identifier;
                Expression expr;
+               Expression member_lookup;
                
                public MemberAccess (Expression expr, string id)
                {
@@ -1614,8 +1879,37 @@ namespace CIR {
                
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
-                       return this;
+                       Expression new_expression = expr.Resolve (tc);
+
+                       if (new_expression == null)
+                               return null;
+
+                       Console.WriteLine ("This is what I figured: " + expr.Type + "/" + expr.ExprClass);
+
+                       member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
+
+                       if (member_lookup is MethodGroupExpr){
+                               MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
+
+                               //
+                               // Bind the instance expression to it
+                               //
+                               // FIXME: This is a horrible way of detecting if it is
+                               // an instance expression.  Figure out how to fix this.
+                               //
+                               Console.WriteLine ("FIXME: Horrible way of figuring if something is an isntance");
+
+                               if (expr is LocalVariableReference)
+                                       mg.InstanceExpression = expr;
+                                       
+                               return member_lookup;
+                       } else
+                               //
+                               // FIXME: This should generate the proper node
+                               // ie, for a Property Access, it should like call it
+                               // and stuff.
+
+                               return null;
                }
 
                public override void Emit (EmitContext ec)
@@ -1672,18 +1966,34 @@ namespace CIR {
        }
 
        // <summary>
-       //   Fully resolved expression that evaluates to a type
+       //   MethodGroup Expression.
+       //  
+       //   This is a fully resolved expression that evaluates to a type
        // </summary>
        public class MethodGroupExpr : Expression {
-               public readonly MethodInfo [] Methods;
+               public readonly MethodBase [] Methods;
+               Expression instance_expression = null;
                
                public MethodGroupExpr (MemberInfo [] mi)
                {
-                       Methods = new MethodInfo [mi.Length];
+                       Methods = new MethodBase [mi.Length];
                        mi.CopyTo (Methods, 0);
                        eclass = ExprClass.MethodGroup;
                }
 
+               //
+               // `A method group may have associated an instance expression' 
+               // 
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expression;
+                       }
+
+                       set {
+                               instance_expression = value;
+                       }
+               }
+               
                override public Expression Resolve (TypeContainer tc)
                {
                        return this;
@@ -1727,6 +2037,7 @@ namespace CIR {
                {
                        FieldInfo = fi;
                        eclass = ExprClass.Variable;
+                       type = fi.FieldType;
                }
 
                override public Expression Resolve (TypeContainer tc)
@@ -1754,11 +2065,13 @@ namespace CIR {
                        eclass = ExprClass.PropertyAccess;
                        IsStatic = false;
                                
-                       MethodInfo [] acc = pi.GetAccessors ();
+                       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)
@@ -1838,12 +2151,12 @@ namespace CIR {
                }
                
        }
-
-               public class ElementAccess : Expression {
-
+       
+       public class ElementAccess : Expression {
+               
                public readonly ArrayList  Arguments;
                public readonly Expression Expr;
-
+               
                public ElementAccess (Expression e, ArrayList e_list)
                {
                        Expr = e;
@@ -1855,14 +2168,14 @@ namespace CIR {
                        // FIXME : Implement
                        return this;
                }
-
+               
                public override void Emit (EmitContext ec)
                {
                        // FIXME : Implement !
                }
-
+               
        }
-
+       
        public class BaseAccess : Expression {
 
                public enum BaseAccessType {