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