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 // These will happen after the semantic analysis
50 // Hashtable defined_indexers;
51 // Hashtable defined_methods;
54 // Modifiers allowed in a class declaration
56 public const int AllowedModifiers =
63 public Interface (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
66 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PUBLIC);
68 OptAttributes = attrs;
70 method_builders = new ArrayList ();
73 public AdditionResult AddMethod (InterfaceMethod imethod)
75 string name = imethod.Name;
76 Object value = defined_names [name];
79 if (!(value is InterfaceMethod))
80 return AdditionResult.NameExists;
83 if (defined_method == null)
84 defined_method = new ArrayList ();
86 defined_method.Add (imethod);
88 DefineName (name, imethod);
90 return AdditionResult.Success;
93 public AdditionResult AddProperty (InterfaceProperty iprop)
96 string name = iprop.Name;
98 if ((res = IsValid (name)) != AdditionResult.Success)
101 DefineName (name, iprop);
103 if (defined_properties == null)
104 defined_properties = new ArrayList ();
106 defined_properties.Add (iprop);
107 return AdditionResult.Success;
110 public AdditionResult AddEvent (InterfaceEvent ievent)
112 string name = ievent.Name;
115 if ((res = IsValid (name)) != AdditionResult.Success)
118 DefineName (name, ievent);
120 if (defined_events == null)
121 defined_events = new ArrayList ();
123 defined_events.Add (ievent);
124 return AdditionResult.Success;
127 public bool AddIndexer (InterfaceIndexer iindexer)
129 if (defined_indexer == null)
130 defined_indexer = new ArrayList ();
132 defined_indexer.Add (iindexer);
136 public ArrayList InterfaceMethods {
138 return defined_method;
142 public ArrayList InterfaceProperties {
144 return defined_properties;
148 public ArrayList InterfaceEvents {
150 return defined_events;
154 public ArrayList InterfaceIndexers {
156 return defined_indexer;
160 public int ModFlags {
166 public ArrayList Bases {
176 public bool IsTopLevel {
179 if (parent.Parent == null)
186 public virtual TypeAttributes InterfaceAttr {
188 TypeAttributes x = 0;
190 if ((mod_flags & Modifiers.PUBLIC) != 0)
191 x |= TypeAttributes.Public;
192 else if ((mod_flags & Modifiers.PRIVATE) != 0)
193 x |= TypeAttributes.NotPublic;
195 if (IsTopLevel == false) {
197 if ((mod_flags & Modifiers.PROTECTED) != 0
198 && (mod_flags & Modifiers.INTERNAL) != 0)
199 x |= TypeAttributes.NestedFamORAssem;
201 if ((mod_flags & Modifiers.PROTECTED) != 0)
202 x |= TypeAttributes.NestedFamily;
204 if ((mod_flags & Modifiers.INTERNAL) != 0)
205 x |= TypeAttributes.NestedAssembly;
209 if ((mod_flags & Modifiers.ABSTRACT) != 0)
210 x |= TypeAttributes.Abstract;
212 if ((mod_flags & Modifiers.SEALED) != 0)
213 x |= TypeAttributes.Sealed;
219 void Error111 (InterfaceMethod im)
223 "Interface `" + Name + "' already contains a definition with the " +
224 "same return value and paramenter types for method `" + im.Name + "'");
227 void RegisterMethod (MethodBase mb, Type [] types)
229 TypeManager.RegisterMethod (mb, types);
230 method_builders.Add (mb);
233 public MethodInfo [] GetMethods ()
235 int n = method_builders.Count;
236 MethodInfo [] mi = new MethodInfo [n];
238 method_builders.CopyTo (mi, 0);
244 // Populates the methods in the interface
246 void PopulateMethod (InterfaceMethod im)
248 Type return_type = parent.LookupType (im.ReturnType, true);
249 Type [] arg_types = im.ParameterTypes (parent);
257 mb = TypeBuilder.DefineMethod (
258 im.Name, interface_method_attributes,
259 return_type, arg_types);
261 RegisterMethod (mb, arg_types);
264 // Define each type attribute (in/out/ref) and
265 // the argument names.
267 p = im.Parameters.FixedParameters;
269 for (i = 0; i < p.Length; i++)
270 mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
272 if (i != arg_types.Length)
273 Console.WriteLine ("Implement the type definition for params");
278 // Populates the properties in the interface
280 void PopulateProperty (InterfaceProperty ip)
284 Type prop_type = parent.LookupType (ip.Type, true);
285 Type [] setter_args = new Type [1];
287 setter_args [0] = prop_type;
290 // FIXME: properties are missing the following
291 // flags: hidebysig newslot specialname
293 pb = TypeBuilder.DefineProperty (
294 ip.Name, PropertyAttributes.None,
298 mb = TypeBuilder.DefineMethod (
299 "get_" + ip.Name, property_attributes ,
303 // HACK because System.Reflection.Emit is lame
305 RegisterMethod (mb, null);
307 pb.SetGetMethod (mb);
311 setter_args [0] = prop_type;
313 mb = TypeBuilder.DefineMethod (
314 "set_" + ip.Name, property_attributes,
317 mb.DefineParameter (1, ParameterAttributes.None, "value");
318 pb.SetSetMethod (mb);
321 // HACK because System.Reflection.Emit is lame
323 RegisterMethod (mb, setter_args);
328 // Populates the events in the interface
330 void PopulateEvent (InterfaceEvent ie)
333 // FIXME: We need to do this after delegates have been
334 // declared or we declare them recursively.
339 // Populates the indexers in the interface
341 void PopulateIndexer (InterfaceIndexer ii)
344 Type prop_type = parent.LookupType (ii.Type, true);
345 Type [] arg_types = ii.ParameterTypes (parent);
346 Type [] value_arg_types;
349 // Sets up the extra invisible `value' argument for setters.
351 if (arg_types != null){
352 int count = arg_types.Length;
353 value_arg_types = new Type [count + 1];
355 arg_types.CopyTo (value_arg_types, 0);
356 value_arg_types [count] = prop_type;
358 value_arg_types = new Type [1];
360 value_arg_types [1] = prop_type;
363 pb = TypeBuilder.DefineProperty (
364 "Item", PropertyAttributes.None,
365 prop_type, arg_types);
368 MethodBuilder get_item;
369 Parameter [] p = ii.Parameters.FixedParameters;
371 get_item = TypeBuilder.DefineMethod (
372 "get_Item", property_attributes, prop_type, arg_types);
373 pb.SetGetMethod (get_item);
375 // HACK because System.Reflection.Emit is lame
377 RegisterMethod (get_item, arg_types);
380 for (int i = 0; i < p.Length; i++)
381 get_item.DefineParameter (
383 p [i].Attributes, p [i].Name);
388 Parameter [] p = ii.Parameters.FixedParameters;
389 MethodBuilder set_item;
392 set_item = TypeBuilder.DefineMethod (
393 "set_Item", property_attributes, null, value_arg_types);
394 pb.SetSetMethod (set_item);
396 // HACK because System.Reflection.Emit is lame
398 RegisterMethod (set_item, value_arg_types);
401 for (; i < p.Length; i++)
402 set_item.DefineParameter (
404 p [i].Attributes, p [i].Name);
406 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
411 // Performs the semantic analysis for all the interface members
412 // that were declared
414 bool SemanticAnalysis ()
416 Hashtable methods = new Hashtable ();
419 if (defined_method != null){
420 foreach (InterfaceMethod im in defined_method){
421 string sig = im.GetSignature (parent);
424 // If there was an undefined Type on the signatures
429 if (methods [sig] != null){
437 // FIXME: Here I should check i
443 // Performs semantic analysis, and then generates the IL interfaces
445 public void Populate ()
447 if (!SemanticAnalysis ())
450 if (defined_method != null){
451 foreach (InterfaceMethod im in defined_method)
455 if (defined_properties != null){
456 foreach (InterfaceProperty ip in defined_properties)
457 PopulateProperty (ip);
460 if (defined_events != null)
461 foreach (InterfaceEvent ie in defined_events)
464 if (defined_indexer != null)
465 foreach (InterfaceIndexer ii in defined_indexer)
466 PopulateIndexer (ii);
470 public class InterfaceMemberBase {
471 public readonly string Name;
472 public readonly bool IsNew;
473 public Attributes OptAttributes;
475 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
479 OptAttributes = attrs;
483 public class InterfaceProperty : InterfaceMemberBase {
484 public readonly bool HasSet;
485 public readonly bool HasGet;
486 public readonly string Type;
487 public readonly string type;
489 public InterfaceProperty (string type, string name,
490 bool is_new, bool has_get, bool has_set, Attributes attrs)
491 : base (name, is_new, attrs)
499 public class InterfaceEvent : InterfaceMemberBase {
500 public readonly string Type;
502 public InterfaceEvent (string type, string name, bool is_new, Attributes attrs)
503 : base (name, is_new, attrs)
509 public class InterfaceMethod : InterfaceMemberBase {
510 public readonly string ReturnType;
511 public readonly Parameters Parameters;
513 public InterfaceMethod (string return_type, string name, bool is_new, Parameters args, Attributes attrs)
514 : base (name, is_new, attrs)
516 this.ReturnType = return_type;
517 this.Parameters = args;
521 // Returns the signature for this interface method
523 public string GetSignature (TypeContainer tc)
525 Type ret = tc.LookupType (ReturnType, false);
526 string args = Parameters.GetSignature (tc);
528 if ((ret == null) || (args == null))
531 return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
534 public Type [] ParameterTypes (TypeContainer tc)
536 return Parameters.GetParameterInfo (tc);
540 public class InterfaceIndexer : InterfaceMemberBase {
541 public readonly bool HasGet, HasSet;
542 public readonly Parameters Parameters;
543 public readonly string Type;
545 public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set, bool is_new,
547 : base ("", is_new, attrs)
555 public Type [] ParameterTypes (TypeContainer tc)
557 return Parameters.GetParameterInfo (tc);