2003-04-17 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / interface.cs
index 968fbfb11eb7c8b22d5211a9456e4c7fbf22ed54..f47a91c35f8d9f6c860ba1cea92ac17fc38baee5 100755 (executable)
@@ -7,48 +7,79 @@
 //
 // (C) 2001 Ximian, Inc (http://www.ximian.com)
 //
-
+#define CACHE
 using System.Collections;
 using System;
 using System.IO;
 using System.Reflection;
 using System.Reflection.Emit;
 
-namespace CIR {
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Interfaces
+       /// </summary>
+       public class Interface : DeclSpace, IMemberContainer {
+               const MethodAttributes interface_method_attributes =
+                       MethodAttributes.Public |
+                       MethodAttributes.Abstract |
+                       MethodAttributes.HideBySig |
+                       MethodAttributes.NewSlot |
+                       MethodAttributes.Virtual;
 
-       public class Interface : DeclSpace {
+               const MethodAttributes property_attributes =
+                       MethodAttributes.Public |
+                       MethodAttributes.Abstract |
+                       MethodAttributes.HideBySig |
+                       MethodAttributes.NewSlot |
+                       MethodAttributes.SpecialName |
+                       MethodAttributes.Virtual;
+               
                ArrayList bases;
-               int mod_flags;
                
-               ArrayList defined_method_list;
-               ArrayList defined_indexer_list;
+               ArrayList defined_method;
+               ArrayList defined_indexer;
+               ArrayList defined_events;
+               ArrayList defined_properties;
+
+               ArrayList method_builders;
+               ArrayList property_builders;
+               ArrayList event_builders;
                
-               Hashtable defined_events;
-               Hashtable defined_properties;
+               Attributes OptAttributes;
+
+               public string IndexerName;
+
+               IMemberContainer parent_container;
+               MemberCache member_cache;
+
+               bool members_defined;
 
                // These will happen after the semantic analysis
                
                // Hashtable defined_indexers;
                // Hashtable defined_methods;
                
-               // <summary>
-               //   Modifiers allowed in a class declaration
-               // </summary>
+               /// <summary>
+               ///   Modifiers allowed in a class declaration
+               /// </summary>
                public const int AllowedModifiers =
-                       Modifiers.NEW |
-                       Modifiers.PUBLIC |
+                       Modifiers.NEW       |
+                       Modifiers.PUBLIC    |
                        Modifiers.PROTECTED |
-                       Modifiers.INTERNAL |
+                       Modifiers.INTERNAL  |
+                       Modifiers.UNSAFE    |
                        Modifiers.PRIVATE;
 
-               public Interface (TypeContainer parent, string name, int mod) : base (name)
+               public Interface (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
+                       : base (parent, name, l)
                {
-                       defined_events = new Hashtable ();
-                       defined_method_list = new ArrayList ();
-                       defined_indexer_list = new ArrayList ();
-                       defined_properties = new Hashtable ();
-
-                       this.mod_flags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PUBLIC);
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
+                       OptAttributes = attrs;
+                       
+                       method_builders = new ArrayList ();
+                       property_builders = new ArrayList ();
+                       event_builders = new ArrayList ();
                }
 
                public AdditionResult AddMethod (InterfaceMethod imethod)
@@ -61,7 +92,10 @@ namespace CIR {
                                        return AdditionResult.NameExists;
                        } 
 
-                       defined_method_list.Add (imethod);
+                       if (defined_method == null)
+                               defined_method = new ArrayList ();
+
+                       defined_method.Add (imethod);
                        if (value == null)
                                DefineName (name, imethod);
                        
@@ -78,7 +112,10 @@ namespace CIR {
 
                        DefineName (name, iprop);
 
-                       defined_properties.Add (name, iprop);
+                       if (defined_properties == null)
+                               defined_properties = new ArrayList ();
+
+                       defined_properties.Add (iprop);
                        return AdditionResult.Success;
                }
 
@@ -92,46 +129,46 @@ namespace CIR {
 
                        DefineName (name, ievent);
 
-                       defined_events.Add (name, ievent);
+                       if (defined_events == null)
+                               defined_events = new ArrayList ();
+
+                       defined_events.Add (ievent);
                        return AdditionResult.Success;
                }
 
                public bool AddIndexer (InterfaceIndexer iindexer)
                {
-                       defined_indexer_list.Add (iindexer);
+                       if (defined_indexer == null)
+                               defined_indexer = new ArrayList ();
+                       
+                       defined_indexer.Add (iindexer);
                        return true;
                }
                
-               public Hashtable InterfaceMethods {
+               public ArrayList InterfaceMethods {
                        get {
-                               return null; // defined_methods;
+                               return defined_method;
                        }
                }
 
-               public Hashtable InterfaceProperties {
+               public ArrayList InterfaceProperties {
                        get {
                                return defined_properties;
                        }
                }
 
-               public Hashtable InterfaceEvents {
+               public ArrayList InterfaceEvents {
                        get {
                                return defined_events;
                        }
                }
 
-               public Hashtable InterfaceIndexers {
+               public ArrayList InterfaceIndexers {
                        get {
-                               return null; // defined_indexers;
+                               return defined_indexer;
                        }
                }
 
-               public int ModFlags {
-                       get {
-                               return mod_flags;
-                       }
-               }
-               
                public ArrayList Bases {
                        get {
                                return bases;
@@ -142,190 +179,903 @@ namespace CIR {
                        }
                }
 
-               Type def;
-               bool in_transit = false;
-               public override Type Define (Tree tree)
-               {
-                       if (in_transit){
-                               CSC.CSharpParser.error (529, "There is a cycle in interface " + Name);
-                               return null;
-                       }
-                       in_transit = true;
+               public virtual TypeAttributes InterfaceAttr {
+                       get {
+                               TypeAttributes x = TypeAttributes.Interface | TypeAttributes.Abstract;
 
-                       ModuleBuilder mb = tree.ModuleBuilder;
+                               if (IsTopLevel == false) {
+                                       
+                                       if ((ModFlags & Modifiers.PROTECTED) != 0
+                                           && (ModFlags & Modifiers.INTERNAL) != 0)
+                                               x |= TypeAttributes.NestedFamORAssem;
+                                       else if ((ModFlags & Modifiers.PROTECTED) != 0)
+                                               x |= TypeAttributes.NestedFamily;
+                                       else if ((ModFlags & Modifiers.INTERNAL) != 0)
+                                               x |= TypeAttributes.NestedAssembly;
+                                       else if ((ModFlags & Modifiers.PUBLIC) != 0)
+                                               x |= TypeAttributes.NestedPublic;
+                                       else
+                                               x |= TypeAttributes.NestedPrivate;
+                               } else {
+                                       if ((ModFlags & Modifiers.PUBLIC) != 0)
+                                               x |= TypeAttributes.Public;
+                                       else if ((ModFlags & Modifiers.PRIVATE) != 0)
+                                               x |= TypeAttributes.NotPublic;
+                               }
+                               
+                               if ((ModFlags & Modifiers.ABSTRACT) != 0)
+                                       x |= TypeAttributes.Abstract;
+                               
+                               if ((ModFlags & Modifiers.SEALED) != 0)
+                                       x |= TypeAttributes.Sealed;
 
-                       if (bases != null){
-                               // FIXME: Go over each one of the TypeRefs
-                               // in Bases and resolve.
-                               Console.WriteLine ("Base interfaces not yet supported");
-                               return null;
+                               return x;
                        }
+               }
+               
+               void Error111 (InterfaceMemberBase ib)
+               {
+                       Report.Error (
+                               111,
+                               "Interface `" + Name + "' already contains a definition with the " +
+                               "same return value and parameter types for member `" + ib.Name + "'");
+               }
 
-                       TypeAttributes attr = TypeAttributes.Interface;
+               bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] types)
+               {
+                       if (!TypeManager.RegisterMethod (mb, ip, types))
+                               return false;
 
-                       attr |= Modifiers.TypeAttr (mod_flags);
-                       
-                       def = mb.DefineType (Name, attr);
+                       method_builders.Add (mb);
+                       return true;
+               }
 
-                       in_transit = false;
+               //
+               // This might trigger a definition of the methods.  This happens only
+               // with Attributes, as Attribute classes are processed before interfaces.
+               // Ideally, we should make everything just define recursively in terms
+               // of its dependencies.
+               //
+               public MethodInfo [] GetMethods (TypeContainer container)
+               {
+                       int n = 0;
+                       
+                       if (!members_defined){
+                               if (DefineMembers (container))
+                                       n = method_builders.Count;
+                       } else
+                               n = method_builders.Count;
+                       
+                       MethodInfo [] mi = new MethodInfo [n];
+                       
+                       method_builders.CopyTo (mi, 0);
 
-                       return def;
+                       return mi;
                }
-       }
 
-       public class InterfaceMemberBase {
-               string name;
-
-               public InterfaceMemberBase (string name)
+               // Hack around System.Reflection as found everywhere else
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
                {
-                       this.name = name;
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Method) != 0) {
+                               foreach (MethodBuilder mb in method_builders)
+                                       if (filter (mb, criteria))
+                                               members.Add (mb);
+                       }
+
+                       if ((mt & MemberTypes.Property) != 0) {
+                               foreach (PropertyBuilder pb in property_builders)
+                                       if (filter (pb, criteria))
+                                               members.Add (pb);
+                       }
+
+                       if ((mt & MemberTypes.Event) != 0) {
+                               foreach (MyEventBuilder eb in event_builders)
+                                       if (filter (eb, criteria))
+                                               members.Add (eb);
+                       }
+
+                       if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
+                               MemberList parent_mi;
+                               
+                               parent_mi = TypeContainer.FindMembers (
+                                       TypeBuilder.BaseType, mt, bf, filter, criteria);
+
+                               members.AddRange (parent_mi);
+                       }
+
+                       return new MemberList (members);
                }
-               
-               public string Name {
+
+               public override MemberCache MemberCache {
                        get {
-                               return name;
+                               return member_cache;
                        }
                }
-       }
-       
-       public class InterfaceProperty : InterfaceMemberBase {
-               bool has_get, has_set, is_new;
-               TypeRef typeref;
-               
-               public InterfaceProperty (TypeRef typeref, string name,
-                                         bool is_new, bool has_get, bool has_set)
-                       : base (name)
+
+               //
+               // Populates the methods in the interface
+               //
+               void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im)
                {
-                       this.typeref = typeref;
-                       this.is_new = is_new;
-                       this.has_get = has_get;
-                       this.has_set = has_set;
-               }
+                       Type return_type = im.ReturnType.Type;
+                       if (return_type == null)
+                               return_type = this.ResolveType (im.ReturnType, false, im.Location);
+                       
+                       Type [] arg_types = im.ParameterTypes (this);
+                       MethodBuilder mb;
+                       Parameter [] p;
+                       int i;
 
-               public bool HasGet {
-                       get {
-                               return has_get;
+                       if (return_type == null)
+                               return;
+
+                       if (return_type.IsPointer && !UnsafeOK (this))
+                               return;
+
+                       if (arg_types == null)
+                               return;
+
+                       foreach (Type t in arg_types){
+
+                               if (t == null)
+                                       return;
+                               
+                               if (t.IsPointer && !UnsafeOK (this))
+                                       return;
                        }
+                       
+                       //
+                       // Create the method
+                       //
+                       mb = TypeBuilder.DefineMethod (
+                               im.Name, interface_method_attributes,
+                               return_type, arg_types);
+
+                       InternalParameters ip = new InternalParameters (arg_types, im.Parameters);
+
+                       if (!RegisterMethod (mb, ip, arg_types)) {
+                               Error111 (im);
+                               return;
+                       }
+
+                       //
+                       // Define each type attribute (in/out/ref) and
+                       // the argument names.
+                       //
+                       p = im.Parameters.FixedParameters;
+                       if (p != null){
+                               for (i = 0; i < p.Length; i++)
+                                       mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
+
+                               if (i != arg_types.Length)
+                                       Console.WriteLine ("Implement the type definition for params");
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         return_type, ModFlags, false);
+
+                       if (im.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, mb, im, im.OptAttributes);
                }
 
-               public bool HasSet {
-                       get {
-                               return has_set;
+               //
+               // Populates the properties in the interface
+               //
+               void PopulateProperty (TypeContainer parent, DeclSpace decl_space, InterfaceProperty ip)
+               {
+                       PropertyBuilder pb;
+                       MethodBuilder get = null, set = null;
+                       ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
+                       if (ip.Type == null)
+                               return;
+                       
+                       Type prop_type = ip.Type.Type;
+                       Type [] setter_args = new Type [1];
+
+                       if (prop_type == null)
+                               return;
+
+                       if (prop_type.IsPointer && !UnsafeOK (this))
+                               return;
+                       
+                       setter_args [0] = prop_type;
+
+                       //
+                       // FIXME: properties are missing the following
+                       // flags: hidebysig newslot specialname
+                       //
+                       pb = TypeBuilder.DefineProperty (
+                               ip.Name, PropertyAttributes.None,
+                               prop_type, null);
+
+                       if (ip.HasGet){
+                               get = TypeBuilder.DefineMethod (
+                                       "get_" + ip.Name, property_attributes ,
+                                       prop_type, null);
+
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               Type [] null_types = null;
+                               InternalParameters inp = new InternalParameters
+                                       (null_types, Parameters.EmptyReadOnlyParameters);
+                               
+                               if (!RegisterMethod (get, inp, null)) {
+                                       Error111 (ip);
+                                       return;
+                               }
+                               
+                               pb.SetGetMethod (get);
                        }
+
+                       if (ip.HasSet){
+                               setter_args [0] = prop_type;
+
+                               set = TypeBuilder.DefineMethod (
+                                       "set_" + ip.Name, property_attributes,
+                                       TypeManager.void_type, setter_args);
+
+                               set.DefineParameter (1, ParameterAttributes.None, "value");
+                               pb.SetSetMethod (set);
+
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               Parameter [] parms = new Parameter [1];
+                               parms [0] = new Parameter (ip.Type, "value", Parameter.Modifier.NONE, null);
+                               InternalParameters ipp = new InternalParameters (
+                                       this, new Parameters (parms, null, Location.Null));
+                                       
+                               if (!RegisterMethod (set, ipp, setter_args)) {
+                                       Error111 (ip);
+                                       return;
+                               }
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         null, ModFlags, false);
+
+                       if (ip.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, pb, ip, ip.OptAttributes);
+
+                       TypeManager.RegisterProperty (pb, get, set);
+                       property_builders.Add (pb);
                }
 
-               public bool IsNew {
-                       get {
-                               return is_new;
+               //
+               // Populates the events in the interface
+               //
+               void PopulateEvent (TypeContainer parent, DeclSpace decl_space, InterfaceEvent ie)
+               {
+                       //
+                       // FIXME: We need to do this after delegates have been
+                       // declared or we declare them recursively.
+                       //
+                       MyEventBuilder eb;
+                       MethodBuilder add = null, remove = null;
+                       ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
+                       if (ie.Type == null)
+                               return;
+                       
+                       Type event_type = ie.Type.Type;
+
+                       if (event_type == null)
+                               return;
+
+                       if (event_type.IsPointer && !UnsafeOK (this))
+                               return;
+
+                       Type [] parameters = new Type [1];
+                       parameters [0] = event_type;
+
+                       eb = new MyEventBuilder (null, TypeBuilder, ie.Name,
+                                                EventAttributes.None, event_type);
+
+                       //
+                       // Now define the accessors
+                       //
+                       string add_name = "add_" + ie.Name;
+                       
+                       add = TypeBuilder.DefineMethod (
+                               add_name, property_attributes, null, parameters);
+                       add.DefineParameter (1, ParameterAttributes.None, "value");
+                       eb.SetAddOnMethod (add);
+
+                       string remove_name = "remove_" + ie.Name;
+                       remove = TypeBuilder.DefineMethod (
+                               remove_name, property_attributes, null, parameters);
+                       remove.DefineParameter (1, ParameterAttributes.None, "value");
+                       eb.SetRemoveOnMethod (remove);
+
+                       Parameter [] parms = new Parameter [1];
+                       parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null);
+                       InternalParameters ip = new InternalParameters (
+                               this, new Parameters (parms, null, Location.Null));
+
+                       if (!RegisterMethod (add, ip, parameters)) {
+                               Error111 (ie);
+                               return;
+                       }
+                       
+                       if (!RegisterMethod (remove, ip, parameters)) {
+                               Error111 (ie);
+                               return;
                        }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         null, ModFlags, false);
+
+
+                       if (ie.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, eb, ie, ie.OptAttributes);
+
+                       TypeManager.RegisterEvent (eb, add, remove);
+                       event_builders.Add (eb);
                }
 
-               public Type Type {
-                       get {
-                               return typeref.Type;
+               //
+               // Populates the indexers in the interface
+               //
+               void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii)
+               {
+                       PropertyBuilder pb;
+                       ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
+                       if (ii.Type == null)
+                               return;
+                       
+                       Type prop_type = ii.Type.Type;
+                       Type [] arg_types = ii.ParameterTypes (this);
+                       Type [] value_arg_types;
+
+                       if (prop_type == null)
+                               return;
+
+                       if (prop_type.IsPointer && !UnsafeOK (this))
+                               return;
+                       
+                       //
+                       // Sets up the extra invisible `value' argument for setters.
+                       // 
+                       if (arg_types != null){
+                               int count = arg_types.Length;
+                               value_arg_types = new Type [count + 1];
+
+                               arg_types.CopyTo (value_arg_types, 0);
+                               value_arg_types [count] = prop_type;
+
+                               foreach (Type t in arg_types){
+                                       if (t.IsPointer && !UnsafeOK (this))
+                                               return;
+                               }
+                       } else {
+                               value_arg_types = new Type [1];
+
+                               value_arg_types [1] = prop_type;
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         null, ModFlags, false);
+
+                       IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes);
+                       if (IndexerName == null)
+                               IndexerName = "Item";
+                       
+                       pb = TypeBuilder.DefineProperty (
+                               IndexerName, PropertyAttributes.None,
+                               prop_type, arg_types);
+                       
+                       MethodBuilder set_item = null, get_item = null;
+                       if (ii.HasGet){
+                               Parameter [] p = ii.Parameters.FixedParameters;
+                               
+                               get_item = TypeBuilder.DefineMethod (
+                                       "get_" + IndexerName, property_attributes,
+                                       prop_type, arg_types);
+                               pb.SetGetMethod (get_item);
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               InternalParameters ip = new InternalParameters (
+                                       arg_types, ii.Parameters);
+                               
+                               if (!RegisterMethod (get_item, ip, arg_types)) {
+                                       Error111 (ii);
+                                       return;
+                               }
+
+                               if (p != null){
+                                       for (int i = 0; i < p.Length; i++)
+                                               get_item.DefineParameter (
+                                                       i + 1,
+                                                       p [i].Attributes, p [i].Name);
+                               }
+                       }
+
+                       if (ii.HasSet){
+                               Parameter [] p = ii.Parameters.FixedParameters;
+                               Parameter [] pv;
+                               int i = 0;
+                               
+                               pv = new Parameter [p.Length + 1];
+                               p.CopyTo (pv, 0);
+                               pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null);
+                               Parameters value_params = new Parameters (pv, null, Location.Null);
+                               value_params.GetParameterInfo (decl_space);
+                               
+                               set_item = TypeBuilder.DefineMethod (
+                                       "set_" + IndexerName, property_attributes,
+                                       TypeManager.void_type, value_arg_types);
+                               pb.SetSetMethod (set_item);
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               InternalParameters ip = new InternalParameters (
+                                       value_arg_types, value_params);
+                               if (!RegisterMethod (set_item, ip, value_arg_types)) {
+                                       Error111 (ii);
+                                       return;
+                               }
+
+                               if (p != null){
+                                       for (; i < p.Length; i++)
+                                               set_item.DefineParameter (
+                                                       i + 1,
+                                                       p [i].Attributes, p [i].Name);
+                               }
+                               
+                               set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
                        }
+
+                       if (ii.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, pb, ii, ii.OptAttributes);
+
+                       property_builders.Add (pb);
                }
-       }
 
-       public class InterfaceEvent : InterfaceMemberBase {
-               TypeRef typeref;
-               bool is_new;
-               
-               public InterfaceEvent (TypeRef typeref, string name, bool is_new)
-                       : base (name)
+               /// <summary>
+               ///   Performs the semantic analysis for all the interface members
+               ///   that were declared
+               /// </summary>
+               bool SemanticAnalysis ()
                {
-                       this.typeref = typeref;
-                       this.is_new = is_new;
+                       Hashtable methods = new Hashtable ();
+
+                       
+                       if (defined_method != null){
+                               foreach (InterfaceMethod im in defined_method){
+                                       string sig = im.GetSignature (this);
+                                       
+                                       //
+                                       // If there was an undefined Type on the signatures
+                                       // 
+                                       if (sig == null)
+                                               continue;
+                                       
+                                       if (methods [sig] != null){
+                                               Error111 (im);
+                                               return false;
+                                       }
+                               }
+                       }
+
+                       //
+                       // FIXME: Here I should check i
+                       // 
+                       return true;
                }
 
-               public Type Type {
-                       get {
-                               return typeref.Type;
+               Type GetInterfaceTypeByName (string name)
+               {
+                       Type t = FindType (Location, name);
+
+                       if (t == null) {
+                               Report.Error (246, Location, "The type or namespace `" + name +
+                                             "' could not be found");
+                               return null;
                        }
+                       
+                       if (t.IsInterface)
+                               return t;
+                               
+                       string cause;
+                       
+                       if (t.IsValueType)
+                               cause = "is a struct";
+                       else if (t.IsClass) 
+                               cause = "is a class";
+                       else
+                               cause = "Should not happen.";
+                       
+                       Report.Error (527, Location, "`"+name+"' " + cause +
+                                     ", need an interface instead");
+                       
+                       return null;
                }
+               
+               //
+               // Returns the list of interfaces that this interface implements
+               // Or null if it does not implement any interface.
+               //
+               // Sets the error boolean accoringly.
+               //
+               Type [] GetInterfaceBases (out bool error)
+               {
+                       Type [] tbases;
+                       int i;
 
-               public bool IsNew {
-                       get {
-                               return is_new;
+                       error = false;
+                       if (Bases == null)
+                               return null;
+                       
+                       tbases = new Type [Bases.Count];
+                       i = 0;
+
+                       foreach (string name in Bases){
+                               Type t;
+
+                               t = GetInterfaceTypeByName (name);
+                               if (t == null){
+                                       error = true;
+                                       return null;
+                               }
+
+                               if (!Parent.AsAccessible (t, ModFlags))
+                                       Report.Error (61, Location,
+                                                     "Inconsistent accessibility: base interface `" +
+                                                     TypeManager.CSharpName (t) + "' is less " +
+                                                     "accessible than interface `" +
+                                                     Name + "'");
+
+                               tbases [i++] = t;
                        }
+                       
+                       return TypeManager.ExpandInterfaces (tbases);
                }
-       }
-       
-       public class InterfaceMethod : InterfaceMemberBase {
-               TypeRef return_type;
-               bool is_new;
-               Parameters args;
                
-               public InterfaceMethod (TypeRef return_type, string name, bool is_new, Parameters args)
-                       : base (name)
+               //
+               // <summary>
+               //  Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
+               // </summary>
+               //
+               // TODO:
+               //   Rework the way we recurse, because for recursive
+               //   definitions of interfaces (A:B and B:A) we report the
+               //   error twice, rather than once.  
+               
+               public override TypeBuilder DefineType ()
                {
-                       this.return_type = return_type;
-                       this.is_new = is_new;
-                       this.args = args;
+                       Type [] ifaces;
+                       bool error;
+
+                       if (TypeBuilder != null)
+                               return TypeBuilder;
+                       
+                       if (InTransit)
+                               return null;
+                       
+                       InTransit = true;
+                       
+                       ifaces = GetInterfaceBases (out error);
+
+                       if (error)
+                               return null;
+
+                       if (IsTopLevel) {
+                               ModuleBuilder builder = CodeGen.ModuleBuilder;
+
+                               TypeBuilder = builder.DefineType (
+                                       Name,
+                                       InterfaceAttr,
+                                       (Type)null,   // Parent Type
+                                       ifaces);
+                               RootContext.RegisterOrder (this);
+                       } else {
+                               TypeBuilder builder = Parent.TypeBuilder;
+
+                               TypeBuilder = builder.DefineNestedType (
+                                       Basename,
+                                       InterfaceAttr,
+                                       (Type) null, //parent type
+                                       ifaces);
+
+                               TypeContainer tc = TypeManager.LookupTypeContainer (builder);
+                               tc.RegisterOrder (this);
+                       }
+
+                       TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
+                       InTransit = false;
+
+                       return TypeBuilder;
                }
 
-               public Type ReturnType {
-                       get {
-                               return return_type.Type;
+               //
+               // Defines the indexers, and also verifies that the IndexerNameAttribute in the
+               // interface is consistent.  Either it is `Item' or it is the name defined by all the
+               // indexers with the `IndexerName' attribute.
+               //
+               // Turns out that the IndexerNameAttribute is applied to each indexer,
+               // but it is never emitted, instead a DefaultName attribute is attached
+               // to the interface
+               //
+               void DefineIndexers (TypeContainer parent)
+               {
+                       string interface_indexer_name = null;
+
+                       foreach (InterfaceIndexer ii in defined_indexer){
+
+                               PopulateIndexer (parent, this, ii);
+
+                               if (interface_indexer_name == null){
+                                       interface_indexer_name = IndexerName;
+                                       continue;
+                               }
+                               
+                               if (IndexerName == interface_indexer_name)
+                                       continue;
+                               
+                               Report.Error (
+                                       668, "Two indexers have different names, " +
+                                       " you should use the same name for all your indexers");
                        }
+                       if (interface_indexer_name == null)
+                               interface_indexer_name = "Item";
+                       IndexerName = interface_indexer_name;
                }
+               
+               /// <summary>
+               ///   Performs semantic analysis, and then generates the IL interfaces
+               /// </summary>
+               public override bool DefineMembers (TypeContainer parent)
+               {
+                       if (members_defined)
+                               return true;
+                       
+                       if (!SemanticAnalysis ())
+                               return false;
 
-               public bool IsNew {
-                       get {
-                               return is_new;
+                       
+                       if (defined_method != null){
+                               foreach (InterfaceMethod im in defined_method)
+                                       PopulateMethod (parent, this, im);
+                       }
+
+                       if (defined_properties != null){
+                               foreach (InterfaceProperty ip in defined_properties)
+                                       PopulateProperty (parent, this, ip);
                        }
+
+                       if (defined_events != null)
+                               foreach (InterfaceEvent ie in defined_events)
+                                       PopulateEvent (parent, this, ie);
+
+                       if (defined_indexer != null) {
+                               DefineIndexers (parent);
+
+                               CustomAttributeBuilder cb = EmitDefaultMemberAttr (
+                                       parent, IndexerName, ModFlags, Location);
+                               if (cb != null)
+                                       TypeBuilder.SetCustomAttribute (cb);
+                       }
+
+#if CACHE
+                       if (TypeBuilder.BaseType != null)
+                               parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+                       member_cache = new MemberCache (this);
+#endif
+                       members_defined = true;
+                       return true;
                }
 
-               public Parameters Parameters {
-                       get {
-                               return args;
+               /// <summary>
+               ///   Applies all the attributes.
+               /// </summary>
+               public override bool Define (TypeContainer parent)
+               {
+                       if (OptAttributes != null) {
+                               EmitContext ec = new EmitContext (parent, this, Location, null, null,
+                                                                 ModFlags, false);
+                               Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
                        }
+
+                       return true;
                }
-       }
 
-       public class InterfaceIndexer : InterfaceMemberBase {
-               bool do_get, do_set, is_new;
-               Parameters args;
-               TypeRef typeref;
-               
-               public InterfaceIndexer (TypeRef typeref, Parameters args, bool do_get, bool do_set, bool is_new)
-                       : base ("")
+               public static CustomAttributeBuilder EmitDefaultMemberAttr (TypeContainer parent,
+                                                                           string name,
+                                                                           int flags,
+                                                                           Location loc)
                {
-                       this.typeref = typeref;
-                       this.args = args;
-                       this.do_get = do_get;
-                       this.do_set = do_set;
-                       this.is_new = is_new;
+                       EmitContext ec = new EmitContext (parent, loc, null, null, flags);
+
+                       Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
+                                                                ".ctor", MemberTypes.Constructor,
+                                                                BindingFlags.Public | BindingFlags.Instance,
+                                                                Location.Null);
+                       
+                       if (!(ml is MethodGroupExpr)) {
+                               Console.WriteLine ("Internal error !!!!");
+                               return null;
+                       }
+                       
+                       MethodGroupExpr mg = (MethodGroupExpr) ml;
+
+                       MethodBase constructor = mg.Methods [0];
+
+                       string [] vals = { name };
+
+                       CustomAttributeBuilder cb = null;
+                       try {
+                               cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
+                       } catch {
+                               Report.Warning (-100, "Can not set the indexer default member attribute");
+                       }
+
+                       return cb;
                }
 
-               public Type Type {
+               //
+               // IMemberContainer
+               //
+
+               string IMemberContainer.Name {
                        get {
-                               return typeref.Type;
+                               return Name;
                        }
                }
 
-               public Parameters Parameters {
+               Type IMemberContainer.Type {
                        get {
-                               return args;
+                               return TypeBuilder;
                        }
                }
 
-               public bool HasGet {
+               IMemberContainer IMemberContainer.Parent {
                        get {
-                               return do_get;
+                               return parent_container;
                        }
                }
 
-               public bool HasSet {
+               MemberCache IMemberContainer.MemberCache {
                        get {
-                               return do_set;
+                               return member_cache;
                        }
                }
 
-               public bool IsNew {
+               bool IMemberContainer.IsInterface {
                        get {
-                               return is_new;
+                               return true;
                        }
                }
+
+               MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+               {
+                       // Interfaces only contain instance members.
+                       if ((bf & BindingFlags.Instance) == 0)
+                               return MemberList.Empty;
+                       if ((bf & BindingFlags.Public) == 0)
+                               return MemberList.Empty;
+
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Method) != 0)
+                               members.AddRange (method_builders);
+
+                       if ((mt & MemberTypes.Property) != 0)
+                               members.AddRange (property_builders);
+
+                       if ((mt & MemberTypes.Event) != 0)
+                               members.AddRange (event_builders);
+
+                       return new MemberList (members);
+               }
+       }
+
+       public class InterfaceMemberBase {
+               public readonly string Name;
+               public readonly bool IsNew;
+               public Attributes OptAttributes;
+               
+               public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
+               {
+                       Name = name;
+                       IsNew = is_new;
+                       OptAttributes = attrs;
+               }
+       }
+       
+       public class InterfaceProperty : InterfaceMemberBase {
+               public readonly bool HasSet;
+               public readonly bool HasGet;
+               public readonly Location Location;
+               public Expression Type;
+               
+               public InterfaceProperty (Expression type, string name,
+                                         bool is_new, bool has_get, bool has_set,
+                                         Attributes attrs, Location loc)
+                       : base (name, is_new, attrs)
+               {
+                       Type = type;
+                       HasGet = has_get;
+                       HasSet = has_set;
+                       Location = loc;
+               }
+       }
+
+       public class InterfaceEvent : InterfaceMemberBase {
+               public readonly Location Location;
+               public Expression Type;
+               
+               public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs,
+                                      Location loc)
+                       : base (name, is_new, attrs)
+               {
+                       Type = type;
+                       Location = loc;
+               }
+       }
+       
+       public class InterfaceMethod : InterfaceMemberBase {
+               public Expression ReturnType;
+               public readonly Parameters Parameters;
+               public readonly Location Location;
+               
+               public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args,
+                                       Attributes attrs, Location l)
+                       : base (name, is_new, attrs)
+               {
+                       this.ReturnType = return_type;
+                       this.Parameters = args;
+                       Location = l;
+               }
+
+               /// <summary>
+               ///   Returns the signature for this interface method
+               /// </summary>
+               public string GetSignature (DeclSpace ds)
+               {
+                       ReturnType = ds.ResolveTypeExpr (ReturnType, false, Location);
+                       if (ReturnType == null)
+                               return null;
+                       
+                       Type ret = ReturnType.Type;
+                       string args = Parameters.GetSignature (ds);
+
+                       if ((ret == null) || (args == null))
+                               return null;
+                       
+                       return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
+               }
+
+               public Type [] ParameterTypes (DeclSpace ds)
+               {
+                       return Parameters.GetParameterInfo (ds);
+               }
+       }
+
+       public class InterfaceIndexer : InterfaceMemberBase {
+               public readonly bool HasGet, HasSet;
+               public readonly Parameters Parameters;
+               public readonly Location Location;
+               public Expression Type;
+               
+               public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set,
+                                        bool is_new, Attributes attrs, Location loc)
+                       : base ("", is_new, attrs)
+               {
+                       Type = type;
+                       Parameters = args;
+                       HasGet = do_get;
+                       HasSet = do_set;
+                       Location = loc;
+               }
+
+               public Type [] ParameterTypes (DeclSpace ds)
+               {
+                       return Parameters.GetParameterInfo (ds);
+               }
        }
 }