2004-03-13 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / gmcs / ecore.cs
index 60f583b959fb9834cb649f5db4afd289292da0e6..dc8c65a00502256f8cf68def1c1858897c8d963d 100755 (executable)
@@ -251,15 +251,9 @@ namespace Mono.CSharp {
                // value will be returned if the expression is not a type
                // reference
                //
-               public Expression ResolveAsTypeTerminal (EmitContext ec)
+               public TypeExpr ResolveAsTypeTerminal (EmitContext ec)
                {
-                       Expression e = ResolveAsTypeStep (ec);
-
-                       if (e == null)
-                               return null;
-                       if (e is SimpleName)
-                               return null;
-                       return e;
+                       return ResolveAsTypeStep (ec) as TypeExpr;
                }
               
                /// <summary>
@@ -320,10 +314,12 @@ namespace Mono.CSharp {
                                break;
 
                        case ExprClass.MethodGroup:
+                               if (!RootContext.V2){
                                if ((flags & ResolveFlags.MethodGroup) == 0) {
                                        ((MethodGroupExpr) e).ReportUsageError ();
                                        return null;
                                }
+                               }
                                break;
 
                        case ExprClass.Value:
@@ -411,6 +407,12 @@ namespace Mono.CSharp {
                /// </remarks>
                public abstract void Emit (EmitContext ec);
 
+               public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       Emit (ec);
+                       ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+               }
+
                /// <summary>
                ///   Protected constructor.  Only derivate types should
                ///   be able to be created
@@ -484,7 +486,7 @@ namespace Mono.CSharp {
                        else if (mi is PropertyInfo)
                                return new PropertyExpr (ec, (PropertyInfo) mi, loc);
                        else if (mi is Type){
-                               return new TypeExpr ((System.Type) mi, loc);
+                               return new TypeExpression ((System.Type) mi, loc);
                        }
 
                        return null;
@@ -669,11 +671,15 @@ namespace Mono.CSharp {
                                Report.Error (
                                        122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." +
                                        name + "' is inaccessible due to its protection level");
-                       else
+                       else if (name == ".ctor") {
+                               Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
+                                                                      TypeManager.CSharpName (queried_type)));
+                       } else {
                                Report.Error (
                                        122, loc, "`" + name + "' is inaccessible due to its " +
                                        "protection level");
                }
+               }
 
                static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
                {
@@ -826,7 +832,7 @@ namespace Mono.CSharp {
                               "a `" + sb.ToString () + "' was expected");
                }
                
-               static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
+               static public void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
                {
                        Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " +
                                      TypeManager.CSharpName (t));
@@ -1320,6 +1326,12 @@ namespace Mono.CSharp {
        public class EmptyCast : Expression {
                protected Expression child;
                
+               public Expression Child {
+                       get {
+                               return child;
+                       }
+               }               
+
                public EmptyCast (Expression child, Type return_type)
                {
                        eclass = child.eclass;
@@ -1879,6 +1891,7 @@ namespace Mono.CSharp {
        /// </remarks>
        public class SimpleName : Expression {
                public string Name;
+               public int NumTypeParameters;
 
                //
                // If true, then we are a simple name, not composed with a ".
@@ -1899,6 +1912,14 @@ namespace Mono.CSharp {
                        is_base = true;
                }
 
+               public SimpleName (string name, int num_type_params, Location l)
+               {
+                       Name = name;
+                       NumTypeParameters = num_type_params;
+                       loc = l;
+                       is_base = true;
+               }
+
                public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
                {
                        if (ec.IsFieldInitializer)
@@ -1950,7 +1971,7 @@ namespace Mono.CSharp {
                public override Expression ResolveAsTypeStep (EmitContext ec)
                {
                        DeclSpace ds = ec.DeclSpace;
-                       NamespaceEntry ns = ds.Namespace;
+                       NamespaceEntry ns = ds.NamespaceEntry;
                        Type t;
                        string alias_value;
 
@@ -1964,19 +1985,19 @@ namespace Mono.CSharp {
                                alias_value = null;
 
                        if (ec.ResolvingTypeTree){
-                               if (alias_value != null){
-                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
-                                               return new TypeExpr (t, loc);
-                               }
-
                                int errors = Report.Errors;
-                               Type dt = ec.DeclSpace.FindType (loc, Name);
+                               Type dt = ds.FindType (loc, Name, NumTypeParameters);
                                
                                if (Report.Errors != errors)
                                        return null;
                                
                                if (dt != null)
-                                       return new TypeExpr (dt, loc);
+                                       return new TypeExpression (dt, loc);
+
+                               if (alias_value != null){
+                                       if ((t = RootContext.LookupType (ds, alias_value, true, NumTypeParameters, loc)) != null)
+                                               return new TypeExpression (t, loc);
+                               }
                        }
 
                        //
@@ -1984,19 +2005,23 @@ namespace Mono.CSharp {
                        //
                        if (alias_value != null){
                                if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
-                                       return new TypeExpr (t, loc);
+                                       return new TypeExpression (t, loc);
                                
                                // we have alias value, but it isn't Type, so try if it's namespace
                                return new SimpleName (alias_value, loc);
                        }
-                       
+
+                       TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc);
+                       if (generic_type != null)
+                               return generic_type.ResolveAsTypeTerminal (ec);
+
                        //
                        // Stage 2: Lookup up if we are an alias to a type
                        // or a namespace.
                        //
 
-                       if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
-                               return new TypeExpr (t, loc);
+                       if ((t = RootContext.LookupType (ds, Name, true, NumTypeParameters, loc)) != null)
+                               return new TypeExpression (t, loc);
                                
                        // No match, maybe our parent can compose us
                        // into something meaningful.
@@ -2024,29 +2049,6 @@ namespace Mono.CSharp {
                {
                        Expression e = null;
 
-                       //
-                       // Since we are cheating (is_base is our hint
-                       // that we are the beginning of the name): we
-                       // only do the Alias lookup for namespaces if
-                       // the name does not include any dots in it
-                       //
-                       NamespaceEntry ns = ec.DeclSpace.Namespace;
-                       if (is_base && ns != null){
-                               string alias_value = ns.LookupAlias (Name);
-                               if (alias_value != null){
-                                       Name = alias_value;
-                                       Type t;
-
-                                       if ((t = TypeManager.LookupType (Name)) != null)
-                                               return new TypeExpr (t, loc);
-                                       
-                                       // No match, maybe our parent can compose us
-                                       // into something meaningful.
-                                       return this;
-                               }
-                       }
-                       
-                       
                        //
                        // Stage 1: Performed by the parser (binding to locals or parameters).
                        //
@@ -2097,12 +2099,35 @@ namespace Mono.CSharp {
 
                                lookup_ds =lookup_ds.Parent;
                        } while (lookup_ds != null);
-                               
+
                        if (e == null && ec.ContainerType != null)
                                e = MemberLookup (ec, ec.ContainerType, Name, loc);
 
-                       if (e == null)
+                       if (e == null) {
+                               //
+                               // Since we are cheating (is_base is our hint
+                               // that we are the beginning of the name): we
+                               // only do the Alias lookup for namespaces if
+                               // the name does not include any dots in it
+                               //
+                               NamespaceEntry ns = ec.DeclSpace.NamespaceEntry;
+                               if (is_base && ns != null){
+                                       string alias_value = ns.LookupAlias (Name);
+                                       if (alias_value != null){
+                                               Name = alias_value;
+                                               Type t;
+
+                                               if ((t = TypeManager.LookupType (Name)) != null)
+                                                       return new TypeExpression (t, loc);
+                                       
+                                               // No match, maybe our parent can compose us
+                                               // into something meaningful.
+                                               return this;
+                                       }
+                               }
+
                                return ResolveAsTypeStep (ec);
+                       }
 
                        if (e is TypeExpr)
                                return e;
@@ -2168,22 +2193,20 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved expression that evaluates to a type
        /// </summary>
-       public class TypeExpr : Expression {
-               public TypeExpr (Type t, Location l)
+       public abstract class TypeExpr : Expression {
+               override public Expression ResolveAsTypeStep (EmitContext ec)
                {
-                       Type = t;
-                       eclass = ExprClass.Type;
-                       loc = l;
-               }
+                       TypeExpr t = DoResolveAsTypeStep (ec);
+                       if (t == null)
+                               return null;
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
-               {
-                       return this;
+                       eclass = ExprClass.Type;
+                       return t;
                }
 
                override public Expression DoResolve (EmitContext ec)
                {
-                       return this;
+                       return ResolveAsTypeTerminal (ec);
                }
 
                override public void Emit (EmitContext ec)
@@ -2191,9 +2214,102 @@ namespace Mono.CSharp {
                        throw new Exception ("Should never be called");
                }
 
+               public virtual bool CheckAccessLevel (DeclSpace ds)
+               {
+                       return ds.CheckAccessLevel (Type);
+               }
+
+               public virtual bool AsAccessible (DeclSpace ds, int flags)
+               {
+                       return ds.AsAccessible (Type, flags);
+               }
+
+               public virtual bool IsClass {
+                       get { return Type.IsClass; }
+               }
+
+               public virtual bool IsValueType {
+                       get { return Type.IsValueType; }
+               }
+
+               public virtual bool IsInterface {
+                       get { return Type.IsInterface; }
+               }
+
+               public virtual bool IsSealed {
+                       get { return Type.IsSealed; }
+               }
+
+               public virtual bool CanInheritFrom ()
+               {
+                       if (Type == TypeManager.enum_type ||
+                           (Type == TypeManager.value_type && RootContext.StdLib) ||
+                           Type == TypeManager.delegate_type ||
+                           Type == TypeManager.array_type)
+                               return false;
+
+                       return true;
+               }
+
+               public virtual bool IsAttribute {
+                       get {
+                               return Type == TypeManager.attribute_type ||
+                                       Type.IsSubclassOf (TypeManager.attribute_type);
+                       }
+               }
+
+               public virtual TypeExpr[] GetInterfaces ()
+               {
+                       return TypeManager.GetInterfaces (Type);
+               }
+
+               public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
+
+               public virtual Type ResolveType (EmitContext ec)
+               {
+                       TypeExpr t = ResolveAsTypeTerminal (ec);
+                       if (t == null)
+                               return null;
+
+                       return t.Type;
+               }
+
+               public abstract string Name {
+                       get;
+               }
+
+               public override bool Equals (object obj)
+               {
+                       TypeExpr tobj = obj as TypeExpr;
+                       if (tobj == null)
+                               return false;
+
+                       return Type == tobj.Type;
+               }
+
                public override string ToString ()
                {
-                       return Type.ToString ();
+                       return Name;
+               }
+       }
+
+       public class TypeExpression : TypeExpr {
+               public TypeExpression (Type t, Location l)
+               {
+                       Type = t;
+                       eclass = ExprClass.Type;
+                       loc = l;
+               }
+
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override string Name {
+                       get {
+                               return Type.ToString ();
+                       }
                }
        }
 
@@ -2205,31 +2321,22 @@ namespace Mono.CSharp {
        public class TypeLookupExpression : TypeExpr {
                string name;
                
-               public TypeLookupExpression (string name) : base (null, Location.Null)
+               public TypeLookupExpression (string name)
                {
                        this.name = name;
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
                        if (type == null)
                                type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
                        return this;
                }
 
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       return ResolveAsTypeStep (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Should never be called");
-               }
-
-               public override string ToString ()
-               {
-                       return name;
+               public override string Name {
+                       get {
+                               return name;
+                       }
                }
        }
 
@@ -2407,7 +2514,7 @@ namespace Mono.CSharp {
                {
                        FieldInfo = fi;
                        eclass = ExprClass.Variable;
-                       type = fi.FieldType;
+                       type = TypeManager.TypeToCoreType (fi.FieldType);
                        loc = l;
                }
 
@@ -2519,12 +2626,25 @@ namespace Mono.CSharp {
                        if (!FieldInfo.IsInitOnly)
                                return this;
 
+                       FieldBase fb = TypeManager.GetField (FieldInfo);
+                       if (fb != null)
+                               fb.SetAssigned ();
+
                        //
                        // InitOnly fields can only be assigned in constructors
                        //
 
                        if (ec.IsConstructor){
-                               if (ec.ContainerType == FieldInfo.DeclaringType)
+                               if (IsStatic && !ec.IsStatic)
+                                       Report_AssignToReadonly (false);
+
+                               Type ctype;
+                               if (ec.TypeContainer.CurrentType != null)
+                                       ctype = ec.TypeContainer.CurrentType.ResolveType (ec);
+                               else
+                                       ctype = ec.ContainerType;
+
+                               if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
                                        return this;
                        }
 
@@ -2549,11 +2669,12 @@ namespace Mono.CSharp {
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
-                                       is_volatile = true;
-                               
-                               f.status |= Field.Status.USED;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                               is_volatile = true;
+                                       
+                                       f.status |= Field.Status.USED;
+                               }
                        } 
                        
                        if (FieldInfo.IsStatic){
@@ -2604,7 +2725,7 @@ namespace Mono.CSharp {
                                Report_AssignToReadonly (!is_static);
                                return;
                        }
-                       
+
                        if (!is_static){
                                Expression instance = instance_expr;
 
@@ -2624,11 +2745,12 @@ namespace Mono.CSharp {
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-                               
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
-                                       ig.Emit (OpCodes.Volatile);
-                               
-                               f.status |= Field.Status.ASSIGNED;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                               ig.Emit (OpCodes.Volatile);
+                                       
+                                       f.status |= Field.Status.ASSIGNED;
+                               }
                        } 
 
                        if (is_static)
@@ -2643,24 +2765,38 @@ namespace Mono.CSharp {
                        
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0){
-                                       Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
-                                       return;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0){
+                                               Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
+                                               return;
+                                       }
+                                       
+                                       if ((mode & AddressOp.Store) != 0)
+                                               f.status |= Field.Status.ASSIGNED;
+                                       if ((mode & AddressOp.Load) != 0)
+                                               f.status |= Field.Status.USED;
                                }
-                               
-                               if ((mode & AddressOp.Store) != 0)
-                                       f.status |= Field.Status.ASSIGNED;
-                               if ((mode & AddressOp.Load) != 0)
-                                       f.status |= Field.Status.USED;
                        } 
 
                        //
                        // Handle initonly fields specially: make a copy and then
                        // get the address of the copy.
                        //
-                       if (FieldInfo.IsInitOnly && !ec.IsConstructor){
+                       bool need_copy;
+                       if (FieldInfo.IsInitOnly){
+                               need_copy = true;
+                               if (ec.IsConstructor){
+                                       if (FieldInfo.IsStatic){
+                                               if (ec.IsStatic)
+                                                       need_copy = false;
+                                       } else
+                                               need_copy = false;
+                               }
+                       } else
+                               need_copy = false;
+                       
+                       if (need_copy){
                                LocalBuilder local;
-                               
                                Emit (ec);
                                local = ig.DeclareLocal (type);
                                ig.Emit (OpCodes.Stloc, local);
@@ -2668,9 +2804,10 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (FieldInfo.IsStatic)
+
+                       if (FieldInfo.IsStatic){
                                ig.Emit (OpCodes.Ldsflda, FieldInfo);
-                       else {
+                       else {
                                //
                                // In the case of `This', we call the AddressOf method, which will
                                // only load the pointer, and not perform an Ldobj immediately after
@@ -2689,6 +2826,20 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // A FieldExpr whose address can not be taken
+       //
+       public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
+               public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
+               {
+               }
+               
+               public new void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
+               }
+       }
+       
        /// <summary>
        ///   Expression that evaluates to a Property.  The Assign class
        ///   might set the `Value' expression if we are in an assignment.
@@ -2816,9 +2967,7 @@ namespace Mono.CSharp {
 
                                // Assembly and FamORAssem succeed if we're in the same assembly.
                                if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
-                                       if (mi.DeclaringType.Assembly != invocation_type.Assembly)
-                                               continue;
-                                       else
+                                       if (mi.DeclaringType.Assembly == invocation_type.Assembly)
                                                return mi;
                                }
 
@@ -2827,7 +2976,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                // Family and FamANDAssem require that we derive.
-                               if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
+                               if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
                                        if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
                                                continue;
                                        else {
@@ -2977,6 +3126,7 @@ namespace Mono.CSharp {
                                if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
                                        instance_expr.Emit (ec);
                                        ec.ig.Emit (OpCodes.Ldlen);
+                                       ec.ig.Emit (OpCodes.Conv_I4);
                                        return;
                                }
                        }
@@ -3087,14 +3237,15 @@ namespace Mono.CSharp {
 
                public void EmitAddOrRemove (EmitContext ec, Expression source)
                {
-                       Expression handler = ((Binary) source).Right;
+                       BinaryDelegate source_del = (BinaryDelegate) source;
+                       Expression handler = source_del.Right;
                        
                        Argument arg = new Argument (handler, Argument.AType.Expression);
                        ArrayList args = new ArrayList ();
                                
                        args.Add (arg);
                        
-                       if (((Binary) source).Oper == Binary.Operator.Addition)
+                       if (source_del.IsAddition)
                                Invocation.EmitCall (
                                        ec, false, IsStatic, instance_expr, add_accessor, args, loc);
                        else