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