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;
17 namespace Mono.CSharp {
22 public class Interface : DeclSpace {
23 const MethodAttributes interface_method_attributes =
24 MethodAttributes.Public |
25 MethodAttributes.Abstract |
26 MethodAttributes.HideBySig |
27 MethodAttributes.NewSlot |
28 MethodAttributes.Virtual;
30 const MethodAttributes property_attributes =
31 MethodAttributes.Public |
32 MethodAttributes.Abstract |
33 MethodAttributes.HideBySig |
34 MethodAttributes.NewSlot |
35 MethodAttributes.SpecialName |
36 MethodAttributes.Virtual;
41 ArrayList defined_method;
42 ArrayList defined_indexer;
43 ArrayList defined_events;
44 ArrayList defined_properties;
46 ArrayList method_builders;
47 ArrayList property_builders;
51 Attributes OptAttributes;
53 public readonly RootContext RootContext;
55 // These will happen after the semantic analysis
57 // Hashtable defined_indexers;
58 // Hashtable defined_methods;
61 /// Modifiers allowed in a class declaration
63 public const int AllowedModifiers =
70 public Interface (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
73 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
75 OptAttributes = attrs;
78 method_builders = new ArrayList ();
79 property_builders = new ArrayList ();
82 public AdditionResult AddMethod (InterfaceMethod imethod)
84 string name = imethod.Name;
85 Object value = defined_names [name];
88 if (!(value is InterfaceMethod))
89 return AdditionResult.NameExists;
92 if (defined_method == null)
93 defined_method = new ArrayList ();
95 defined_method.Add (imethod);
97 DefineName (name, imethod);
99 return AdditionResult.Success;
102 public AdditionResult AddProperty (InterfaceProperty iprop)
105 string name = iprop.Name;
107 if ((res = IsValid (name)) != AdditionResult.Success)
110 DefineName (name, iprop);
112 if (defined_properties == null)
113 defined_properties = new ArrayList ();
115 defined_properties.Add (iprop);
116 return AdditionResult.Success;
119 public AdditionResult AddEvent (InterfaceEvent ievent)
121 string name = ievent.Name;
124 if ((res = IsValid (name)) != AdditionResult.Success)
127 DefineName (name, ievent);
129 if (defined_events == null)
130 defined_events = new ArrayList ();
132 defined_events.Add (ievent);
133 return AdditionResult.Success;
136 public bool AddIndexer (InterfaceIndexer iindexer)
138 if (defined_indexer == null)
139 defined_indexer = new ArrayList ();
141 defined_indexer.Add (iindexer);
145 public ArrayList InterfaceMethods {
147 return defined_method;
151 public ArrayList InterfaceProperties {
153 return defined_properties;
157 public ArrayList InterfaceEvents {
159 return defined_events;
163 public ArrayList InterfaceIndexers {
165 return defined_indexer;
169 public int ModFlags {
175 public ArrayList Bases {
185 public bool IsTopLevel {
188 if (parent.Parent == null)
195 public virtual TypeAttributes InterfaceAttr {
197 TypeAttributes x = 0;
199 if ((mod_flags & Modifiers.PUBLIC) != 0)
200 x |= TypeAttributes.Public;
201 else if ((mod_flags & Modifiers.PRIVATE) != 0)
202 x |= TypeAttributes.NotPublic;
204 if (IsTopLevel == false) {
206 if ((mod_flags & Modifiers.PROTECTED) != 0
207 && (mod_flags & Modifiers.INTERNAL) != 0)
208 x |= TypeAttributes.NestedFamORAssem;
210 if ((mod_flags & Modifiers.PROTECTED) != 0)
211 x |= TypeAttributes.NestedFamily;
213 if ((mod_flags & Modifiers.INTERNAL) != 0)
214 x |= TypeAttributes.NestedAssembly;
218 if ((mod_flags & Modifiers.ABSTRACT) != 0)
219 x |= TypeAttributes.Abstract;
221 if ((mod_flags & Modifiers.SEALED) != 0)
222 x |= TypeAttributes.Sealed;
228 void Error111 (InterfaceMemberBase ib)
232 "Interface `" + Name + "' already contains a definition with the " +
233 "same return value and parameter types for member `" + ib.Name + "'");
236 bool RegisterMethod (MethodBase mb, Type [] types)
238 if (!TypeManager.RegisterMethod (mb, types))
241 method_builders.Add (mb);
245 public MethodInfo [] GetMethods ()
247 int n = method_builders.Count;
248 MethodInfo [] mi = new MethodInfo [n];
250 method_builders.CopyTo (mi, 0);
255 // Hack around System.Reflection as found everywhere else
256 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
258 ArrayList members = new ArrayList ();
260 if ((mt & MemberTypes.Method) != 0) {
261 foreach (MethodBuilder mb in method_builders)
262 if (filter (mb, criteria))
266 if ((mt & MemberTypes.Property) != 0) {
267 foreach (PropertyBuilder pb in property_builders)
268 if (filter (pb, criteria))
272 // The rest of the cases, if any, are unhandled at present.
274 int count = members.Count;
277 MemberInfo [] mi = new MemberInfo [count];
278 members.CopyTo (mi, 0);
287 // Populates the methods in the interface
289 void PopulateMethod (InterfaceMethod im)
291 Type return_type = parent.LookupType (im.ReturnType, true);
292 Type [] arg_types = im.ParameterTypes (parent);
300 mb = TypeBuilder.DefineMethod (
301 im.Name, interface_method_attributes,
302 return_type, arg_types);
304 if (!RegisterMethod (mb, arg_types)) {
310 // Define each type attribute (in/out/ref) and
311 // the argument names.
313 p = im.Parameters.FixedParameters;
315 for (i = 0; i < p.Length; i++)
316 mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
318 if (i != arg_types.Length)
319 Console.WriteLine ("Implement the type definition for params");
324 // Populates the properties in the interface
326 void PopulateProperty (InterfaceProperty ip)
330 Type prop_type = parent.LookupType (ip.Type, true);
331 Type [] setter_args = new Type [1];
333 setter_args [0] = prop_type;
336 // FIXME: properties are missing the following
337 // flags: hidebysig newslot specialname
339 pb = TypeBuilder.DefineProperty (
340 ip.Name, PropertyAttributes.None,
344 mb = TypeBuilder.DefineMethod (
345 "get_" + ip.Name, property_attributes ,
349 // HACK because System.Reflection.Emit is lame
351 if (!RegisterMethod (mb, null)) {
356 pb.SetGetMethod (mb);
360 setter_args [0] = prop_type;
362 mb = TypeBuilder.DefineMethod (
363 "set_" + ip.Name, property_attributes,
366 mb.DefineParameter (1, ParameterAttributes.None, "value");
367 pb.SetSetMethod (mb);
370 // HACK because System.Reflection.Emit is lame
372 if (!RegisterMethod (mb, setter_args)) {
378 property_builders.Add (pb);
382 // Populates the events in the interface
384 void PopulateEvent (InterfaceEvent ie)
387 // FIXME: We need to do this after delegates have been
388 // declared or we declare them recursively.
393 // Populates the indexers in the interface
395 void PopulateIndexer (InterfaceIndexer ii)
398 Type prop_type = parent.LookupType (ii.Type, true);
399 Type [] arg_types = ii.ParameterTypes (parent);
400 Type [] value_arg_types;
403 // Sets up the extra invisible `value' argument for setters.
405 if (arg_types != null){
406 int count = arg_types.Length;
407 value_arg_types = new Type [count + 1];
409 arg_types.CopyTo (value_arg_types, 0);
410 value_arg_types [count] = prop_type;
412 value_arg_types = new Type [1];
414 value_arg_types [1] = prop_type;
417 pb = TypeBuilder.DefineProperty (
418 "Item", PropertyAttributes.None,
419 prop_type, arg_types);
422 MethodBuilder get_item;
423 Parameter [] p = ii.Parameters.FixedParameters;
425 get_item = TypeBuilder.DefineMethod (
426 "get_Item", property_attributes, prop_type, arg_types);
427 pb.SetGetMethod (get_item);
429 // HACK because System.Reflection.Emit is lame
431 if (!RegisterMethod (get_item, arg_types)) {
437 for (int i = 0; i < p.Length; i++)
438 get_item.DefineParameter (
440 p [i].Attributes, p [i].Name);
445 Parameter [] p = ii.Parameters.FixedParameters;
446 MethodBuilder set_item;
449 set_item = TypeBuilder.DefineMethod (
450 "set_Item", property_attributes, null, value_arg_types);
451 pb.SetSetMethod (set_item);
453 // HACK because System.Reflection.Emit is lame
455 if (!RegisterMethod (set_item, value_arg_types)) {
461 for (; i < p.Length; i++)
462 set_item.DefineParameter (
464 p [i].Attributes, p [i].Name);
466 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
471 /// Performs the semantic analysis for all the interface members
472 /// that were declared
474 bool SemanticAnalysis ()
476 Hashtable methods = new Hashtable ();
479 if (defined_method != null){
480 foreach (InterfaceMethod im in defined_method){
481 string sig = im.GetSignature (parent);
484 // If there was an undefined Type on the signatures
489 if (methods [sig] != null){
497 // FIXME: Here I should check i
503 // Returns the Type that represents the interface whose name
507 Type GetInterfaceTypeByName (object builder, string name)
510 Type t = RootContext.TypeManager.LookupType (name);
520 cause = "is a struct";
522 cause = "is a class";
524 cause = "Should not happen.";
526 Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
531 Tree tree = RootContext.Tree;
532 parent = (Interface) tree.Interfaces [name];
534 string cause = "is undefined";
536 if (tree.Classes [name] != null)
537 cause = "is a class";
538 else if (tree.Structs [name] != null)
539 cause = "is a struct";
541 Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
545 t = parent.DefineInterface (builder);
548 "Inherited interface `"+name+"' is circular");
556 // Returns the list of interfaces that this interface implements
557 // Or null if it does not implement any interface.
559 // Sets the error boolean accoringly.
561 Type [] GetInterfaceBases (object builder, out bool error)
570 tbases = new Type [Bases.Count];
573 foreach (string name in Bases){
576 t = GetInterfaceTypeByName (builder, name);
590 // Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
593 // Rework the way we recurse, because for recursive
594 // definitions of interfaces (A:B and B:A) we report the
595 // error twice, rather than once.
597 public TypeBuilder DefineInterface (object parent_builder)
607 ifaces = GetInterfaceBases (parent_builder, out error);
612 if (parent_builder is ModuleBuilder) {
613 ModuleBuilder builder = (ModuleBuilder) parent_builder;
615 TypeBuilder = builder.DefineType (Name,
616 TypeAttributes.Interface |
618 TypeAttributes.Abstract,
622 TypeBuilder builder = (TypeBuilder) parent_builder;
624 TypeBuilder = builder.DefineNestedType (Name,
625 TypeAttributes.Interface |
627 TypeAttributes.Abstract,
632 RootContext.TypeManager.AddUserInterface (Name, TypeBuilder, this);
640 /// Performs semantic analysis, and then generates the IL interfaces
642 public void Populate ()
644 if (!SemanticAnalysis ())
647 if (defined_method != null){
648 foreach (InterfaceMethod im in defined_method)
652 if (defined_properties != null){
653 foreach (InterfaceProperty ip in defined_properties)
654 PopulateProperty (ip);
657 if (defined_events != null)
658 foreach (InterfaceEvent ie in defined_events)
661 if (defined_indexer != null)
662 foreach (InterfaceIndexer ii in defined_indexer)
663 PopulateIndexer (ii);
666 public void CloseType ()
668 TypeBuilder.CreateType ();
673 public class InterfaceMemberBase {
674 public readonly string Name;
675 public readonly bool IsNew;
676 public Attributes OptAttributes;
678 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
682 OptAttributes = attrs;
686 public class InterfaceProperty : InterfaceMemberBase {
687 public readonly bool HasSet;
688 public readonly bool HasGet;
689 public readonly string Type;
690 public readonly string type;
692 public InterfaceProperty (string type, string name,
693 bool is_new, bool has_get, bool has_set, Attributes attrs)
694 : base (name, is_new, attrs)
702 public class InterfaceEvent : InterfaceMemberBase {
703 public readonly string Type;
705 public InterfaceEvent (string type, string name, bool is_new, Attributes attrs)
706 : base (name, is_new, attrs)
712 public class InterfaceMethod : InterfaceMemberBase {
713 public readonly string ReturnType;
714 public readonly Parameters Parameters;
716 public InterfaceMethod (string return_type, string name, bool is_new, Parameters args, Attributes attrs)
717 : base (name, is_new, attrs)
719 this.ReturnType = return_type;
720 this.Parameters = args;
724 /// Returns the signature for this interface method
726 public string GetSignature (TypeContainer tc)
728 Type ret = tc.LookupType (ReturnType, false);
729 string args = Parameters.GetSignature (tc);
731 if ((ret == null) || (args == null))
734 return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
737 public Type [] ParameterTypes (TypeContainer tc)
739 return Parameters.GetParameterInfo (tc);
743 public class InterfaceIndexer : InterfaceMemberBase {
744 public readonly bool HasGet, HasSet;
745 public readonly Parameters Parameters;
746 public readonly string Type;
748 public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set, bool is_new,
750 : base ("", is_new, attrs)
758 public Type [] ParameterTypes (TypeContainer tc)
760 return Parameters.GetParameterInfo (tc);