2001-09-17 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 3f309ec4673d1effe6bb5cd06f7822a9c434dfbb..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,42 +111,58 @@ 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;
-                       
+
                        MemberInfo [] mi = rc.TypeManager.FindMembers (t, mt, bf, Type.FilterName, name);
 
                        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
@@ -623,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,
@@ -636,6 +652,8 @@ namespace CIR {
 
                Operator oper;
                Expression left, right;
+               MethodBase method;
+               ArrayList  Arguments;
 
                public Binary (Operator oper, Expression left, Expression right)
                {
@@ -686,7 +704,7 @@ namespace CIR {
                                return "%";
                        case Operator.Add:
                                return "+";
-                       case Operator.Substract:
+                       case Operator.Subtract:
                                return "-";
                        case Operator.ShiftLeft:
                                return "<<";
@@ -694,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 "==";
@@ -869,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:
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
@@ -906,8 +979,8 @@ namespace CIR {
                            oper == Operator.NotEqual ||
                            oper == Operator.LessOrEqual ||
                            oper == Operator.LessThan ||
-                           oper == Operator.GreatherOrEqual ||
-                           oper == Operator.GreatherThan){
+                           oper == Operator.GreaterOrEqual ||
+                           oper == Operator.GreaterThan){
                                type = TypeManager.bool_type;
                        }
                        
@@ -930,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;
@@ -981,7 +1054,7 @@ namespace CIR {
                                        opcode = OpCodes.Blt;
                                break;
 
-                       case Operator.GreatherThan:
+                       case Operator.GreaterThan:
                                if (close_target)
                                        opcode = OpCodes.Bgt_S;
                                else
@@ -995,7 +1068,7 @@ namespace CIR {
                                        opcode = OpCodes.Ble;
                                break;
 
-                       case Operator.GreatherOrEqual:
+                       case Operator.GreaterOrEqual:
                                if (close_target)
                                        opcode = OpCodes.Bge_S;
                                else
@@ -1016,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);
@@ -1060,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;
@@ -1095,7 +1176,7 @@ namespace CIR {
                                opcode = OpCodes.Clt;
                                break;
 
-                       case Operator.GreatherThan:
+                       case Operator.GreaterThan:
                                opcode = OpCodes.Cgt;
                                break;
 
@@ -1106,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);
                                
@@ -1404,9 +1485,14 @@ 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,
@@ -1455,17 +1541,17 @@ namespace CIR {
                //   Returns the Parameters (a ParameterData interface) for the
                //   Method `mb'
                // </summary>
-               static ParameterData GetParameterData (TypeContainer tc, MethodBase mb)
+               static ParameterData GetParameterData (MethodBase mb)
                {
                        object pd = method_parameter_cache [mb];
 
                        if (pd != null)
                                return (ParameterData) pd;
 
-                       if (mb is MethodBuilder){
-                               Method m = TypeContainer.LookupMethodByBuilder ((MethodBuilder) mb);
+                       if (mb is MethodBuilder || mb is ConstructorBuilder){
+                               MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
 
-                               InternalParameters ip = m.GetParameters ();
+                               InternalParameters ip = mc.ParameterInfo;
                                method_parameter_cache [mb] = ip;
 
                                return (ParameterData) ip;
@@ -1480,14 +1566,23 @@ namespace CIR {
                
                // <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 MethodInfo OverloadResolve (TypeContainer tc, 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)
@@ -1500,7 +1595,11 @@ namespace CIR {
                                MethodBase mb = me.Methods [i];
                                ParameterData pd;
 
-                               pd = GetParameterData (tc, mb);
+                               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
@@ -1555,9 +1654,6 @@ namespace CIR {
                                return null;
                        }
 
-                       if (method_parameter_cache == null)
-                               method_parameter_cache = new Hashtable ();
-
                        //
                        // Next, evaluate all the expressions in the argument list
                        //
@@ -1571,7 +1667,7 @@ namespace CIR {
                                }
                        }
 
-                       method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments);
+                       method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
 
                        if (method == null){
                                tc.RootContext.Report.Error (-6,
@@ -1579,7 +1675,9 @@ namespace CIR {
                                return null;
                        }
 
-                       type = method.ReturnType;
+                       if (method is MethodInfo)
+                               type = ((MethodInfo)method).ReturnType;
+
                        return this;
                }
 
@@ -1612,13 +1710,22 @@ namespace CIR {
 
                                mg.InstanceExpression.Emit (ec);
                        }
-                       
-                       EmitArguments (ec, Arguments);
 
-                       if (method.IsVirtual)
-                               ec.ig.Emit (OpCodes.Callvirt, method);
-                       else
-                               ec.ig.Emit (OpCodes.Call, method);
+                       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);
+                       } 
+
                }
        }
 
@@ -1637,7 +1744,7 @@ namespace CIR {
                public readonly ArrayList Indices;
                public readonly ArrayList Initializers;
                
-               MethodInfo method = null;
+               MethodBase method = null;
 
                public New (string requested_type, ArrayList arguments)
                {
@@ -1664,20 +1771,8 @@ namespace CIR {
 
                        Expression ml;
 
-                       MemberTypes mt =
-                               MemberTypes.Constructor;
-                       
-                       BindingFlags bf =
-                               BindingFlags.Public |
-                               BindingFlags.Instance;
-                       
-                       MemberInfo [] mi = tc.RootContext.TypeManager.FindMembers (type, mt, bf, null, null);
-
-                       Console.WriteLine ("Found: " + mi.Length);
-                       for (int i = 0; i < mi.Length; i++)
-                               Console.WriteLine (" " + i + ": " + mi [i]);
-                       
-                       ml = MemberLookup (tc.RootContext, type, ".ctor", false);
+                       ml = MemberLookup (tc.RootContext, type, ".ctor", false,
+                                          MemberTypes.Constructor, AllBindingsFlags);
 
                        if (! (ml is MethodGroupExpr)){
                                //
@@ -1697,11 +1792,11 @@ namespace CIR {
                                }
                        }
 
-                       method = Invocation.OverloadResolve (tc, (MethodGroupExpr) ml, Arguments);
+                       method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
 
                        if (method == null){
                                tc.RootContext.Report.Error (-6,
-                               "Figure out error: Can not find a good function for this argument list");
+                               "New invocation: Can not find a constructor for this argument list");
                                return null;
                        }
 
@@ -1711,7 +1806,7 @@ namespace CIR {
                public override void Emit (EmitContext ec)
                {
                        Invocation.EmitArguments (ec, Arguments);
-                       ec.ig.Emit (OpCodes.Newobj, (MethodInfo) method);
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
                }
        }
 
@@ -1876,12 +1971,12 @@ namespace CIR {
        //   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;
                }
@@ -1970,7 +2065,7 @@ 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)
@@ -2056,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;
@@ -2073,14 +2168,14 @@ namespace CIR {
                        // FIXME : Implement
                        return this;
                }
-
+               
                public override void Emit (EmitContext ec)
                {
                        // FIXME : Implement !
                }
-
+               
        }
-
+       
        public class BaseAccess : Expression {
 
                public enum BaseAccessType {