Merge from main branch
[mono.git] / mcs / gmcs / interface.cs
1 //
2 // interface.cs: Interface handler
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 #define CACHE
11 using System.Collections;
12 using System;
13 using System.IO;
14 using System.Reflection;
15 using System.Reflection.Emit;
16
17 namespace Mono.CSharp {
18
19         /// <summary>
20         ///   Interfaces
21         /// </summary>
22         public class Interface : DeclSpace, IMemberContainer {
23                 const MethodAttributes interface_method_attributes =
24                         MethodAttributes.Public |
25                         MethodAttributes.Abstract |
26                         MethodAttributes.HideBySig |
27                         MethodAttributes.NewSlot |
28                         MethodAttributes.Virtual;
29
30                 const MethodAttributes property_attributes =
31                         MethodAttributes.Public |
32                         MethodAttributes.Abstract |
33                         MethodAttributes.HideBySig |
34                         MethodAttributes.NewSlot |
35                         MethodAttributes.SpecialName |
36                         MethodAttributes.Virtual;
37                 
38                 ArrayList bases;
39                 
40                 ArrayList defined_method;
41                 ArrayList defined_indexer;
42                 ArrayList defined_events;
43                 ArrayList defined_properties;
44
45                 ArrayList method_builders;
46                 ArrayList property_builders;
47                 ArrayList event_builders;
48                 
49                 Attributes OptAttributes;
50
51                 public string IndexerName;
52
53                 IMemberContainer parent_container;
54                 MemberCache member_cache;
55
56                 bool members_defined;
57
58                 // These will happen after the semantic analysis
59                 
60                 // Hashtable defined_indexers;
61                 // Hashtable defined_methods;
62                 
63                 /// <summary>
64                 ///   Modifiers allowed in a class declaration
65                 /// </summary>
66                 public const int AllowedModifiers =
67                         Modifiers.NEW       |
68                         Modifiers.PUBLIC    |
69                         Modifiers.PROTECTED |
70                         Modifiers.INTERNAL  |
71                         Modifiers.UNSAFE    |
72                         Modifiers.PRIVATE;
73
74                 public Interface (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
75                         : base (parent, name, l)
76                 {
77                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
78                         OptAttributes = attrs;
79                         
80                         method_builders = new ArrayList ();
81                         property_builders = new ArrayList ();
82                         event_builders = new ArrayList ();
83                 }
84
85                 public AdditionResult AddMethod (InterfaceMethod imethod)
86                 {
87                         string name = imethod.Name;
88                         Object value = defined_names [name];
89
90                         if (value != null){
91                                 if (!(value is InterfaceMethod))
92                                         return AdditionResult.NameExists;
93                         } 
94
95                         if (defined_method == null)
96                                 defined_method = new ArrayList ();
97
98                         defined_method.Add (imethod);
99                         if (value == null)
100                                 DefineName (name, imethod);
101                         
102                         return AdditionResult.Success;
103                 }
104
105                 public AdditionResult AddProperty (InterfaceProperty iprop)
106                 {
107                         AdditionResult res;
108                         string name = iprop.Name;
109
110                         if ((res = IsValid (name, name)) != AdditionResult.Success)
111                                 return res;
112
113                         DefineName (name, iprop);
114
115                         if (defined_properties == null)
116                                 defined_properties = new ArrayList ();
117
118                         defined_properties.Add (iprop);
119                         return AdditionResult.Success;
120                 }
121
122                 public AdditionResult AddEvent (InterfaceEvent ievent)
123                 {
124                         string name = ievent.Name;
125                         AdditionResult res;
126                         
127                         if ((res = IsValid (name, name)) != AdditionResult.Success)
128                                 return res;
129
130                         DefineName (name, ievent);
131
132                         if (defined_events == null)
133                                 defined_events = new ArrayList ();
134
135                         defined_events.Add (ievent);
136                         return AdditionResult.Success;
137                 }
138
139                 public bool AddIndexer (InterfaceIndexer iindexer)
140                 {
141                         if (defined_indexer == null)
142                                 defined_indexer = new ArrayList ();
143                         
144                         defined_indexer.Add (iindexer);
145                         return true;
146                 }
147                 
148                 public ArrayList InterfaceMethods {
149                         get {
150                                 return defined_method;
151                         }
152                 }
153
154                 public ArrayList InterfaceProperties {
155                         get {
156                                 return defined_properties;
157                         }
158                 }
159
160                 public ArrayList InterfaceEvents {
161                         get {
162                                 return defined_events;
163                         }
164                 }
165
166                 public ArrayList InterfaceIndexers {
167                         get {
168                                 return defined_indexer;
169                         }
170                 }
171
172                 public ArrayList Bases {
173                         get {
174                                 return bases;
175                         }
176
177                         set {
178                                 bases = value;
179                         }
180                 }
181
182                 public virtual TypeAttributes InterfaceAttr {
183                         get {
184                                 TypeAttributes x = TypeAttributes.Interface | TypeAttributes.Abstract;
185
186                                 if (IsTopLevel == false) {
187                                         
188                                         if ((ModFlags & Modifiers.PROTECTED) != 0
189                                             && (ModFlags & Modifiers.INTERNAL) != 0)
190                                                 x |= TypeAttributes.NestedFamORAssem;
191                                         else if ((ModFlags & Modifiers.PROTECTED) != 0)
192                                                 x |= TypeAttributes.NestedFamily;
193                                         else if ((ModFlags & Modifiers.INTERNAL) != 0)
194                                                 x |= TypeAttributes.NestedAssembly;
195                                         else if ((ModFlags & Modifiers.PUBLIC) != 0)
196                                                 x |= TypeAttributes.NestedPublic;
197                                         else
198                                                 x |= TypeAttributes.NestedPrivate;
199                                 } else {
200                                         if ((ModFlags & Modifiers.PUBLIC) != 0)
201                                                 x |= TypeAttributes.Public;
202                                         else if ((ModFlags & Modifiers.PRIVATE) != 0)
203                                                 x |= TypeAttributes.NotPublic;
204                                 }
205                                 
206                                 if ((ModFlags & Modifiers.ABSTRACT) != 0)
207                                         x |= TypeAttributes.Abstract;
208                                 
209                                 if ((ModFlags & Modifiers.SEALED) != 0)
210                                         x |= TypeAttributes.Sealed;
211
212                                 return x;
213                         }
214                 }
215                 
216                 void Error111 (InterfaceMemberBase ib)
217                 {
218                         Report.Error (
219                                 111,
220                                 "Interface `" + Name + "' already contains a definition with the " +
221                                 "same return value and parameter types for member `" + ib.Name + "'");
222                 }
223
224                 bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] types)
225                 {
226                         if (!TypeManager.RegisterMethod (mb, ip, types))
227                                 return false;
228
229                         method_builders.Add (mb);
230                         return true;
231                 }
232
233                 //
234                 // This might trigger a definition of the methods.  This happens only
235                 // with Attributes, as Attribute classes are processed before interfaces.
236                 // Ideally, we should make everything just define recursively in terms
237                 // of its dependencies.
238                 //
239                 public MethodInfo [] GetMethods (TypeContainer container)
240                 {
241                         int n = 0;
242                         
243                         if (!members_defined){
244                                 if (DefineMembers (container))
245                                         n = method_builders.Count;
246                         } else
247                                 n = method_builders.Count;
248                         
249                         MethodInfo [] mi = new MethodInfo [n];
250                         
251                         method_builders.CopyTo (mi, 0);
252
253                         return mi;
254                 }
255
256                 // Hack around System.Reflection as found everywhere else
257                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
258                                                         MemberFilter filter, object criteria)
259                 {
260                         ArrayList members = new ArrayList ();
261
262                         if ((mt & MemberTypes.Method) != 0) {
263                                 foreach (MethodBuilder mb in method_builders)
264                                         if (filter (mb, criteria))
265                                                 members.Add (mb);
266                         }
267
268                         if ((mt & MemberTypes.Property) != 0) {
269                                 foreach (PropertyBuilder pb in property_builders)
270                                         if (filter (pb, criteria))
271                                                 members.Add (pb);
272                         }
273
274                         if ((mt & MemberTypes.Event) != 0) {
275                                 foreach (MyEventBuilder eb in event_builders)
276                                         if (filter (eb, criteria))
277                                                 members.Add (eb);
278                         }
279
280                         if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
281                                 MemberList parent_mi;
282                                 
283                                 parent_mi = TypeContainer.FindMembers (
284                                         TypeBuilder.BaseType, mt, bf, filter, criteria);
285
286                                 members.AddRange (parent_mi);
287                         }
288
289                         return new MemberList (members);
290                 }
291
292                 public override MemberCache MemberCache {
293                         get {
294                                 return member_cache;
295                         }
296                 }
297
298                 //
299                 // Populates the methods in the interface
300                 //
301                 void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im)
302                 {
303                         Type return_type = im.ReturnType.Type;
304                         if (return_type == null)
305                                 return_type = this.ResolveType (im.ReturnType, false, im.Location);
306                         
307                         Type [] arg_types = im.ParameterTypes (this);
308                         MethodBuilder mb;
309                         Parameter [] p;
310                         int i;
311
312                         if (return_type == null)
313                                 return;
314
315                         if (return_type.IsPointer && !UnsafeOK (this))
316                                 return;
317
318                         if (arg_types == null)
319                                 return;
320
321                         foreach (Type t in arg_types){
322
323                                 if (t == null)
324                                         return;
325                                 
326                                 if (t.IsPointer && !UnsafeOK (this))
327                                         return;
328                         }
329                         
330                         //
331                         // Create the method
332                         //
333                         mb = TypeBuilder.DefineMethod (
334                                 im.Name, interface_method_attributes,
335                                 return_type, arg_types);
336
337                         InternalParameters ip = new InternalParameters (arg_types, im.Parameters);
338
339                         if (!RegisterMethod (mb, ip, arg_types)) {
340                                 Error111 (im);
341                                 return;
342                         }
343
344                         //
345                         // Define each type attribute (in/out/ref) and
346                         // the argument names.
347                         //
348                         p = im.Parameters.FixedParameters;
349                         if (p != null){
350                                 for (i = 0; i < p.Length; i++)
351                                         mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
352
353                                 if (i != arg_types.Length)
354                                         Console.WriteLine ("Implement the type definition for params");
355                         }
356
357                         im.Builder = mb;
358                         
359                 }
360
361                 //
362                 // Populates the properties in the interface
363                 //
364                 void PopulateProperty (TypeContainer parent, DeclSpace decl_space, InterfaceProperty ip)
365                 {
366                         PropertyBuilder pb;
367                         MethodBuilder get = null, set = null;
368                         ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
369                         if (ip.Type == null)
370                                 return;
371                         
372                         Type prop_type = ip.Type.Type;
373                         Type [] setter_args = new Type [1];
374
375                         if (prop_type == null)
376                                 return;
377
378                         if (prop_type.IsPointer && !UnsafeOK (this))
379                                 return;
380                         
381                         setter_args [0] = prop_type;
382
383                         //
384                         // FIXME: properties are missing the following
385                         // flags: hidebysig newslot specialname
386                         //
387                         pb = TypeBuilder.DefineProperty (
388                                 ip.Name, PropertyAttributes.None,
389                                 prop_type, null);
390
391                         if (ip.HasGet){
392                                 get = TypeBuilder.DefineMethod (
393                                         "get_" + ip.Name, property_attributes ,
394                                         prop_type, null);
395
396                                 //
397                                 // HACK because System.Reflection.Emit is lame
398                                 //
399                                 Type [] null_types = null;
400                                 InternalParameters inp = new InternalParameters
401                                         (null_types, Parameters.EmptyReadOnlyParameters);
402                                 
403                                 if (!RegisterMethod (get, inp, null)) {
404                                         Error111 (ip);
405                                         return;
406                                 }
407                                 
408                                 pb.SetGetMethod (get);
409                         }
410
411                         if (ip.HasSet){
412                                 setter_args [0] = prop_type;
413
414                                 set = TypeBuilder.DefineMethod (
415                                         "set_" + ip.Name, property_attributes,
416                                         TypeManager.void_type, setter_args);
417
418                                 set.DefineParameter (1, ParameterAttributes.None, "value");
419                                 pb.SetSetMethod (set);
420
421                                 //
422                                 // HACK because System.Reflection.Emit is lame
423                                 //
424                                 Parameter [] parms = new Parameter [1];
425                                 parms [0] = new Parameter (ip.Type, "value", Parameter.Modifier.NONE, null);
426                                 InternalParameters ipp = new InternalParameters (
427                                         this, new Parameters (parms, null, Location.Null));
428                                         
429                                 if (!RegisterMethod (set, ipp, setter_args)) {
430                                         Error111 (ip);
431                                         return;
432                                 }
433                         }
434
435                         TypeManager.RegisterProperty (pb, get, set);
436                         property_builders.Add (pb);
437                         ip.Builder = pb;
438                 }
439
440                 //
441                 // Populates the events in the interface
442                 //
443                 void PopulateEvent (TypeContainer parent, DeclSpace decl_space, InterfaceEvent ie)
444                 {
445                         //
446                         // FIXME: We need to do this after delegates have been
447                         // declared or we declare them recursively.
448                         //
449                         MyEventBuilder eb;
450                         MethodBuilder add = null, remove = null;
451                         ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
452                         if (ie.Type == null)
453                                 return;
454                         
455                         Type event_type = ie.Type.Type;
456
457                         if (event_type == null)
458                                 return;
459
460                         if (event_type.IsPointer && !UnsafeOK (this))
461                                 return;
462
463                         Type [] parameters = new Type [1];
464                         parameters [0] = event_type;
465
466                         eb = new MyEventBuilder (null, TypeBuilder, ie.Name,
467                                                  EventAttributes.None, event_type);
468
469                         //
470                         // Now define the accessors
471                         //
472                         string add_name = "add_" + ie.Name;
473                         
474                         add = TypeBuilder.DefineMethod (
475                                 add_name, property_attributes, null, parameters);
476                         add.DefineParameter (1, ParameterAttributes.None, "value");
477                         eb.SetAddOnMethod (add);
478
479                         string remove_name = "remove_" + ie.Name;
480                         remove = TypeBuilder.DefineMethod (
481                                 remove_name, property_attributes, null, parameters);
482                         remove.DefineParameter (1, ParameterAttributes.None, "value");
483                         eb.SetRemoveOnMethod (remove);
484
485                         Parameter [] parms = new Parameter [1];
486                         parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null);
487                         InternalParameters ip = new InternalParameters (
488                                 this, new Parameters (parms, null, Location.Null));
489
490                         if (!RegisterMethod (add, ip, parameters)) {
491                                 Error111 (ie);
492                                 return;
493                         }
494                         
495                         if (!RegisterMethod (remove, ip, parameters)) {
496                                 Error111 (ie);
497                                 return;
498                         }
499
500                         TypeManager.RegisterEvent (eb, add, remove);
501                         event_builders.Add (eb);
502
503                         ie.Builder = eb;
504                 }
505
506                 //
507                 // Populates the indexers in the interface
508                 //
509                 void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii)
510                 {
511                         PropertyBuilder pb;
512                         ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
513                         if (ii.Type == null)
514                                 return;
515                         
516                         Type prop_type = ii.Type.Type;
517                         Type [] arg_types = ii.ParameterTypes (this);
518                         Type [] value_arg_types;
519
520                         if (prop_type == null)
521                                 return;
522
523                         if (prop_type.IsPointer && !UnsafeOK (this))
524                                 return;
525                         
526                         //
527                         // Sets up the extra invisible `value' argument for setters.
528                         // 
529                         if (arg_types != null){
530                                 int count = arg_types.Length;
531                                 value_arg_types = new Type [count + 1];
532
533                                 arg_types.CopyTo (value_arg_types, 0);
534                                 value_arg_types [count] = prop_type;
535
536                                 foreach (Type t in arg_types){
537                                         if (t.IsPointer && !UnsafeOK (this))
538                                                 return;
539                                 }
540                         } else {
541                                 value_arg_types = new Type [1];
542
543                                 value_arg_types [1] = prop_type;
544                         }
545
546                         EmitContext ec = new EmitContext (parent, decl_space, Location, null,
547                                                           null, ModFlags, false);
548
549                         IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes);
550                         if (IndexerName == null)
551                                 IndexerName = "Item";
552                         
553                         pb = TypeBuilder.DefineProperty (
554                                 IndexerName, PropertyAttributes.None,
555                                 prop_type, arg_types);
556                         
557                         MethodBuilder set_item = null, get_item = null;
558                         if (ii.HasGet){
559                                 Parameter [] p = ii.Parameters.FixedParameters;
560                                 
561                                 get_item = TypeBuilder.DefineMethod (
562                                         "get_" + IndexerName, property_attributes,
563                                         prop_type, arg_types);
564                                 pb.SetGetMethod (get_item);
565                                 //
566                                 // HACK because System.Reflection.Emit is lame
567                                 //
568                                 InternalParameters ip = new InternalParameters (
569                                         arg_types, ii.Parameters);
570                                 
571                                 if (!RegisterMethod (get_item, ip, arg_types)) {
572                                         Error111 (ii);
573                                         return;
574                                 }
575
576                                 if (p != null){
577                                         for (int i = 0; i < p.Length; i++)
578                                                 get_item.DefineParameter (
579                                                         i + 1,
580                                                         p [i].Attributes, p [i].Name);
581                                 }
582                         }
583
584                         if (ii.HasSet){
585                                 Parameter [] p = ii.Parameters.FixedParameters;
586                                 Parameter [] pv;
587                                 int i = 0;
588                                 
589                                 pv = new Parameter [p.Length + 1];
590                                 p.CopyTo (pv, 0);
591                                 pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null);
592                                 Parameters value_params = new Parameters (pv, null, Location.Null);
593                                 value_params.GetParameterInfo (decl_space);
594                                 
595                                 set_item = TypeBuilder.DefineMethod (
596                                         "set_" + IndexerName, property_attributes,
597                                         TypeManager.void_type, value_arg_types);
598                                 pb.SetSetMethod (set_item);
599                                 //
600                                 // HACK because System.Reflection.Emit is lame
601                                 //
602                                 InternalParameters ip = new InternalParameters (
603                                         value_arg_types, value_params);
604                                 if (!RegisterMethod (set_item, ip, value_arg_types)) {
605                                         Error111 (ii);
606                                         return;
607                                 }
608
609                                 if (p != null){
610                                         for (; i < p.Length; i++)
611                                                 set_item.DefineParameter (
612                                                         i + 1,
613                                                         p [i].Attributes, p [i].Name);
614                                 }
615                                 
616                                 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
617                         }
618
619                         property_builders.Add (pb);
620
621                         ii.Builder = pb;
622                 }
623
624                 /// <summary>
625                 ///   Performs the semantic analysis for all the interface members
626                 ///   that were declared
627                 /// </summary>
628                 bool SemanticAnalysis ()
629                 {
630                         Hashtable methods = new Hashtable ();
631
632                         
633                         if (defined_method != null){
634                                 foreach (InterfaceMethod im in defined_method){
635                                         string sig = im.GetSignature (this);
636                                         
637                                         //
638                                         // If there was an undefined Type on the signatures
639                                         // 
640                                         if (sig == null)
641                                                 continue;
642                                         
643                                         if (methods [sig] != null){
644                                                 Error111 (im);
645                                                 return false;
646                                         }
647                                 }
648                         }
649
650                         //
651                         // FIXME: Here I should check i
652                         // 
653                         return true;
654                 }
655
656                 Type GetInterfaceTypeByName (Expression name)
657                 {
658                         Expression original = name;
659                         name = ResolveTypeExpr (name, false, Location);
660                         if (name == null)
661                                 return null;
662
663                         Type t = name.Type;
664                         
665                         if (t.IsInterface)
666                                 return t;
667                                 
668                         string cause;
669                         
670                         if (t.IsValueType)
671                                 cause = "is a struct";
672                         else if (t.IsClass) 
673                                 cause = "is a class";
674                         else
675                                 cause = "Should not happen.";
676                         
677                         Report.Error (527, Location, "`"+name+"' " + cause +
678                                       ", need an interface instead");
679                         
680                         return null;
681                 }
682                 
683                 //
684                 // Returns the list of interfaces that this interface implements
685                 // Or null if it does not implement any interface.
686                 //
687                 // Sets the error boolean accoringly.
688                 //
689                 Type [] GetInterfaceBases (out bool error)
690                 {
691                         Type [] tbases;
692                         int i;
693
694                         error = false;
695                         if (Bases == null)
696                                 return null;
697                         
698                         tbases = new Type [Bases.Count];
699                         i = 0;
700
701                         foreach (Expression name in Bases){
702                                 Type t;
703
704                                 t = GetInterfaceTypeByName (name);
705                                 if (t == null){
706                                         error = true;
707                                         return null;
708                                 }
709
710                                 if (!Parent.AsAccessible (t, ModFlags))
711                                         Report.Error (61, Location,
712                                                       "Inconsistent accessibility: base interface `" +
713                                                       TypeManager.CSharpName (t) + "' is less " +
714                                                       "accessible than interface `" +
715                                                       Name + "'");
716
717                                 tbases [i++] = t;
718                         }
719                         
720                         return TypeManager.ExpandInterfaces (tbases);
721                 }
722                 
723                 //
724                 // <summary>
725                 //  Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
726                 // </summary>
727                 //
728                 // TODO:
729                 //   Rework the way we recurse, because for recursive
730                 //   definitions of interfaces (A:B and B:A) we report the
731                 //   error twice, rather than once.  
732                 
733                 public override TypeBuilder DefineType ()
734                 {
735                         Type [] ifaces;
736                         bool error;
737
738                         if (TypeBuilder != null)
739                                 return TypeBuilder;
740                         
741                         if (InTransit)
742                                 return null;
743                         
744                         InTransit = true;
745                         
746                         ifaces = GetInterfaceBases (out error);
747
748                         if (error)
749                                 return null;
750
751                         if (IsTopLevel) {
752                                 if (TypeManager.NamespaceClash (Name, Location))
753                                         return null;
754                                 
755                                 ModuleBuilder builder = CodeGen.ModuleBuilder;
756
757                                 TypeBuilder = builder.DefineType (
758                                         Name,
759                                         InterfaceAttr,
760                                         (Type)null,   // Parent Type
761                                         ifaces);
762                                 RootContext.RegisterOrder (this);
763                         } else {
764                                 TypeBuilder builder = Parent.TypeBuilder;
765
766                                 TypeBuilder = builder.DefineNestedType (
767                                         Basename,
768                                         InterfaceAttr,
769                                         (Type) null, //parent type
770                                         ifaces);
771
772                                 TypeContainer tc = TypeManager.LookupTypeContainer (builder);
773                                 tc.RegisterOrder (this);
774                         }
775
776                         TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
777                         InTransit = false;
778
779                         return TypeBuilder;
780                 }
781
782                 //
783                 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
784                 // interface is consistent.  Either it is `Item' or it is the name defined by all the
785                 // indexers with the `IndexerName' attribute.
786                 //
787                 // Turns out that the IndexerNameAttribute is applied to each indexer,
788                 // but it is never emitted, instead a DefaultName attribute is attached
789                 // to the interface
790                 //
791                 void DefineIndexers (TypeContainer parent)
792                 {
793                         string interface_indexer_name = null;
794
795                         foreach (InterfaceIndexer ii in defined_indexer){
796
797                                 PopulateIndexer (parent, this, ii);
798
799                                 if (interface_indexer_name == null){
800                                         interface_indexer_name = IndexerName;
801                                         continue;
802                                 }
803                                 
804                                 if (IndexerName == interface_indexer_name)
805                                         continue;
806                                 
807                                 Report.Error (
808                                         668, "Two indexers have different names, " +
809                                         " you should use the same name for all your indexers");
810                         }
811                         if (interface_indexer_name == null)
812                                 interface_indexer_name = "Item";
813                         IndexerName = interface_indexer_name;
814                 }
815                 
816                 /// <summary>
817                 ///   Performs semantic analysis, and then generates the IL interfaces
818                 /// </summary>
819                 public override bool DefineMembers (TypeContainer parent)
820                 {
821                         if (members_defined)
822                                 return true;
823                         
824                         if (!SemanticAnalysis ())
825                                 return false;
826
827                         
828                         if (defined_method != null){
829                                 foreach (InterfaceMethod im in defined_method)
830                                         PopulateMethod (parent, this, im);
831                         }
832
833                         if (defined_properties != null){
834                                 foreach (InterfaceProperty ip in defined_properties)
835                                         PopulateProperty (parent, this, ip);
836                         }
837
838                         if (defined_events != null)
839                                 foreach (InterfaceEvent ie in defined_events)
840                                         PopulateEvent (parent, this, ie);
841
842                         if (defined_indexer != null) {
843                                 DefineIndexers (parent);
844
845                                 CustomAttributeBuilder cb = EmitDefaultMemberAttr (
846                                         parent, IndexerName, ModFlags, Location);
847                                 if (cb != null)
848                                         TypeBuilder.SetCustomAttribute (cb);
849                         }
850
851 #if CACHE
852                         if (TypeBuilder.BaseType != null)
853                                 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
854
855                         member_cache = new MemberCache (this);
856 #endif
857                         members_defined = true;
858                         return true;
859                 }
860
861
862                 //
863                 // In the case of Interfaces, there is nothing to do here
864                 //
865                 public override bool Define (TypeContainer parent)
866                 {
867                         return true;
868                 }
869
870                 /// <summary>
871                 ///   Applies all the attributes.
872                 /// </summary>
873                 public void Emit (TypeContainer tc)
874                 {
875                         if (OptAttributes != null) {
876                                 EmitContext ec = new EmitContext (tc, this, Location, null, null,
877                                                                   ModFlags, false);
878                                 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
879                         }
880
881                         // Now emit attributes for each interface member
882                         if (defined_method != null) {
883                                 foreach (InterfaceMethod im in defined_method) {
884                                         EmitContext ec = new EmitContext (tc, this, Location, null,
885                                                                           im.ReturnType.Type, ModFlags, false);
886                                         
887                                         if (im.OptAttributes != null)
888                                                 Attribute.ApplyAttributes (ec, im.Builder, im, im.OptAttributes);
889                                 }      
890                         }
891
892                         if (defined_properties != null) {
893                                 foreach (InterfaceProperty ip in defined_properties) {
894                                         EmitContext ec = new EmitContext (tc, this, Location, null,
895                                                                           null, ModFlags, false);
896                                         
897                                         if (ip.OptAttributes != null)
898                                                 Attribute.ApplyAttributes (ec, ip.Builder, ip, ip.OptAttributes);
899                                 }
900                         }
901
902                         if (defined_events != null) {
903                                 foreach (InterfaceEvent ie in defined_events) {
904                                         EmitContext ec = new EmitContext (tc, this, Location, null,
905                                                                           null, ModFlags, false);
906                                         
907                                         if (ie.OptAttributes != null)
908                                                 Attribute.ApplyAttributes (ec, ie.Builder, ie, ie.OptAttributes);
909                                 }
910                         }
911                 }
912
913                 public static CustomAttributeBuilder EmitDefaultMemberAttr (TypeContainer parent,
914                                                                             string name,
915                                                                             int flags,
916                                                                             Location loc)
917                 {
918                         EmitContext ec = new EmitContext (parent, loc, null, null, flags);
919
920                         Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
921                                                                  ".ctor", MemberTypes.Constructor,
922                                                                  BindingFlags.Public | BindingFlags.Instance,
923                                                                  Location.Null);
924                         
925                         if (!(ml is MethodGroupExpr)) {
926                                 Console.WriteLine ("Internal error !!!!");
927                                 return null;
928                         }
929                         
930                         MethodGroupExpr mg = (MethodGroupExpr) ml;
931
932                         MethodBase constructor = mg.Methods [0];
933
934                         string [] vals = { name };
935
936                         CustomAttributeBuilder cb = null;
937                         try {
938                                 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
939                         } catch {
940                                 Report.Warning (-100, "Can not set the indexer default member attribute");
941                         }
942
943                         return cb;
944                 }
945
946                 //
947                 // IMemberContainer
948                 //
949
950                 string IMemberContainer.Name {
951                         get {
952                                 return Name;
953                         }
954                 }
955
956                 Type IMemberContainer.Type {
957                         get {
958                                 return TypeBuilder;
959                         }
960                 }
961
962                 IMemberContainer IMemberContainer.Parent {
963                         get {
964                                 return parent_container;
965                         }
966                 }
967
968                 MemberCache IMemberContainer.MemberCache {
969                         get {
970                                 return member_cache;
971                         }
972                 }
973
974                 bool IMemberContainer.IsInterface {
975                         get {
976                                 return true;
977                         }
978                 }
979
980                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
981                 {
982                         // Interfaces only contain instance members.
983                         if ((bf & BindingFlags.Instance) == 0)
984                                 return MemberList.Empty;
985                         if ((bf & BindingFlags.Public) == 0)
986                                 return MemberList.Empty;
987
988                         ArrayList members = new ArrayList ();
989
990                         if ((mt & MemberTypes.Method) != 0)
991                                 members.AddRange (method_builders);
992
993                         if ((mt & MemberTypes.Property) != 0)
994                                 members.AddRange (property_builders);
995
996                         if ((mt & MemberTypes.Event) != 0)
997                                 members.AddRange (event_builders);
998
999                         return new MemberList (members);
1000                 }
1001         }
1002
1003         public class InterfaceMemberBase {
1004                 public readonly string Name;
1005                 public readonly bool IsNew;
1006                 public Attributes OptAttributes;
1007                 
1008                 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
1009                 {
1010                         Name = name;
1011                         IsNew = is_new;
1012                         OptAttributes = attrs;
1013                 }
1014         }
1015         
1016         public class InterfaceProperty : InterfaceMemberBase {
1017                 public readonly bool HasSet;
1018                 public readonly bool HasGet;
1019                 public readonly Location Location;
1020                 public Expression Type;
1021                 public PropertyBuilder Builder;
1022                 
1023                 public InterfaceProperty (Expression type, string name,
1024                                           bool is_new, bool has_get, bool has_set,
1025                                           Attributes attrs, Location loc)
1026                         : base (name, is_new, attrs)
1027                 {
1028                         Type = type;
1029                         HasGet = has_get;
1030                         HasSet = has_set;
1031                         Location = loc;
1032                 }
1033         }
1034
1035         public class InterfaceEvent : InterfaceMemberBase {
1036                 public readonly Location Location;
1037                 public Expression Type;
1038                 public MyEventBuilder Builder;
1039                 
1040                 public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs,
1041                                        Location loc)
1042                         : base (name, is_new, attrs)
1043                 {
1044                         Type = type;
1045                         Location = loc;
1046                 }
1047         }
1048         
1049         public class InterfaceMethod : InterfaceMemberBase {
1050                 public Expression ReturnType;
1051                 public readonly Parameters Parameters;
1052                 public readonly Location Location;
1053                 public MethodBuilder Builder;
1054                 
1055                 public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args,
1056                                         Attributes attrs, Location l)
1057                         : base (name, is_new, attrs)
1058                 {
1059                         this.ReturnType = return_type;
1060                         this.Parameters = args;
1061                         Location = l;
1062                 }
1063
1064                 /// <summary>
1065                 ///   Returns the signature for this interface method
1066                 /// </summary>
1067                 public string GetSignature (DeclSpace ds)
1068                 {
1069                         ReturnType = ds.ResolveTypeExpr (ReturnType, false, Location);
1070                         if (ReturnType == null)
1071                                 return null;
1072                         
1073                         Type ret = ReturnType.Type;
1074                         string args = Parameters.GetSignature (ds);
1075
1076                         if ((ret == null) || (args == null))
1077                                 return null;
1078                         
1079                         return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
1080                 }
1081
1082                 public Type [] ParameterTypes (DeclSpace ds)
1083                 {
1084                         return Parameters.GetParameterInfo (ds);
1085                 }
1086         }
1087
1088         public class InterfaceIndexer : InterfaceMemberBase {
1089                 public readonly bool HasGet, HasSet;
1090                 public readonly Parameters Parameters;
1091                 public readonly Location Location;
1092                 public Expression Type;
1093                 public PropertyBuilder Builder;
1094                 
1095                 public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set,
1096                                          bool is_new, Attributes attrs, Location loc)
1097                         : base ("", is_new, attrs)
1098                 {
1099                         Type = type;
1100                         Parameters = args;
1101                         HasGet = do_get;
1102                         HasSet = do_set;
1103                         Location = loc;
1104                 }
1105
1106                 public Type [] ParameterTypes (DeclSpace ds)
1107                 {
1108                         return Parameters.GetParameterInfo (ds);
1109                 }
1110         }
1111 }