2001-09-18 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 9bab36cfc087587cedf37815ea031ed83e0f43c0..45854d2aa2604c3583b75089947bbfca571b1d46 100755 (executable)
@@ -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;
 
@@ -137,7 +125,7 @@ namespace CIR {
                        
                        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: " + 
@@ -156,6 +144,25 @@ namespace CIR {
 
                        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
@@ -647,6 +654,7 @@ namespace CIR {
                Expression left, right;
                MethodBase method;
                ArrayList  Arguments;
+               
 
                public Binary (Operator oper, Expression left, Expression right)
                {
@@ -880,54 +888,66 @@ namespace CIR {
                        //
                        // Step 1: Perform Operator Overload location
                        //
-                       Expression i, j;
+                       Expression left_expr, right_expr;
                        
                        string op = "Operator" + oper;
 
-                       i = MemberLookup (tc.RootContext, l, op, false);
+                       left_expr = MemberLookup (tc.RootContext, l, op, false);
 
-                       if (!(i is MethodGroupExpr)){
+                       if (!(left_expr is MethodGroupExpr)){
                                // FIXME: Find proper error
                                tc.RootContext.Report.Error (118, "Did find something that is not a method");
                                return null;
                        }
-                       
-                       j = MemberLookup (tc.RootContext, r, op, false);
 
-                       if (!(j is MethodGroupExpr)){
+                       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;
                        }
 
-                       // Now we need to form the union of these two sets and then call OverloadResolve
-                       // on that.
-                       MethodGroupExpr left_set = (MethodGroupExpr) i;
-                       MethodGroupExpr right_set = (MethodGroupExpr) j;
-                       
-                       int length1, length2;
-                       length1 = left_set.Methods.Length;
-                       length2 = right_set.Methods.Length;
+                       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;
+                               }
 
-                       MemberInfo [] mi = new MemberInfo [length1 + length2];
-                       left_set.Methods.CopyTo (mi, 0);
-                       right_set.Methods.CopyTo (mi, length1);
-                       
-                       MethodGroupExpr union = new MethodGroupExpr (mi);
+                               if (right_expr != null) {
+                                       right_set = (MethodGroupExpr) right_expr;
+                                       length2 = right_set.Methods.Length;
+                               }
 
-                       Arguments = new ArrayList ();
-                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                       
-                       method = Invocation.OverloadResolve (tc, union, Arguments);
-                       if (method != null)
-                               return this;
+                               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:
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
@@ -1071,11 +1091,29 @@ namespace CIR {
                        OpCode opcode;
 
                        if (method != null) {
-                               if (method is MethodInfo) {
-                                       Invocation.EmitArguments (ec, Arguments);
-                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
-                                       return;
-                               }
+
+                               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);
@@ -1300,6 +1338,13 @@ namespace CIR {
                        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
@@ -1508,9 +1553,9 @@ namespace CIR {
                                throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
                        }
                        
-                       if (t == a.Expr.Type)
+                       if (t == a.Expr.Type) 
                                return 0;
-
+                       
                        // FIXME: Implement implicit conversions here.
                        // FIXME: Implement better conversion here.
                        
@@ -1521,7 +1566,7 @@ 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];
 
@@ -1546,9 +1591,18 @@ 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 MethodBase OverloadResolve (TypeContainer tc, MethodGroupExpr me,
-                                                         ArrayList Arguments)
+               public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
                {
                        ArrayList afm = new ArrayList ();
                        int best_match = 10000;
@@ -1566,7 +1620,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
@@ -1634,7 +1692,7 @@ namespace CIR {
                                }
                        }
 
-                       method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments);
+                       method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
 
                        if (method == null){
                                tc.RootContext.Report.Error (-6,
@@ -1677,20 +1735,22 @@ namespace CIR {
 
                                mg.InstanceExpression.Emit (ec);
                        }
-                       
-                       EmitArguments (ec, Arguments);
 
-                       if (method.IsVirtual){
+                       if (Arguments != null)
+                               EmitArguments (ec, Arguments);
+
+                       if (is_static){
                                if (method is MethodInfo)
-                                       ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
                                else
-                                       ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                                       ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
                        } else {
                                if (method is MethodInfo)
-                                       ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
+                                       ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
                                else
-                                       ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-                       }
+                                       ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+                       } 
+
                }
        }
 
@@ -1736,20 +1796,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)){
                                //
@@ -1769,9 +1817,9 @@ namespace CIR {
                                }
                        }
 
-                       method = Invocation.OverloadResolve (tc, (MethodGroupExpr) ml, Arguments);
+                       method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
 
-                       if (method == null){
+                       if (method == null) {
                                tc.RootContext.Report.Error (-6,
                                "New invocation: Can not find a constructor for this argument list");
                                return null;
@@ -1787,15 +1835,21 @@ namespace CIR {
                }
        }
 
+       //
+       // Represents the `this' construct
+       //
        public class This : Expression {
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
+                       eclass = ExprClass.Variable;
+                       type = tc.TypeBuilder;
+                       
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
                }
        }
 
@@ -1809,12 +1863,18 @@ namespace CIR {
 
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
+                       type = tc.LookupType (QueriedType, false);
+
+                       if (type == null)
+                               return null;
+                       
+                       eclass = ExprClass.Type;
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       // FIXME: Implement.
                }
        }
 
@@ -1874,11 +1934,18 @@ namespace CIR {
                                // 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)
+                               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
                                //
@@ -1886,7 +1953,7 @@ namespace CIR {
                                // ie, for a Property Access, it should like call it
                                // and stuff.
 
-                               return null;
+                               return member_lookup;
                }
 
                public override void Emit (EmitContext ec)
@@ -2009,7 +2076,8 @@ namespace CIR {
        // </summary>
        public class FieldExpr : Expression {
                public readonly FieldInfo FieldInfo;
-
+               public Expression Instance;
+                       
                public FieldExpr (FieldInfo fi)
                {
                        FieldInfo = fi;
@@ -2019,13 +2087,32 @@ namespace CIR {
 
                override public Expression Resolve (TypeContainer tc)
                {
-                       // We are born in resolved state. 
+                       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;
                }
 
                override public void Emit (EmitContext ec)
                {
-                       // FIXME: Assert that this should not be reached?
+                       ILGenerator ig = ec.ig;
+
+                       if (FieldInfo.IsStatic)
+                               ig.Emit (OpCodes.Ldsfld, FieldInfo);
+                       else {
+                               Instance.Emit (ec);
+                               
+                               ig.Emit (OpCodes.Ldfld, FieldInfo);
+                       }
                }
        }
        
@@ -2089,7 +2176,7 @@ namespace CIR {
        
        public class CheckedExpr : Expression {
 
-               public readonly Expression Expr;
+               public Expression Expr;
 
                public CheckedExpr (Expression e)
                {
@@ -2098,19 +2185,32 @@ namespace CIR {
 
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME : Implement !
+                       Expr = Expr.Resolve (tc);
+
+                       if (Expr == null)
+                               return null;
+
+                       eclass = Expr.ExprClass;
+                       type = Expr.Type;
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       bool last_check = ec.CheckState;
+
+                       ec.CheckState = true;
+                       
+                       Expr.Emit (ec);
+
+                       ec.CheckState = last_check;
                }
                
        }
 
        public class UnCheckedExpr : Expression {
 
-               public readonly Expression Expr;
+               public Expression Expr;
 
                public UnCheckedExpr (Expression e)
                {
@@ -2119,12 +2219,25 @@ namespace CIR {
 
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME : Implement !
+                       Expr = Expr.Resolve (tc);
+
+                       if (Expr == null)
+                               return null;
+
+                       eclass = Expr.ExprClass;
+                       type = Expr.Type;
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       bool last_check = ec.CheckState;
+
+                       ec.CheckState = false;
+                       
+                       Expr.Emit (ec);
+
+                       ec.CheckState = last_check;
                }
                
        }