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;
45 Attributes OptAttributes;
47 // These will happen after the semantic analysis
49 // Hashtable defined_indexers;
50 // Hashtable defined_methods;
53 // Modifiers allowed in a class declaration
55 public const int AllowedModifiers =
62 public Interface (TypeContainer parent, string name, int mod, Attributes attrs) : base (name)
64 this.mod_flags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PUBLIC);
66 OptAttributes = attrs;
69 public AdditionResult AddMethod (InterfaceMethod imethod)
71 string name = imethod.Name;
72 Object value = defined_names [name];
75 if (!(value is InterfaceMethod))
76 return AdditionResult.NameExists;
79 if (defined_method == null)
80 defined_method = new ArrayList ();
82 defined_method.Add (imethod);
84 DefineName (name, imethod);
86 return AdditionResult.Success;
89 public AdditionResult AddProperty (InterfaceProperty iprop)
92 string name = iprop.Name;
94 if ((res = IsValid (name)) != AdditionResult.Success)
97 DefineName (name, iprop);
99 if (defined_properties == null)
100 defined_properties = new ArrayList ();
102 defined_properties.Add (iprop);
103 return AdditionResult.Success;
106 public AdditionResult AddEvent (InterfaceEvent ievent)
108 string name = ievent.Name;
111 if ((res = IsValid (name)) != AdditionResult.Success)
114 DefineName (name, ievent);
116 if (defined_events == null)
117 defined_events = new ArrayList ();
119 defined_events.Add (ievent);
120 return AdditionResult.Success;
123 public bool AddIndexer (InterfaceIndexer iindexer)
125 if (defined_indexer == null)
126 defined_indexer = new ArrayList ();
128 defined_indexer.Add (iindexer);
132 public ArrayList InterfaceMethods {
134 return defined_method;
138 public ArrayList InterfaceProperties {
140 return defined_properties;
144 public ArrayList InterfaceEvents {
146 return defined_events;
150 public ArrayList InterfaceIndexers {
152 return defined_indexer;
156 public int ModFlags {
162 public ArrayList Bases {
172 public bool IsTopLevel {
175 if (parent.Parent == null)
182 public virtual TypeAttributes InterfaceAttr {
184 TypeAttributes x = 0;
186 if ((mod_flags & Modifiers.PUBLIC) != 0)
187 x |= TypeAttributes.Public;
189 if ((mod_flags & Modifiers.PRIVATE) != 0)
190 x |= TypeAttributes.NotPublic;
192 if (IsTopLevel == false) {
194 if ((mod_flags & Modifiers.PROTECTED) != 0
195 && (mod_flags & Modifiers.INTERNAL) != 0)
196 x |= TypeAttributes.NestedFamORAssem;
198 if ((mod_flags & Modifiers.PROTECTED) != 0)
199 x |= TypeAttributes.NestedFamily;
201 if ((mod_flags & Modifiers.INTERNAL) != 0)
202 x |= TypeAttributes.NestedAssembly;
206 if ((mod_flags & Modifiers.ABSTRACT) != 0)
207 x |= TypeAttributes.Abstract;
209 if ((mod_flags & Modifiers.SEALED) != 0)
210 x |= TypeAttributes.Sealed;
216 void Error111 (InterfaceMethod im)
218 parent.RootContext.Report.Error (
220 "Interface `" + Name + "' already contains a definition with the " +
221 "same return value and paramenter types for method `" + im.Name + "'");
225 // Populates the methods in the interface
227 void PopulateMethod (InterfaceMethod im)
229 Type return_type = parent.LookupType (im.ReturnType, true);
230 Type [] arg_types = im.ParameterTypes (parent);
238 mb = TypeBuilder.DefineMethod (
239 im.Name, interface_method_attributes,
240 return_type, arg_types);
243 // Define each type attribute (in/out/ref) and
244 // the argument names.
246 p = im.Parameters.FixedParameters;
248 for (i = 0; i < p.Length; i++)
249 mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
251 if (i != arg_types.Length)
252 Console.WriteLine ("Implement the type definition for params");
257 // Populates the properties in the interface
259 void PopulateProperty (InterfaceProperty ip)
263 Type prop_type = parent.LookupType (ip.Type, true);
264 Type [] setter_args = new Type [1];
266 setter_args [0] = prop_type;
269 // FIXME: properties are missing the following
270 // flags: hidebysig newslot specialname
272 pb = TypeBuilder.DefineProperty (
273 ip.Name, PropertyAttributes.None,
277 mb = TypeBuilder.DefineMethod (
278 "get_" + ip.Name, property_attributes ,
281 pb.SetGetMethod (mb);
285 setter_args [0] = prop_type;
287 mb = TypeBuilder.DefineMethod (
288 "set_" + ip.Name, property_attributes,
291 mb.DefineParameter (1, ParameterAttributes.None, "value");
292 pb.SetSetMethod (mb);
297 // Populates the events in the interface
299 void PopulateEvent (InterfaceEvent ie)
302 // FIXME: We need to do this after delegates have been
303 // declared or we declare them recursively.
308 // Populates the indexers in the interface
310 void PopulateIndexer (InterfaceIndexer ii)
313 Type prop_type = parent.LookupType (ii.Type, true);
314 Type [] arg_types = ii.ParameterTypes (parent);
315 Type [] value_arg_types;
318 // Sets up the extra invisible `value' argument for setters.
320 if (arg_types != null){
321 int count = arg_types.Length;
322 value_arg_types = new Type [count + 1];
324 arg_types.CopyTo (value_arg_types, 0);
325 value_arg_types [count] = prop_type;
327 value_arg_types = new Type [1];
329 value_arg_types [1] = prop_type;
332 pb = TypeBuilder.DefineProperty (
333 "Item", PropertyAttributes.None,
334 prop_type, arg_types);
337 MethodBuilder get_item;
338 Parameter [] p = ii.Parameters.FixedParameters;
340 get_item = TypeBuilder.DefineMethod (
341 "get_Item", property_attributes, prop_type, arg_types);
342 pb.SetGetMethod (get_item);
345 for (int i = 0; i < p.Length; i++)
346 get_item.DefineParameter (
348 p [i].Attributes, p [i].Name);
353 Parameter [] p = ii.Parameters.FixedParameters;
354 MethodBuilder set_item;
357 set_item = TypeBuilder.DefineMethod (
358 "set_Item", property_attributes, null, value_arg_types);
359 pb.SetSetMethod (set_item);
362 for (; i < p.Length; i++)
363 set_item.DefineParameter (
365 p [i].Attributes, p [i].Name);
367 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
372 // Performs the semantic analysis for all the interface members
373 // that were declared
375 bool SemanticAnalysis ()
377 Hashtable methods = new Hashtable ();
380 if (defined_method != null){
381 foreach (InterfaceMethod im in defined_method){
382 string sig = im.GetSignature (parent);
385 // If there was an undefined Type on the signatures
390 if (methods [sig] != null){
398 // FIXME: Here I should check i
404 // Performs semantic analysis, and then generates the IL interfaces
406 public void Populate ()
408 if (!SemanticAnalysis ())
411 if (defined_method != null){
412 foreach (InterfaceMethod im in defined_method)
416 if (defined_properties != null){
417 foreach (InterfaceProperty ip in defined_properties)
418 PopulateProperty (ip);
421 if (defined_events != null)
422 foreach (InterfaceEvent ie in defined_events)
425 if (defined_indexer != null)
426 foreach (InterfaceIndexer ii in defined_indexer)
427 PopulateIndexer (ii);
431 public class InterfaceMemberBase {
432 public readonly string Name;
433 public readonly bool IsNew;
434 public Attributes OptAttributes;
436 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
440 OptAttributes = attrs;
444 public class InterfaceProperty : InterfaceMemberBase {
445 public readonly bool HasSet;
446 public readonly bool HasGet;
447 public readonly string Type;
448 public readonly string type;
450 public InterfaceProperty (string type, string name,
451 bool is_new, bool has_get, bool has_set, Attributes attrs)
452 : base (name, is_new, attrs)
460 public class InterfaceEvent : InterfaceMemberBase {
461 public readonly string Type;
463 public InterfaceEvent (string type, string name, bool is_new, Attributes attrs)
464 : base (name, is_new, attrs)
470 public class InterfaceMethod : InterfaceMemberBase {
471 public readonly string ReturnType;
472 public readonly Parameters Parameters;
474 public InterfaceMethod (string return_type, string name, bool is_new, Parameters args, Attributes attrs)
475 : base (name, is_new, attrs)
477 this.ReturnType = return_type;
478 this.Parameters = args;
482 // Returns the signature for this interface method
484 public string GetSignature (TypeContainer tc)
486 Type ret = tc.LookupType (ReturnType, false);
487 string args = Parameters.GetSignature (tc);
489 if ((ret == null) || (args == null))
492 return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
495 public Type [] ParameterTypes (TypeContainer tc)
497 return Parameters.GetParameterInfo (tc);
501 public class InterfaceIndexer : InterfaceMemberBase {
502 public readonly bool HasGet, HasSet;
503 public readonly Parameters Parameters;
504 public readonly string Type;
506 public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set, bool is_new,
508 : base ("", is_new, attrs)
516 public Type [] ParameterTypes (TypeContainer tc)
518 return Parameters.GetParameterInfo (tc);