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;
42 ArrayList method_builders;
46 Attributes OptAttributes;
48 public readonly RootContext RootContext;
50 // These will happen after the semantic analysis
52 // Hashtable defined_indexers;
53 // Hashtable defined_methods;
56 // Modifiers allowed in a class declaration
58 public const int AllowedModifiers =
65 public Interface (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
68 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PUBLIC);
70 OptAttributes = attrs;
73 method_builders = new ArrayList ();
76 public AdditionResult AddMethod (InterfaceMethod imethod)
78 string name = imethod.Name;
79 Object value = defined_names [name];
82 if (!(value is InterfaceMethod))
83 return AdditionResult.NameExists;
86 if (defined_method == null)
87 defined_method = new ArrayList ();
89 defined_method.Add (imethod);
91 DefineName (name, imethod);
93 return AdditionResult.Success;
96 public AdditionResult AddProperty (InterfaceProperty iprop)
99 string name = iprop.Name;
101 if ((res = IsValid (name)) != AdditionResult.Success)
104 DefineName (name, iprop);
106 if (defined_properties == null)
107 defined_properties = new ArrayList ();
109 defined_properties.Add (iprop);
110 return AdditionResult.Success;
113 public AdditionResult AddEvent (InterfaceEvent ievent)
115 string name = ievent.Name;
118 if ((res = IsValid (name)) != AdditionResult.Success)
121 DefineName (name, ievent);
123 if (defined_events == null)
124 defined_events = new ArrayList ();
126 defined_events.Add (ievent);
127 return AdditionResult.Success;
130 public bool AddIndexer (InterfaceIndexer iindexer)
132 if (defined_indexer == null)
133 defined_indexer = new ArrayList ();
135 defined_indexer.Add (iindexer);
139 public ArrayList InterfaceMethods {
141 return defined_method;
145 public ArrayList InterfaceProperties {
147 return defined_properties;
151 public ArrayList InterfaceEvents {
153 return defined_events;
157 public ArrayList InterfaceIndexers {
159 return defined_indexer;
163 public int ModFlags {
169 public ArrayList Bases {
179 public bool IsTopLevel {
182 if (parent.Parent == null)
189 public virtual TypeAttributes InterfaceAttr {
191 TypeAttributes x = 0;
193 if ((mod_flags & Modifiers.PUBLIC) != 0)
194 x |= TypeAttributes.Public;
195 else if ((mod_flags & Modifiers.PRIVATE) != 0)
196 x |= TypeAttributes.NotPublic;
198 if (IsTopLevel == false) {
200 if ((mod_flags & Modifiers.PROTECTED) != 0
201 && (mod_flags & Modifiers.INTERNAL) != 0)
202 x |= TypeAttributes.NestedFamORAssem;
204 if ((mod_flags & Modifiers.PROTECTED) != 0)
205 x |= TypeAttributes.NestedFamily;
207 if ((mod_flags & Modifiers.INTERNAL) != 0)
208 x |= TypeAttributes.NestedAssembly;
212 if ((mod_flags & Modifiers.ABSTRACT) != 0)
213 x |= TypeAttributes.Abstract;
215 if ((mod_flags & Modifiers.SEALED) != 0)
216 x |= TypeAttributes.Sealed;
222 void Error111 (InterfaceMethod im)
226 "Interface `" + Name + "' already contains a definition with the " +
227 "same return value and paramenter types for method `" + im.Name + "'");
230 void RegisterMethod (MethodBase mb, Type [] types)
232 TypeManager.RegisterMethod (mb, types);
233 method_builders.Add (mb);
236 public MethodInfo [] GetMethods ()
238 int n = method_builders.Count;
239 MethodInfo [] mi = new MethodInfo [n];
241 method_builders.CopyTo (mi, 0);
247 // Populates the methods in the interface
249 void PopulateMethod (InterfaceMethod im)
251 Type return_type = parent.LookupType (im.ReturnType, true);
252 Type [] arg_types = im.ParameterTypes (parent);
260 mb = TypeBuilder.DefineMethod (
261 im.Name, interface_method_attributes,
262 return_type, arg_types);
264 RegisterMethod (mb, arg_types);
267 // Define each type attribute (in/out/ref) and
268 // the argument names.
270 p = im.Parameters.FixedParameters;
272 for (i = 0; i < p.Length; i++)
273 mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
275 if (i != arg_types.Length)
276 Console.WriteLine ("Implement the type definition for params");
281 // Populates the properties in the interface
283 void PopulateProperty (InterfaceProperty ip)
287 Type prop_type = parent.LookupType (ip.Type, true);
288 Type [] setter_args = new Type [1];
290 setter_args [0] = prop_type;
293 // FIXME: properties are missing the following
294 // flags: hidebysig newslot specialname
296 pb = TypeBuilder.DefineProperty (
297 ip.Name, PropertyAttributes.None,
301 mb = TypeBuilder.DefineMethod (
302 "get_" + ip.Name, property_attributes ,
306 // HACK because System.Reflection.Emit is lame
308 RegisterMethod (mb, null);
310 pb.SetGetMethod (mb);
314 setter_args [0] = prop_type;
316 mb = TypeBuilder.DefineMethod (
317 "set_" + ip.Name, property_attributes,
320 mb.DefineParameter (1, ParameterAttributes.None, "value");
321 pb.SetSetMethod (mb);
324 // HACK because System.Reflection.Emit is lame
326 RegisterMethod (mb, setter_args);
331 // Populates the events in the interface
333 void PopulateEvent (InterfaceEvent ie)
336 // FIXME: We need to do this after delegates have been
337 // declared or we declare them recursively.
342 // Populates the indexers in the interface
344 void PopulateIndexer (InterfaceIndexer ii)
347 Type prop_type = parent.LookupType (ii.Type, true);
348 Type [] arg_types = ii.ParameterTypes (parent);
349 Type [] value_arg_types;
352 // Sets up the extra invisible `value' argument for setters.
354 if (arg_types != null){
355 int count = arg_types.Length;
356 value_arg_types = new Type [count + 1];
358 arg_types.CopyTo (value_arg_types, 0);
359 value_arg_types [count] = prop_type;
361 value_arg_types = new Type [1];
363 value_arg_types [1] = prop_type;
366 pb = TypeBuilder.DefineProperty (
367 "Item", PropertyAttributes.None,
368 prop_type, arg_types);
371 MethodBuilder get_item;
372 Parameter [] p = ii.Parameters.FixedParameters;
374 get_item = TypeBuilder.DefineMethod (
375 "get_Item", property_attributes, prop_type, arg_types);
376 pb.SetGetMethod (get_item);
378 // HACK because System.Reflection.Emit is lame
380 RegisterMethod (get_item, arg_types);
383 for (int i = 0; i < p.Length; i++)
384 get_item.DefineParameter (
386 p [i].Attributes, p [i].Name);
391 Parameter [] p = ii.Parameters.FixedParameters;
392 MethodBuilder set_item;
395 set_item = TypeBuilder.DefineMethod (
396 "set_Item", property_attributes, null, value_arg_types);
397 pb.SetSetMethod (set_item);
399 // HACK because System.Reflection.Emit is lame
401 RegisterMethod (set_item, value_arg_types);
404 for (; i < p.Length; i++)
405 set_item.DefineParameter (
407 p [i].Attributes, p [i].Name);
409 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
414 // Performs the semantic analysis for all the interface members
415 // that were declared
417 bool SemanticAnalysis ()
419 Hashtable methods = new Hashtable ();
422 if (defined_method != null){
423 foreach (InterfaceMethod im in defined_method){
424 string sig = im.GetSignature (parent);
427 // If there was an undefined Type on the signatures
432 if (methods [sig] != null){
440 // FIXME: Here I should check i
446 // Returns the Type that represents the interface whose name
450 Type GetInterfaceTypeByName (object builder, string name)
453 Type t = RootContext.TypeManager.LookupType (name);
463 cause = "is a struct";
465 cause = "is a class";
467 cause = "Should not happen.";
469 Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
474 Tree tree = RootContext.Tree;
475 parent = (Interface) tree.Interfaces [name];
477 string cause = "is undefined";
479 if (tree.Classes [name] != null)
480 cause = "is a class";
481 else if (tree.Structs [name] != null)
482 cause = "is a struct";
484 Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
488 t = parent.DefineInterface (builder);
491 "Inherited interface `"+name+"' is circular");
499 // Returns the list of interfaces that this interface implements
500 // Or null if it does not implement any interface.
502 // Sets the error boolean accoringly.
504 Type [] GetInterfaceBases (object builder, out bool error)
513 tbases = new Type [Bases.Count];
516 foreach (string name in Bases){
519 t = GetInterfaceTypeByName (builder, name);
533 // Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
536 // Rework the way we recurse, because for recursive
537 // definitions of interfaces (A:B and B:A) we report the
538 // error twice, rather than once.
540 public TypeBuilder DefineInterface (object parent_builder)
550 ifaces = GetInterfaceBases (parent_builder, out error);
555 if (parent_builder is ModuleBuilder) {
556 ModuleBuilder builder = (ModuleBuilder) parent_builder;
558 TypeBuilder = builder.DefineType (Name,
559 TypeAttributes.Interface |
561 TypeAttributes.Abstract,
565 TypeBuilder builder = (TypeBuilder) parent_builder;
567 TypeBuilder = builder.DefineNestedType (Name,
568 TypeAttributes.Interface |
570 TypeAttributes.Abstract,
575 RootContext.TypeManager.AddUserInterface (Name, TypeBuilder, this);
583 // Performs semantic analysis, and then generates the IL interfaces
585 public void Populate ()
587 if (!SemanticAnalysis ())
590 if (defined_method != null){
591 foreach (InterfaceMethod im in defined_method)
595 if (defined_properties != null){
596 foreach (InterfaceProperty ip in defined_properties)
597 PopulateProperty (ip);
600 if (defined_events != null)
601 foreach (InterfaceEvent ie in defined_events)
604 if (defined_indexer != null)
605 foreach (InterfaceIndexer ii in defined_indexer)
606 PopulateIndexer (ii);
609 public void CloseType ()
611 TypeBuilder.CreateType ();
616 public class InterfaceMemberBase {
617 public readonly string Name;
618 public readonly bool IsNew;
619 public Attributes OptAttributes;
621 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
625 OptAttributes = attrs;
629 public class InterfaceProperty : InterfaceMemberBase {
630 public readonly bool HasSet;
631 public readonly bool HasGet;
632 public readonly string Type;
633 public readonly string type;
635 public InterfaceProperty (string type, string name,
636 bool is_new, bool has_get, bool has_set, Attributes attrs)
637 : base (name, is_new, attrs)
645 public class InterfaceEvent : InterfaceMemberBase {
646 public readonly string Type;
648 public InterfaceEvent (string type, string name, bool is_new, Attributes attrs)
649 : base (name, is_new, attrs)
655 public class InterfaceMethod : InterfaceMemberBase {
656 public readonly string ReturnType;
657 public readonly Parameters Parameters;
659 public InterfaceMethod (string return_type, string name, bool is_new, Parameters args, Attributes attrs)
660 : base (name, is_new, attrs)
662 this.ReturnType = return_type;
663 this.Parameters = args;
667 // Returns the signature for this interface method
669 public string GetSignature (TypeContainer tc)
671 Type ret = tc.LookupType (ReturnType, false);
672 string args = Parameters.GetSignature (tc);
674 if ((ret == null) || (args == null))
677 return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
680 public Type [] ParameterTypes (TypeContainer tc)
682 return Parameters.GetParameterInfo (tc);
686 public class InterfaceIndexer : InterfaceMemberBase {
687 public readonly bool HasGet, HasSet;
688 public readonly Parameters Parameters;
689 public readonly string Type;
691 public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set, bool is_new,
693 : base ("", is_new, attrs)
701 public Type [] ParameterTypes (TypeContainer tc)
703 return Parameters.GetParameterInfo (tc);