2 // interface.cs: Interface handler
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
11 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
19 public class Interface : DeclSpace {
20 const MethodAttributes interface_method_attributes =
21 MethodAttributes.Public |
22 MethodAttributes.Abstract |
23 MethodAttributes.HideBySig |
24 MethodAttributes.NewSlot |
25 MethodAttributes.Virtual;
27 const MethodAttributes property_attributes =
28 MethodAttributes.Public |
29 MethodAttributes.Abstract |
30 MethodAttributes.HideBySig |
31 MethodAttributes.NewSlot |
32 MethodAttributes.SpecialName |
33 MethodAttributes.Virtual;
38 ArrayList defined_method;
39 ArrayList defined_indexer;
40 ArrayList defined_events;
41 ArrayList defined_properties;
43 ArrayList method_builders;
44 ArrayList property_builders;
48 Attributes OptAttributes;
50 public readonly RootContext RootContext;
52 // These will happen after the semantic analysis
54 // Hashtable defined_indexers;
55 // Hashtable defined_methods;
58 // Modifiers allowed in a class declaration
60 public const int AllowedModifiers =
67 public Interface (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
70 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PUBLIC);
72 OptAttributes = attrs;
75 method_builders = new ArrayList ();
76 property_builders = new ArrayList ();
79 public AdditionResult AddMethod (InterfaceMethod imethod)
81 string name = imethod.Name;
82 Object value = defined_names [name];
85 if (!(value is InterfaceMethod))
86 return AdditionResult.NameExists;
89 if (defined_method == null)
90 defined_method = new ArrayList ();
92 defined_method.Add (imethod);
94 DefineName (name, imethod);
96 return AdditionResult.Success;
99 public AdditionResult AddProperty (InterfaceProperty iprop)
102 string name = iprop.Name;
104 if ((res = IsValid (name)) != AdditionResult.Success)
107 DefineName (name, iprop);
109 if (defined_properties == null)
110 defined_properties = new ArrayList ();
112 defined_properties.Add (iprop);
113 return AdditionResult.Success;
116 public AdditionResult AddEvent (InterfaceEvent ievent)
118 string name = ievent.Name;
121 if ((res = IsValid (name)) != AdditionResult.Success)
124 DefineName (name, ievent);
126 if (defined_events == null)
127 defined_events = new ArrayList ();
129 defined_events.Add (ievent);
130 return AdditionResult.Success;
133 public bool AddIndexer (InterfaceIndexer iindexer)
135 if (defined_indexer == null)
136 defined_indexer = new ArrayList ();
138 defined_indexer.Add (iindexer);
142 public ArrayList InterfaceMethods {
144 return defined_method;
148 public ArrayList InterfaceProperties {
150 return defined_properties;
154 public ArrayList InterfaceEvents {
156 return defined_events;
160 public ArrayList InterfaceIndexers {
162 return defined_indexer;
166 public int ModFlags {
172 public ArrayList Bases {
182 public bool IsTopLevel {
185 if (parent.Parent == null)
192 public virtual TypeAttributes InterfaceAttr {
194 TypeAttributes x = 0;
196 if ((mod_flags & Modifiers.PUBLIC) != 0)
197 x |= TypeAttributes.Public;
198 else if ((mod_flags & Modifiers.PRIVATE) != 0)
199 x |= TypeAttributes.NotPublic;
201 if (IsTopLevel == false) {
203 if ((mod_flags & Modifiers.PROTECTED) != 0
204 && (mod_flags & Modifiers.INTERNAL) != 0)
205 x |= TypeAttributes.NestedFamORAssem;
207 if ((mod_flags & Modifiers.PROTECTED) != 0)
208 x |= TypeAttributes.NestedFamily;
210 if ((mod_flags & Modifiers.INTERNAL) != 0)
211 x |= TypeAttributes.NestedAssembly;
215 if ((mod_flags & Modifiers.ABSTRACT) != 0)
216 x |= TypeAttributes.Abstract;
218 if ((mod_flags & Modifiers.SEALED) != 0)
219 x |= TypeAttributes.Sealed;
225 void Error111 (InterfaceMemberBase ib)
229 "Interface `" + Name + "' already contains a definition with the " +
230 "same return value and parameter types for member `" + ib.Name + "'");
233 bool RegisterMethod (MethodBase mb, Type [] types)
235 if (!TypeManager.RegisterMethod (mb, types))
238 method_builders.Add (mb);
242 public MethodInfo [] GetMethods ()
244 int n = method_builders.Count;
245 MethodInfo [] mi = new MethodInfo [n];
247 method_builders.CopyTo (mi, 0);
252 // Hack around System.Reflection as found everywhere else
253 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
255 ArrayList members = new ArrayList ();
257 if ((mt & MemberTypes.Method) != 0) {
258 foreach (MethodBuilder mb in method_builders)
259 if (filter (mb, criteria))
263 if ((mt & MemberTypes.Property) != 0) {
264 foreach (PropertyBuilder pb in property_builders)
265 if (filter (pb, criteria))
269 // The rest of the cases, if any, are unhandled at present.
271 int count = members.Count;
274 MemberInfo [] mi = new MemberInfo [count];
275 members.CopyTo (mi, 0);
284 // Populates the methods in the interface
286 void PopulateMethod (InterfaceMethod im)
288 Type return_type = parent.LookupType (im.ReturnType, true);
289 Type [] arg_types = im.ParameterTypes (parent);
297 mb = TypeBuilder.DefineMethod (
298 im.Name, interface_method_attributes,
299 return_type, arg_types);
301 if (!RegisterMethod (mb, arg_types)) {
307 // Define each type attribute (in/out/ref) and
308 // the argument names.
310 p = im.Parameters.FixedParameters;
312 for (i = 0; i < p.Length; i++)
313 mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
315 if (i != arg_types.Length)
316 Console.WriteLine ("Implement the type definition for params");
321 // Populates the properties in the interface
323 void PopulateProperty (InterfaceProperty ip)
327 Type prop_type = parent.LookupType (ip.Type, true);
328 Type [] setter_args = new Type [1];
330 setter_args [0] = prop_type;
333 // FIXME: properties are missing the following
334 // flags: hidebysig newslot specialname
336 pb = TypeBuilder.DefineProperty (
337 ip.Name, PropertyAttributes.None,
341 mb = TypeBuilder.DefineMethod (
342 "get_" + ip.Name, property_attributes ,
346 // HACK because System.Reflection.Emit is lame
348 if (!RegisterMethod (mb, null)) {
353 pb.SetGetMethod (mb);
357 setter_args [0] = prop_type;
359 mb = TypeBuilder.DefineMethod (
360 "set_" + ip.Name, property_attributes,
363 mb.DefineParameter (1, ParameterAttributes.None, "value");
364 pb.SetSetMethod (mb);
367 // HACK because System.Reflection.Emit is lame
369 if (!RegisterMethod (mb, setter_args)) {
375 property_builders.Add (pb);
379 // Populates the events in the interface
381 void PopulateEvent (InterfaceEvent ie)
384 // FIXME: We need to do this after delegates have been
385 // declared or we declare them recursively.
390 // Populates the indexers in the interface
392 void PopulateIndexer (InterfaceIndexer ii)
395 Type prop_type = parent.LookupType (ii.Type, true);
396 Type [] arg_types = ii.ParameterTypes (parent);
397 Type [] value_arg_types;
400 // Sets up the extra invisible `value' argument for setters.
402 if (arg_types != null){
403 int count = arg_types.Length;
404 value_arg_types = new Type [count + 1];
406 arg_types.CopyTo (value_arg_types, 0);
407 value_arg_types [count] = prop_type;
409 value_arg_types = new Type [1];
411 value_arg_types [1] = prop_type;
414 pb = TypeBuilder.DefineProperty (
415 "Item", PropertyAttributes.None,
416 prop_type, arg_types);
419 MethodBuilder get_item;
420 Parameter [] p = ii.Parameters.FixedParameters;
422 get_item = TypeBuilder.DefineMethod (
423 "get_Item", property_attributes, prop_type, arg_types);
424 pb.SetGetMethod (get_item);
426 // HACK because System.Reflection.Emit is lame
428 if (!RegisterMethod (get_item, arg_types)) {
434 for (int i = 0; i < p.Length; i++)
435 get_item.DefineParameter (
437 p [i].Attributes, p [i].Name);
442 Parameter [] p = ii.Parameters.FixedParameters;
443 MethodBuilder set_item;
446 set_item = TypeBuilder.DefineMethod (
447 "set_Item", property_attributes, null, value_arg_types);
448 pb.SetSetMethod (set_item);
450 // HACK because System.Reflection.Emit is lame
452 if (!RegisterMethod (set_item, value_arg_types)) {
458 for (; i < p.Length; i++)
459 set_item.DefineParameter (
461 p [i].Attributes, p [i].Name);
463 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
468 // Performs the semantic analysis for all the interface members
469 // that were declared
471 bool SemanticAnalysis ()
473 Hashtable methods = new Hashtable ();
476 if (defined_method != null){
477 foreach (InterfaceMethod im in defined_method){
478 string sig = im.GetSignature (parent);
481 // If there was an undefined Type on the signatures
486 if (methods [sig] != null){
494 // FIXME: Here I should check i
500 // Returns the Type that represents the interface whose name
504 Type GetInterfaceTypeByName (object builder, string name)
507 Type t = RootContext.TypeManager.LookupType (name);
517 cause = "is a struct";
519 cause = "is a class";
521 cause = "Should not happen.";
523 Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
528 Tree tree = RootContext.Tree;
529 parent = (Interface) tree.Interfaces [name];
531 string cause = "is undefined";
533 if (tree.Classes [name] != null)
534 cause = "is a class";
535 else if (tree.Structs [name] != null)
536 cause = "is a struct";
538 Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
542 t = parent.DefineInterface (builder);
545 "Inherited interface `"+name+"' is circular");
553 // Returns the list of interfaces that this interface implements
554 // Or null if it does not implement any interface.
556 // Sets the error boolean accoringly.
558 Type [] GetInterfaceBases (object builder, out bool error)
567 tbases = new Type [Bases.Count];
570 foreach (string name in Bases){
573 t = GetInterfaceTypeByName (builder, name);
587 // Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
590 // Rework the way we recurse, because for recursive
591 // definitions of interfaces (A:B and B:A) we report the
592 // error twice, rather than once.
594 public TypeBuilder DefineInterface (object parent_builder)
604 ifaces = GetInterfaceBases (parent_builder, out error);
609 if (parent_builder is ModuleBuilder) {
610 ModuleBuilder builder = (ModuleBuilder) parent_builder;
612 TypeBuilder = builder.DefineType (Name,
613 TypeAttributes.Interface |
615 TypeAttributes.Abstract,
619 TypeBuilder builder = (TypeBuilder) parent_builder;
621 TypeBuilder = builder.DefineNestedType (Name,
622 TypeAttributes.Interface |
624 TypeAttributes.Abstract,
629 RootContext.TypeManager.AddUserInterface (Name, TypeBuilder, this);
637 // Performs semantic analysis, and then generates the IL interfaces
639 public void Populate ()
641 if (!SemanticAnalysis ())
644 if (defined_method != null){
645 foreach (InterfaceMethod im in defined_method)
649 if (defined_properties != null){
650 foreach (InterfaceProperty ip in defined_properties)
651 PopulateProperty (ip);
654 if (defined_events != null)
655 foreach (InterfaceEvent ie in defined_events)
658 if (defined_indexer != null)
659 foreach (InterfaceIndexer ii in defined_indexer)
660 PopulateIndexer (ii);
663 public void CloseType ()
665 TypeBuilder.CreateType ();
670 public class InterfaceMemberBase {
671 public readonly string Name;
672 public readonly bool IsNew;
673 public Attributes OptAttributes;
675 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
679 OptAttributes = attrs;
683 public class InterfaceProperty : InterfaceMemberBase {
684 public readonly bool HasSet;
685 public readonly bool HasGet;
686 public readonly string Type;
687 public readonly string type;
689 public InterfaceProperty (string type, string name,
690 bool is_new, bool has_get, bool has_set, Attributes attrs)
691 : base (name, is_new, attrs)
699 public class InterfaceEvent : InterfaceMemberBase {
700 public readonly string Type;
702 public InterfaceEvent (string type, string name, bool is_new, Attributes attrs)
703 : base (name, is_new, attrs)
709 public class InterfaceMethod : InterfaceMemberBase {
710 public readonly string ReturnType;
711 public readonly Parameters Parameters;
713 public InterfaceMethod (string return_type, string name, bool is_new, Parameters args, Attributes attrs)
714 : base (name, is_new, attrs)
716 this.ReturnType = return_type;
717 this.Parameters = args;
721 // Returns the signature for this interface method
723 public string GetSignature (TypeContainer tc)
725 Type ret = tc.LookupType (ReturnType, false);
726 string args = Parameters.GetSignature (tc);
728 if ((ret == null) || (args == null))
731 return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
734 public Type [] ParameterTypes (TypeContainer tc)
736 return Parameters.GetParameterInfo (tc);
740 public class InterfaceIndexer : InterfaceMemberBase {
741 public readonly bool HasGet, HasSet;
742 public readonly Parameters Parameters;
743 public readonly string Type;
745 public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set, bool is_new,
747 : base ("", is_new, attrs)
755 public Type [] ParameterTypes (TypeContainer tc)
757 return Parameters.GetParameterInfo (tc);