2002-09-16 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / ecore.cs
index 4b2c3a9c01120a132d5bcc78a40d3094e4125c1e..26d88130ad84bd63e665004339c1e700409e43c4 100755 (executable)
@@ -56,6 +56,9 @@ namespace Mono.CSharp {
                // partially resolved (namespace-qualified names for example).
                SimpleName              = 8,
 
+               // Mask of all the expression class flags.
+               MaskExprClass           = 15,
+
                // Disable control flow analysis while resolving the expression.
                // This is used when resolving the instance expression of a field expression.
                DisableFlowAnalysis     = 16
@@ -152,6 +155,13 @@ namespace Mono.CSharp {
                        get;
                }
 
+               /// <summary>
+               ///   The type which declares this member.
+               /// </summary>
+               Type DeclaringType {
+                       get;
+               }
+
                /// <summary>
                ///   The instance expression associated with this member, if it's a
                ///   non-static member.
@@ -161,6 +171,17 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   Expression which resolves to a type.
+       /// </summary>
+       public interface ITypeExpression
+       {
+               /// <summary>
+               ///   Resolve the expression, but only lookup types.
+               /// </summary>
+               Expression DoResolveType (EmitContext ec);
+       }
+
        /// <remarks>
        ///   Base class for expressions
        /// </remarks>
@@ -268,12 +289,21 @@ namespace Mono.CSharp {
                /// </remarks>
                public Expression Resolve (EmitContext ec, ResolveFlags flags)
                {
-                       Expression e;
+                       // Are we doing a types-only search ?
+                       if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) {
+                               ITypeExpression type_expr = this as ITypeExpression;
+
+                               if (type_expr == null)
+                                       return null;
+
+                               return type_expr.DoResolveType (ec);
+                       }
 
                        bool old_do_flow_analysis = ec.DoFlowAnalysis;
                        if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
                                ec.DoFlowAnalysis = false;
 
+                       Expression e;
                        if (this is SimpleName)
                                e = ((SimpleName) this).DoResolveAllowStatic (ec);
                        else 
@@ -288,10 +318,16 @@ namespace Mono.CSharp {
                                SimpleName s = (SimpleName) e;
 
                                if ((flags & ResolveFlags.SimpleName) == 0) {
-                                       Report.Error (
-                                               103, loc,
-                                               "The name `" + s.Name + "' could not be found in `" +
-                                               ec.DeclSpace.Name + "'");
+
+                                       object lookup = TypeManager.MemberLookup (
+                                               ec.ContainerType, ec.ContainerType, AllMemberTypes,
+                                               AllBindingFlags | BindingFlags.NonPublic, s.Name);
+                                       if (lookup != null)
+                                               Error (122, "`" + s.Name + "' " +
+                                                      "is inaccessible because of its protection level");
+                                       else
+                                               Error (103, "The name `" + s.Name + "' could not be " +
+                                                      "found in `" + ec.DeclSpace.Name + "'");
                                        return null;
                                }
 
@@ -518,6 +554,15 @@ namespace Mono.CSharp {
                        return MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc);
                }
 
+               //
+               // Lookup type `t' for code in class `invocation_type'.  Note that it's important
+               // to set `invocation_type' correctly since this method also checks whether the
+               // invoking class is allowed to access the member in class `t'.  When you want to
+               // explicitly do a lookup in the base class, you must set both `t' and `invocation_type'
+               // to the base class (although a derived class can access protected members of its base
+               // class it cannot do so through an instance of the base class (error CS1540)).
+               // 
+
                public static Expression MemberLookup (EmitContext ec, Type invocation_type, Type t,
                                                       string name, MemberTypes mt, BindingFlags bf,
                                                       Location loc)
@@ -753,19 +798,8 @@ namespace Mono.CSharp {
                                        return new ULongConstant ((ulong) v);
                        }
 
-                       //
-                       // If we have an enumeration, extract the underlying type,
-                       // use this during the comparission, but wrap around the original
-                       // target_type
-                       //
-                       Type real_target_type = target_type;
+                       Type real_target_type = target_type;
 
-                       if (TypeManager.IsEnumType (real_target_type))
-                               real_target_type = TypeManager.EnumToUnderlying (real_target_type);
-
-                       if (expr_type == real_target_type)
-                               return new EmptyCast (expr, target_type);
-                       
                        if (expr_type == TypeManager.sbyte_type){
                                //
                                // From sbyte to short, int, long, float, double.
@@ -1009,7 +1043,7 @@ namespace Mono.CSharp {
 
                        return false;
                }
-               
+
                /// <summary>
                ///  Determines if a standard implicit conversion exists from
                ///  expr_type to target_type
@@ -1017,6 +1051,9 @@ namespace Mono.CSharp {
                public static bool StandardConversionExists (Expression expr, Type target_type)
                {
                        Type expr_type = expr.Type;
+
+                       if (expr_type == TypeManager.void_type)
+                               return false;
                        
                        if (expr_type == target_type)
                                return true;
@@ -1179,6 +1216,7 @@ namespace Mono.CSharp {
                                if (i.Value == 0)
                                        return true;
                        }
+
                        return false;
                }
 
@@ -1258,7 +1296,7 @@ namespace Mono.CSharp {
                ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
                ///   for explicit and implicit conversion operators.
                /// </summary>
-               static public Type FindMostSpecificSource (MethodGroupExpr me, Type source_type,
+               static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source,
                                                           bool apply_explicit_conv_rules,
                                                           Location loc)
                {
@@ -1266,10 +1304,11 @@ namespace Mono.CSharp {
                        
                        if (priv_fms_expr == null)
                                priv_fms_expr = new EmptyExpression ();
-                       
+
                        //
                        // If any operator converts from S then Sx = S
                        //
+                       Type source_type = source.Type;
                        foreach (MethodBase mb in me.Methods){
                                ParameterData pd = Invocation.GetParameterData (mb);
                                Type param_type = pd.ParameterType (0);
@@ -1290,16 +1329,14 @@ namespace Mono.CSharp {
                                        if (StandardConversionExists (priv_fms_expr, source_type))
                                                src_types_set.Add (param_type);
                                        else {
-                                               priv_fms_expr.SetType (source_type);
-                                               if (StandardConversionExists (priv_fms_expr, param_type))
+                                               if (StandardConversionExists (source, param_type))
                                                        src_types_set.Add (param_type);
                                        }
                                } else {
                                        //
                                        // Only if S is encompassed by param_type
                                        //
-                                       priv_fms_expr.SetType (source_type);
-                                       if (StandardConversionExists (priv_fms_expr, param_type))
+                                       if (StandardConversionExists (source, param_type))
                                                src_types_set.Add (param_type);
                                }
                        }
@@ -1311,9 +1348,7 @@ namespace Mono.CSharp {
                                ArrayList candidate_set = new ArrayList ();
 
                                foreach (Type param_type in src_types_set){
-                                       priv_fms_expr.SetType (source_type);
-                                       
-                                       if (StandardConversionExists (priv_fms_expr, param_type))
+                                       if (StandardConversionExists (source, param_type))
                                                candidate_set.Add (param_type);
                                }
 
@@ -1406,8 +1441,10 @@ namespace Mono.CSharp {
                        //
                        if (apply_explicit_conv_rules)
                                return FindMostEncompassedType (tgt_types_set);
-                       else
+                       else {
+                               Console.WriteLine ("Here with: " + tgt_types_set.Count);
                                return FindMostEncompassingType (tgt_types_set);
+                       }
                }
                
                /// <summary>
@@ -1528,14 +1565,14 @@ namespace Mono.CSharp {
                        }
 #endif
                        
-                       most_specific_source = FindMostSpecificSource (union, source_type, look_for_explicit, loc);
+                       most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
                        if (most_specific_source == null)
                                return null;
 
                        most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc);
                        if (most_specific_target == null) 
                                return null;
-                       
+
                        int count = 0;
 
                        foreach (MethodBase mb in union.Methods){
@@ -1752,7 +1789,7 @@ namespace Mono.CSharp {
 
                        //
                        // If we have an enumeration, extract the underlying type,
-                       // use this during the comparission, but wrap around the original
+                       // use this during the comparison, but wrap around the original
                        // target_type
                        //
                        Type real_target_type = target_type;
@@ -1760,6 +1797,9 @@ namespace Mono.CSharp {
                        if (TypeManager.IsEnumType (real_target_type))
                                real_target_type = TypeManager.EnumToUnderlying (real_target_type);
 
+                       if (StandardConversionExists (expr, real_target_type))
+                               return new EmptyCast (expr, target_type);
+                       
                        if (expr_type == TypeManager.sbyte_type){
                                //
                                // From sbyte to byte, ushort, uint, ulong, char
@@ -3329,7 +3369,7 @@ namespace Mono.CSharp {
        ///   The downside of this is that we might be hitting `LookupType' too many
        ///   times with this scheme.
        /// </remarks>
-       public class SimpleName : Expression {
+       public class SimpleName : Expression, ITypeExpression {
                public readonly string Name;
                
                public SimpleName (string name, Location l)
@@ -3386,6 +3426,47 @@ namespace Mono.CSharp {
                        return SimpleNameResolve (ec, null, true);
                }
 
+               public Expression DoResolveType (EmitContext ec)
+               {
+                       //
+                       // Stage 3: Lookup symbol in the various namespaces. 
+                       //
+                       DeclSpace ds = ec.DeclSpace;
+                       Type t;
+                       string alias_value;
+
+                       if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
+                               return new TypeExpr (t, loc);
+                               
+                       //
+                       // Stage 2 part b: Lookup up if we are an alias to a type
+                       // or a namespace.
+                       //
+                       // Since we are cheating: we only do the Alias lookup for
+                       // namespaces if the name does not include any dots in it
+                       //
+                               
+                       alias_value = ec.DeclSpace.LookupAlias (Name);
+                               
+                       if (Name.IndexOf ('.') == -1 && alias_value != null) {
+                               if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
+                                       return new TypeExpr (t, loc);
+                                       
+                               // we have alias value, but it isn't Type, so try if it's namespace
+                               return new SimpleName (alias_value, loc);
+                       }
+                               
+                       if (ec.ResolvingTypeTree){
+                               Type dt = ec.DeclSpace.FindType (Name);
+                               if (dt != null)
+                                       return new TypeExpr (dt, loc);
+                       }
+
+                       // No match, maybe our parent can compose us
+                       // into something meaningful.
+                       return this;
+               }
+
                /// <remarks>
                ///   7.5.2: Simple Names. 
                ///
@@ -3410,120 +3491,73 @@ namespace Mono.CSharp {
                        //
                        // Stage 1: Performed by the parser (binding to locals or parameters).
                        //
-                       if (!ec.OnlyLookupTypes){
-                               Block current_block = ec.CurrentBlock;
-                               if (current_block != null && current_block.IsVariableDefined (Name)){
-                                       LocalVariableReference var;
-                                       
-                                       var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+                       Block current_block = ec.CurrentBlock;
+                       if (current_block != null && current_block.IsVariableDefined (Name)){
+                               LocalVariableReference var;
 
-                                       if (right_side != null)
-                                               return var.ResolveLValue (ec, right_side);
-                                       else
-                                               return var.Resolve (ec);
-                               }
+                               var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+
+                               if (right_side != null)
+                                       return var.ResolveLValue (ec, right_side);
+                               else
+                                       return var.Resolve (ec);
+                       }
 
-                               if (current_block != null){
-                                       int idx = -1;
-                                       Parameter par = null;
-                                       Parameters pars = current_block.Parameters;
-                                       if (pars != null)
-                                               par = pars.GetParameterByName (Name, out idx);
+                       if (current_block != null){
+                               int idx = -1;
+                               Parameter par = null;
+                               Parameters pars = current_block.Parameters;
+                               if (pars != null)
+                                       par = pars.GetParameterByName (Name, out idx);
 
-                                       if (par != null) {
-                                               ParameterReference param;
+                               if (par != null) {
+                                       ParameterReference param;
                                        
-                                               param = new ParameterReference (pars, idx, Name, loc);
+                                       param = new ParameterReference (pars, idx, Name, loc);
 
-                                               if (right_side != null)
-                                                       return param.ResolveLValue (ec, right_side);
-                                               else
-                                                       return param.Resolve (ec);
-                                       }
+                                       if (right_side != null)
+                                               return param.ResolveLValue (ec, right_side);
+                                       else
+                                               return param.Resolve (ec);
                                }
+                       }
 
-                               //
-                               // Stage 2: Lookup members 
-                               //
-
-                               //
-                               // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
-                               // Hence we have two different cases
-                               //
-
-                               DeclSpace lookup_ds = ec.DeclSpace;
-                               do {
-                                       if (lookup_ds.TypeBuilder == null)
-                                               break;
+                       //
+                       // Stage 2: Lookup members 
+                       //
 
-                                       e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
-                                       if (e != null)
-                                               break;
+                       //
+                       // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
+                       // Hence we have two different cases
+                       //
 
-                                       //
-                                       // Classes/structs keep looking, enums break
-                                       //
-                                       if (lookup_ds is TypeContainer)
-                                               lookup_ds = ((TypeContainer) lookup_ds).Parent;
-                                       else
-                                               break;
-                               } while (lookup_ds != null);
-                               
-                               if (e == null && ec.ContainerType != null)
-                                       e = MemberLookup (ec, ec.ContainerType, Name, loc);
-                       }
+                       DeclSpace lookup_ds = ec.DeclSpace;
+                       do {
+                               if (lookup_ds.TypeBuilder == null)
+                                       break;
 
-                       // Continuation of stage 2
-                       if (e == null){
-                               //
-                               // Stage 3: Lookup symbol in the various namespaces. 
-                               //
-                               DeclSpace ds = ec.DeclSpace;
-                               Type t;
-                               string alias_value;
+                               e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
+                               if (e != null)
+                                       break;
 
-                               if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
-                                       return new TypeExpr (t, loc);
-                               
                                //
-                               // Stage 2 part b: Lookup up if we are an alias to a type
-                               // or a namespace.
+                               // Classes/structs keep looking, enums break
                                //
-                               // Since we are cheating: we only do the Alias lookup for
-                               // namespaces if the name does not include any dots in it
-                               //
-                               
-                               alias_value = ec.DeclSpace.LookupAlias (Name);
-                               
-                               if (Name.IndexOf ('.') == -1 && alias_value != null) {
-                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc))
-                                           != null)
-                                               return new TypeExpr (t, loc);
-                                       
-                               // we have alias value, but it isn't Type, so try if it's namespace
-                                       return new SimpleName (alias_value, loc);
-                               }
-                               
-                               if (ec.ResolvingTypeTree){
-                                       Type dt = ec.DeclSpace.FindType (Name);
-                                       if (dt != null)
-                                               return new TypeExpr (dt, loc);
-                               }
+                               if (lookup_ds is TypeContainer)
+                                       lookup_ds = ((TypeContainer) lookup_ds).Parent;
+                               else
+                                       break;
+                       } while (lookup_ds != null);
                                
-                               // No match, maybe our parent can compose us
-                               // into something meaningful.
-                               return this;
-                       }
+                       if (e == null && ec.ContainerType != null)
+                               e = MemberLookup (ec, ec.ContainerType, Name, loc);
+
+                       if (e == null)
+                               return DoResolveType (ec);
 
-                       //
-                       // Stage 2 continues here. 
-                       // 
                        if (e is TypeExpr)
                                return e;
 
-                       if (ec.OnlyLookupTypes)
-                               return null;
-
                        if (e is IMemberExpr) {
                                e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
                                if (e == null)
@@ -3538,6 +3572,14 @@ namespace Mono.CSharp {
                                if (!me.IsStatic && (me.InstanceExpression == null))
                                        return e;
 
+                               if (!me.IsStatic &&
+                                   TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) {
+                                       Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
+                                              "outer type `" + me.DeclaringType + "' via nested type `" +
+                                              me.InstanceExpression.Type + "'");
+                                       return null;
+                               }
+
                                if (right_side != null)
                                        e = e.DoResolveLValue (ec, right_side);
                                else
@@ -3576,7 +3618,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved expression that evaluates to a type
        /// </summary>
-       public class TypeExpr : Expression {
+       public class TypeExpr : Expression, ITypeExpression {
                public TypeExpr (Type t, Location l)
                {
                        Type = t;
@@ -3584,6 +3626,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public virtual Expression DoResolveType (EmitContext ec)
+               {
+                       return this;
+               }
+
                override public Expression DoResolve (EmitContext ec)
                {
                        return this;
@@ -3593,31 +3640,41 @@ namespace Mono.CSharp {
                {
                        throw new Exception ("Should never be called");
                }
+
+               public override string ToString ()
+               {
+                       return Type.ToString ();
+               }
        }
 
        /// <summary>
        ///   Used to create types from a fully qualified name.  These are just used
-       ///   by the parser to setup the core types.  A TypeExpression is always
+       ///   by the parser to setup the core types.  A TypeLookupExpression is always
        ///   classified as a type.
        /// </summary>
-       public class TypeExpression : TypeExpr {
+       public class TypeLookupExpression : TypeExpr {
                string name;
                
-               public TypeExpression (string name) : base (null, Location.Null)
+               public TypeLookupExpression (string name) : base (null, Location.Null)
                {
                        this.name = name;
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               public override Expression DoResolveType (EmitContext ec)
                {
                        if (type == null)
                                type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
                        return this;
                }
 
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolveType (ec);
+               }
+
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Should never be called");                 
+                       throw new Exception ("Should never be called");
                }
 
                public override string ToString ()
@@ -3634,6 +3691,7 @@ namespace Mono.CSharp {
        public class MethodGroupExpr : Expression, IMemberExpr {
                public MethodBase [] Methods;
                Expression instance_expression = null;
+               bool is_explicit_impl = false;
                
                public MethodGroupExpr (MemberInfo [] mi, Location l)
                {
@@ -3663,6 +3721,12 @@ namespace Mono.CSharp {
                        eclass = ExprClass.MethodGroup;
                        type = TypeManager.object_type;
                }
+
+               public Type DeclaringType {
+                       get {
+                               return Methods [0].DeclaringType;
+                       }
+               }
                
                //
                // `A method group may have associated an instance expression' 
@@ -3677,6 +3741,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsExplicitImpl {
+                       get {
+                               return is_explicit_impl;
+                       }
+
+                       set {
+                               is_explicit_impl = value;
+                       }
+               }
+
                public string Name {
                        get {
                                return Methods [0].Name;
@@ -3705,6 +3779,12 @@ namespace Mono.CSharp {
                
                override public Expression DoResolve (EmitContext ec)
                {
+                       if (instance_expression != null) {
+                               instance_expression = instance_expression.DoResolve (ec);
+                               if (instance_expression == null)
+                                       return null;
+                       }
+
                        return this;
                }
 
@@ -3789,6 +3869,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public Type DeclaringType {
+                       get {
+                               return FieldInfo.DeclaringType;
+                       }
+               }
+
                public Expression InstanceExpression {
                        get {
                                return instance_expr;
@@ -4061,6 +4147,12 @@ namespace Mono.CSharp {
                        }
                }
                
+               public Type DeclaringType {
+                       get {
+                               return PropertyInfo.DeclaringType;
+                       }
+               }
+
                //
                // The instance expression associated with this expression
                //
@@ -4096,6 +4188,17 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if ((instance_expr == null) && ec.IsStatic && !is_static) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
+                               return null;
+                       }
+
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return null;
+                       }
+
                        return this;
                }
 
@@ -4109,6 +4212,12 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return null;
+                       }
+
                        return this;
                }
 
@@ -4119,7 +4228,8 @@ namespace Mono.CSharp {
                        //
                        // Special case: length of single dimension array is turned into ldlen
                        //
-                       if (method == TypeManager.int_array_get_length){
+                       if ((method == TypeManager.system_int_array_get_length) ||
+                           (method == TypeManager.int_array_get_length)){
                                Type iet = instance_expr.Type;
 
                                //
@@ -4202,6 +4312,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public Type DeclaringType {
+                       get {
+                               return EventInfo.DeclaringType;
+                       }
+               }
+
                public Expression InstanceExpression {
                        get {
                                return instance_expr;
@@ -4214,7 +4330,12 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       // We are born fully resolved
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return null;
+                       }
+
                        return this;
                }