Sat Jan 5 16:08:23 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / mcs / class.cs
1 //
2 // class.cs: Class and Struct handlers
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
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System;
16
17 namespace Mono.CSharp {
18
19         /// <summary>
20         ///   This is the base class for structs and classes.  
21         /// </summary>
22         public class TypeContainer : DeclSpace {
23                 // Holds a list of classes and structures
24                 ArrayList types;
25
26                 // Holds the list of properties
27                 ArrayList properties;
28
29                 // Holds the list of enumerations
30                 ArrayList enums;
31
32                 // Holds the list of delegates
33                 ArrayList delegates;
34                 
35                 // Holds the list of constructors
36                 ArrayList instance_constructors;
37
38                 // Holds the list of fields
39                 ArrayList fields;
40
41                 // Holds a list of fields that have initializers
42                 ArrayList initialized_fields;
43
44                 // Holds a list of static fields that have initializers
45                 ArrayList initialized_static_fields;
46
47                 // Holds the list of constants
48                 ArrayList constants;
49
50                 // Holds the list of
51                 ArrayList interfaces;
52
53                 // Holds the methods.
54                 ArrayList methods;
55
56                 // Holds the events
57                 ArrayList events;
58
59                 // Holds the indexers
60                 ArrayList indexers;
61
62                 // Holds the operators
63                 ArrayList operators;
64
65                 //
66                 // Pointers to the default constructor and the default static constructor
67                 //
68                 Constructor default_constructor;
69                 Constructor default_static_constructor;
70
71                 //
72                 // Whether we have seen a static constructor for this class or not
73                 //
74                 bool have_static_constructor = false;
75                 
76                 //
77                 // This one is computed after we can distinguish interfaces
78                 // from classes from the arraylist `type_bases' 
79                 //
80                 string     base_class_name;
81
82                 TypeContainer parent;
83                 ArrayList type_bases;
84
85                 // Attributes for this type
86                 protected Attributes attributes;
87
88                 // Information in the case we are an attribute type
89
90                 public AttributeTargets Targets;
91                 public bool AllowMultiple;
92                 public bool Inherited;
93                 
94
95                 public TypeContainer (TypeContainer parent, string name, Location l)
96                         : base (name, l)
97                 {
98                         string n;
99                         types = new ArrayList ();
100                         this.parent = parent;
101
102                         if (parent == null)
103                                 n = "";
104                         else
105                                 n = parent.Name;
106
107                         base_class_name = null;
108                         
109                         //Console.WriteLine ("New class " + name + " inside " + n);
110                 }
111
112                 public AdditionResult AddConstant (Const constant)
113                 {
114                         AdditionResult res;
115                         string name = constant.Name;
116
117                         if ((res = IsValid (name)) != AdditionResult.Success)
118                                 return res;
119                         
120                         if (constants == null)
121                                 constants = new ArrayList ();
122
123                         constants.Add (constant);
124                         DefineName (name, constant);
125
126                         return AdditionResult.Success;
127                 }
128
129                 public AdditionResult AddEnum (Mono.CSharp.Enum e)
130                 {
131                         AdditionResult res;
132                         string name = e.Name;
133
134                         if ((res = IsValid (name)) != AdditionResult.Success)
135                                 return res;
136
137                         if (enums == null)
138                                 enums = new ArrayList ();
139
140                         enums.Add (e);
141                         DefineName (name, e);
142
143                         return AdditionResult.Success;
144                 }
145                 
146                 public AdditionResult AddClass (Class c)
147                 {
148                         AdditionResult res;
149                         string name = c.Name;
150
151
152                         if ((res = IsValid (name)) != AdditionResult.Success)
153                                 return res;
154
155                         DefineName (name, c);
156                         types.Add (c);
157
158                         return AdditionResult.Success;
159                 }
160
161                 public AdditionResult AddStruct (Struct s)
162                 {
163                         AdditionResult res;
164                         string name = s.Name;
165                         
166                         if ((res = IsValid (name)) != AdditionResult.Success)
167                                 return res;
168
169                         DefineName (name, s);
170                         types.Add (s);
171
172                         return AdditionResult.Success;
173                 }
174
175                 public AdditionResult AddDelegate (Delegate d)
176                 {
177                         AdditionResult res;
178                         string name = d.Name;
179
180                         if ((res = IsValid (name)) != AdditionResult.Success)
181                                 return res;
182
183                         if (delegates == null)
184                                 delegates = new ArrayList ();
185                         
186                         DefineName (name, d);
187                         delegates.Add (d);
188
189                         return AdditionResult.Success;
190                 }
191
192                 public AdditionResult AddMethod (Method method)
193                 {
194                         string name = method.Name;
195                         Object value = defined_names [name];
196                         
197                         if (value != null && (!(value is Method)))
198                                 return AdditionResult.NameExists;
199
200                         if (methods == null)
201                                 methods = new ArrayList ();
202
203                         methods.Add (method);
204                         if (value != null)
205                                 DefineName (name, method);
206
207                         return AdditionResult.Success;
208                 }
209
210                 public AdditionResult AddConstructor (Constructor c)
211                 {
212                         if (c.Name != Basename) 
213                                 return AdditionResult.NotAConstructor;
214
215                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
216                         
217                         if (is_static){
218                                 have_static_constructor = true;
219                                 if (default_static_constructor != null){
220                                         Console.WriteLine ("I have a static constructor already");
221                                         Console.WriteLine ("   " + default_static_constructor);
222                                         return AdditionResult.MethodExists;
223                                 }
224
225                                 default_static_constructor = c;
226                         } else {
227                                 if (c.IsDefault ()){
228                                         if (default_constructor != null)
229                                                 return AdditionResult.MethodExists;
230                                         default_constructor = c;
231                                 }
232                                 
233                                 if (instance_constructors == null)
234                                         instance_constructors = new ArrayList ();
235                                 
236                                 instance_constructors.Add (c);
237                         }
238                         
239                         return AdditionResult.Success;
240                 }
241                 
242                 public AdditionResult AddInterface (Interface iface)
243                 {
244                         AdditionResult res;
245                         string name = iface.Name;
246
247                         if ((res = IsValid (name)) != AdditionResult.Success)
248                                 return res;
249                         
250                         if (interfaces == null)
251                                 interfaces = new ArrayList ();
252                         interfaces.Add (iface);
253                         DefineName (name, iface);
254                         
255                         return AdditionResult.Success;
256                 }
257
258                 public AdditionResult AddField (Field field)
259                 {
260                         AdditionResult res;
261                         string name = field.Name;
262                         
263                         if ((res = IsValid (name)) != AdditionResult.Success)
264                                 return res;
265
266                         if (fields == null)
267                                 fields = new ArrayList ();
268
269                         fields.Add (field);
270                         if (field.Initializer != null){
271                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
272                                         if (initialized_static_fields == null)
273                                                 initialized_static_fields = new ArrayList ();
274
275                                         initialized_static_fields.Add (field);
276
277                                         //
278                                         // We have not seen a static constructor,
279                                         // but we will provide static initialization of fields
280                                         //
281                                         have_static_constructor = true;
282                                 } else {
283                                         if (initialized_fields == null)
284                                                 initialized_fields = new ArrayList ();
285                                 
286                                         initialized_fields.Add (field);
287                                 }
288                         }
289                         
290                         DefineName (name, field);
291                         return AdditionResult.Success;
292                 }
293
294                 public AdditionResult AddProperty (Property prop)
295                 {
296                         AdditionResult res;
297                         string name = prop.Name;
298
299                         if ((res = IsValid (name)) != AdditionResult.Success)
300                                 return res;
301
302                         if (properties == null)
303                                 properties = new ArrayList ();
304
305                         properties.Add (prop);
306                         DefineName (name, prop);
307
308                         return AdditionResult.Success;
309                 }
310
311                 public AdditionResult AddEvent (Event e)
312                 {
313                         AdditionResult res;
314                         string name = e.Name;
315
316                         if ((res = IsValid (name)) != AdditionResult.Success)
317                                 return res;
318
319                         if (events == null)
320                                 events = new ArrayList ();
321                         
322                         events.Add (e);
323                         DefineName (name, e);
324
325                         return AdditionResult.Success;
326                 }
327
328                 public AdditionResult AddIndexer (Indexer i)
329                 {
330                         if (indexers == null)
331                                 indexers = new ArrayList ();
332
333                         indexers.Add (i);
334
335                         return AdditionResult.Success;
336                 }
337
338                 public AdditionResult AddOperator (Operator op)
339                 {
340                         if (operators == null)
341                                 operators = new ArrayList ();
342
343                         operators.Add (op);
344
345                         return AdditionResult.Success;
346                 }
347                 
348                 public TypeContainer Parent {
349                         get {
350                                 return parent;
351                         }
352                 }
353
354                 public ArrayList Types {
355                         get {
356                                 return types;
357                         }
358                 }
359
360                 public ArrayList Methods {
361                         get {
362                                 return methods;
363                         }
364                 }
365
366                 public ArrayList Constants {
367                         get {
368                                 return constants;
369                         }
370                 }
371
372                 public ArrayList Interfaces {
373                         get {
374                                 return interfaces;
375                         }
376                 }
377                 
378                 public string Base {
379                         get {
380                                 return base_class_name;
381                         }
382                 }
383                 
384                 public ArrayList Bases {
385                         get {
386                                 return type_bases;
387                         }
388
389                         set {
390                                 type_bases = value;
391                         }
392                 }
393
394                 public ArrayList Fields {
395                         get {
396                                 return fields;
397                         }
398                 }
399
400                 public ArrayList InstanceConstructors {
401                         get {
402                                 return instance_constructors;
403                         }
404                 }
405
406                 public ArrayList Properties {
407                         get {
408                                 return properties;
409                         }
410                 }
411
412                 public ArrayList Events {
413                         get {
414                                 return events;
415                         }
416                 }
417                 
418                 public ArrayList Enums {
419                         get {
420                                 return enums;
421                         }
422                 }
423
424                 public ArrayList Indexers {
425                         get {
426                                 return indexers;
427                         }
428                 }
429
430                 public ArrayList Operators {
431                         get {
432                                 return operators;
433                         }
434                 }
435
436                 public ArrayList Delegates {
437                         get {
438                                 return delegates;
439                         }
440                 }
441                 
442                 public Attributes OptAttributes {
443                         get {
444                                 return attributes;
445                         }
446                 }
447                 
448                 // 
449                 // root_types contains all the types.  All TopLevel types
450                 // hence have a parent that points to `root_types', that is
451                 // why there is a non-obvious test down here.
452                 //
453                 public bool IsTopLevel {
454                         get {
455                                 if (parent != null){
456                                         if (parent.Parent == null)
457                                                 return true;
458                                 }
459                                 return false;
460                         }
461                 }
462                         
463                 public bool HaveStaticConstructor {
464                         get {
465                                 return have_static_constructor;
466                         }
467                 }
468                 
469                 public virtual TypeAttributes TypeAttr {
470                         get {
471                                 return Modifiers.TypeAttr (ModFlags, this);
472                         }
473                 }
474
475                 //
476                 // Emits the instance field initializers
477                 //
478                 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
479                 {
480                         ArrayList fields;
481                         ILGenerator ig = ec.ig;
482
483                         if (is_static)
484                                 fields = initialized_static_fields;
485                         else
486                                 fields = initialized_fields;
487
488                         if (fields == null)
489                                 return true;
490                         
491                         foreach (Field f in fields){
492                                 Object init = f.Initializer;
493
494                                 Expression e;
495                                 if (init is Expression)
496                                         e = (Expression) init;
497                                 else {
498                                         string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
499                                         string rank = f.Type.Substring (f.Type.IndexOf ("["));
500                                         e = new ArrayCreation (base_type, rank, (ArrayList) init, f.Location); 
501                                 }
502                                 
503                                 e = e.Resolve (ec);
504                                 if (e == null)
505                                         return false;
506                                 
507                                 if (!is_static)
508                                         ig.Emit (OpCodes.Ldarg_0);
509                                 
510                                 e.Emit (ec);
511                                 
512                                 if (is_static)
513                                         ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
514                                 else
515                                         ig.Emit (OpCodes.Stfld, f.FieldBuilder);
516                                 
517                         }
518                         
519                         return true;
520                 }
521                 
522                 //
523                 // Defines the default constructors
524                 //
525                 void DefineDefaultConstructor (bool is_static)
526                 {
527                         Constructor c;
528                         int mods = 0;
529
530                         c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
531                                              new ConstructorBaseInitializer (null, new Location (-1)),
532                                              new Location (-1));
533                         
534                         if (is_static)
535                                 mods = Modifiers.STATIC;
536
537                         c.ModFlags = mods;
538
539                         AddConstructor (c);
540                         
541                         c.Block = new Block (null);
542                         
543                 }
544
545                 public void ReportStructInitializedInstanceError ()
546                 {
547                         string n = TypeBuilder.FullName;
548                         
549                         foreach (Field f in initialized_fields){
550                                 Report.Error (
551                                         573, Location,
552                                         "`" + n + "." + f.Name + "': can not have " +
553                                         "instance field initializers in structs");
554                         }
555                 }
556
557                 struct TypeAndMethods {
558                         public Type          type;
559                         public MethodInfo [] methods;
560
561                         // Far from ideal, but we want to avoid creating a copy
562                         // of methods above.
563                         public Type [][]     args;
564
565                         //
566                         // This flag on the method says `We found a match, but
567                         // because it was private, we could not use the match
568                         //
569                         public bool []       found;
570                 }
571
572                 //
573                 // This array keeps track of the pending implementations
574                 // 
575                 TypeAndMethods [] pending_implementations;
576                 
577                 //
578                 // Registers the required method implementations for this class
579                 //
580                 // Register method implementations are either abstract methods
581                 // flagged as such on the base class or interface methods
582                 //
583                 public void RegisterRequiredImplementations ()
584                 {
585                         Type [] ifaces = TypeBuilder.GetInterfaces ();
586                         Type b = TypeBuilder.BaseType;
587                         int icount = 0;
588                         
589                         if (ifaces != null)
590                                 icount = ifaces.Length;
591
592                         if (icount == 0)
593                                 return;
594                         
595                         pending_implementations = new TypeAndMethods [icount + (b.IsAbstract ? 1 : 0)];
596                         
597                         int i = 0;
598                         if (ifaces != null){
599                                 foreach (Type t in ifaces){
600                                         MethodInfo [] mi;
601
602                                         if (t is TypeBuilder){
603                                                 Interface iface;
604
605                                                 iface = RootContext.TypeManager.LookupInterface (t);
606                                                 
607                                                 mi = iface.GetMethods ();
608                                         } else
609                                                 mi = t.GetMethods ();
610
611                                         int count = mi.Length;
612                                         pending_implementations [i].type = t;
613                                         pending_implementations [i].methods = mi;
614                                         pending_implementations [i].args = new Type [count][];
615                                         pending_implementations [i].found = new bool [count];
616
617                                         int j = 0;
618                                         foreach (MethodInfo m in mi){
619                                                 Type [] types = TypeManager.GetArgumentTypes (m);
620
621                                                 pending_implementations [i].args [j] = types;
622                                                 j++;
623                                         }
624                                         i++;
625                                 }
626                         }
627
628                         if (b.IsAbstract){
629                                 MemberInfo [] abstract_methods;
630
631                                 abstract_methods = FindMembers (
632                                         TypeBuilder.BaseType,
633                                         MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
634                                         abstract_method_filter, null);
635
636                                 if (abstract_methods != null){
637                                         int count = abstract_methods.Length;
638                                         pending_implementations [i].methods = new MethodInfo [count];
639                                         
640                                         abstract_methods.CopyTo (pending_implementations [i].methods, 0);
641                                         pending_implementations [i].found = new bool [count];
642                                         pending_implementations [i].args = new Type [count][];
643                                         pending_implementations [i].type = TypeBuilder;
644
645                                         int j = 0;
646                                         foreach (MemberInfo m in abstract_methods){
647                                                 MethodInfo mi = (MethodInfo) m;
648                                                 
649                                                 Type [] types = TypeManager.GetArgumentTypes (mi);
650
651                                                 pending_implementations [i].args [j] = types;
652                                                 j++;
653                                         }
654                                 }
655                         }
656                         
657                 }
658
659                 public static string MakeFQN (string nsn, string name)
660                 {
661                         string prefix = (nsn == "" ? "" : nsn + ".");
662
663                         return prefix + name;
664                 }
665                        
666                 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
667                 {
668                         TypeContainer parent;
669                         Type t;
670
671                         error = false;
672                         name = MakeFQN (ns, name);
673
674                         t  = RootContext.TypeManager.LookupType (name);
675                         if (t != null)
676                                 return t;
677
678                         if (is_class)
679                                 parent = (Class) RootContext.Tree.Classes [name];
680                         else 
681                                 parent = (Struct) RootContext.Tree.Structs [name];
682                         
683
684                         if (parent != null){
685                                 t = parent.DefineType (builder);
686                                 if (t == null){
687                                         Report.Error (146, "Class definition is circular: `"+name+"'");
688                                         error = true;
689                                         return null;
690                                 }
691
692                                 return t;
693                         }
694
695                         return null;
696                 }
697                 
698                 //
699                 // returns the type for an interface or a class, this will recursively
700                 // try to define the types that it depends on.
701                 //
702                 Type GetInterfaceOrClass (object builder, string name, bool is_class)
703                 {
704                         Type t;
705                         bool error;
706
707                         //
708                         // Attempt to lookup the class on our namespace
709                         //
710                         t = LookupInterfaceOrClass (builder, Namespace.Name, name, is_class, out error);
711                         if (error)
712                                 return null;
713                         
714                         if (t != null) 
715                                 return t;
716
717                         //
718                         // Attempt to do a direct unqualified lookup
719                         //
720                         t = LookupInterfaceOrClass (builder, "", name, is_class, out error);
721                         if (error)
722                                 return null;
723                         
724                         if (t != null)
725                                 return t;
726                         
727                         //
728                         // Attempt to lookup the class on any of the `using'
729                         // namespaces
730                         //
731
732                         for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
733                                 ArrayList using_list = ns.UsingTable;
734                                 
735                                 if (using_list == null)
736                                         continue;
737
738                                 foreach (string n in using_list){
739                                         t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
740                                         if (error)
741                                                 return null;
742
743                                         if (t != null)
744                                                 return t;
745                                 }
746                                 
747                         }
748                         Report.Error (246, "Can not find type `"+name+"'");
749                         return null;
750                 }
751
752                 /// <summary>
753                 ///   This function computes the Base class and also the
754                 ///   list of interfaces that the class or struct @c implements.
755                 ///   
756                 ///   The return value is an array (might be null) of
757                 ///   interfaces implemented (as Types).
758                 ///   
759                 ///   The @parent argument is set to the parent object or null
760                 ///   if this is `System.Object'. 
761                 /// </summary>
762                 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
763                 {
764                         ArrayList bases = Bases;
765                         int count;
766                         int start, j, i;
767
768                         error = false;
769
770                         if (is_class)
771                                 parent = null;
772                         else
773                                 parent = TypeManager.value_type;
774
775                         if (bases == null){
776                                 if (is_class){
777                                         if (RootContext.StdLib)
778                                                 parent = TypeManager.object_type;
779                                         else if (Name != "System.Object")
780                                                 parent = TypeManager.object_type;
781                                 } else {
782                                         //
783                                         // If we are compiling our runtime,
784                                         // and we are defining ValueType, then our
785                                         // parent is `System.Object'.
786                                         //
787                                         if (!RootContext.StdLib && Name == "System.ValueType")
788                                                 parent = TypeManager.object_type;
789                                 }
790
791                                 return null;
792                         }
793
794                         //
795                         // Bases should be null if there are no bases at all
796                         //
797                         count = bases.Count;
798
799                         if (is_class){
800                                 string name = (string) bases [0];
801                                 Type first = GetInterfaceOrClass (builder, name, is_class);
802
803                                 if (first == null){
804                                         error = true;
805                                         return null;
806                                 }
807                                 
808                                 if (first.IsClass){
809                                         parent = first;
810                                         start = 1;
811                                 } else {
812                                         parent = TypeManager.object_type;
813                                         start = 0;
814                                 }
815                         } else {
816                                 start = 0;
817                         }
818
819                         Type [] ifaces = new Type [count-start];
820                         
821                         for (i = start, j = 0; i < count; i++, j++){
822                                 string name = (string) bases [i];
823                                 Type t = GetInterfaceOrClass (builder, name, is_class);
824                                 
825                                 if (t == null){
826                                         error = true;
827                                         return null;
828                                 }
829
830                                 if (is_class == false && !t.IsInterface){
831                                         Report.Error (527, "In Struct `" + Name + "', type `"+
832                                                       name +"' is not an interface");
833                                         error = true;
834                                         return null;
835                                 }
836                                 
837                                 if (t.IsSealed) {
838                                         string detail = "";
839                                         
840                                         if (t.IsValueType)
841                                                 detail = " (a class can not inherit from a struct)";
842                                                         
843                                         Report.Error (509, "class `"+ Name +
844                                                       "': Cannot inherit from sealed class `"+
845                                                       bases [i]+"'"+detail);
846                                         error = true;
847                                         return null;
848                                 }
849
850                                 if (t.IsClass) {
851                                         if (parent != null){
852                                                 Report.Error (527, "In Class `" + Name + "', type `"+
853                                                               name+"' is not an interface");
854                                                 error = true;
855                                                 return null;
856                                         }
857                                 }
858                                 
859                                 ifaces [j] = t;
860                         }
861
862                         return ifaces;
863                 }
864                 
865                 //
866                 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
867                 //
868                 public TypeBuilder DefineType (object parent_builder)
869                 {
870                         Type parent;
871                         Type [] ifaces;
872                         bool error;
873                         bool is_class;
874
875                         if (TypeBuilder != null)
876                                 return TypeBuilder;
877                         
878                         if (InTransit)
879                                 return null;
880                         
881                         InTransit = true;
882                         
883                         if (this is Class)
884                                 is_class = true;
885                         else
886                                 is_class = false;
887
888                         ifaces = GetClassBases (parent_builder, is_class, out parent, out error); 
889                         
890                         if (error)
891                                 return null;
892
893                         if (parent_builder is ModuleBuilder) {
894                                 ModuleBuilder builder = (ModuleBuilder) parent_builder;
895                                 //
896                                 // Structs with no fields need to have a ".size 1"
897                                 // appended
898                                 //
899
900                                 if (!is_class && Fields == null)
901                                         TypeBuilder = builder.DefineType (Name,
902                                                                           TypeAttr,
903                                                                           parent, 
904                                                                           PackingSize.Unspecified, 1);
905                                 else
906                                 //
907                                 // classes or structs with fields
908                                 //
909                                         TypeBuilder = builder.DefineType (Name,
910                                                                           TypeAttr,
911                                                                           parent,
912                                                                           ifaces);
913                         } else {
914                                 TypeBuilder builder = (System.Reflection.Emit.TypeBuilder) parent_builder;
915                                 
916                                 //
917                                 // Structs with no fields need to have a ".size 1"
918                                 // appended
919                                 //
920                                 if (!is_class && Fields == null)
921                                         TypeBuilder = builder.DefineNestedType (Basename,
922                                                                                 TypeAttr,
923                                                                                 parent, 
924                                                                                 PackingSize.Unspecified);
925                                 else
926                                 //
927                                 // classes or structs with fields
928                                 //
929                                         TypeBuilder = builder.DefineNestedType (Basename,
930                                                                                 TypeAttr,
931                                                                                 parent,
932                                                                                 ifaces);
933                         }
934
935                         RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
936                         RootContext.RegisterOrder (this);
937                         
938                         if (Types != null) {
939                                 foreach (TypeContainer tc in Types)
940                                         tc.DefineType (TypeBuilder);
941                         }
942
943                         if (Delegates != null) {
944                                 foreach (Delegate d in Delegates)
945                                         d.DefineDelegate (TypeBuilder);
946                         }
947
948                         if (Enums != null) {
949                                 foreach (Enum en in Enums)
950                                         en.DefineEnum (TypeBuilder);
951                         }
952                         
953                         InTransit = false;
954                         return TypeBuilder;
955                 }
956
957
958                 /// <summary>
959                 ///   Defines the MemberCore objects that are in the `list' Arraylist
960                 ///
961                 ///   The `defined_names' array contains a list of members defined in
962                 ///   a base class
963                 /// </summary>
964                 static ArrayList remove_list = new ArrayList ();
965                 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
966                 {
967                         int idx;
968                         
969                         remove_list.Clear ();
970
971                         foreach (MemberCore mc in list){
972                                 if (!mc.Define (this)){
973                                         remove_list.Add (mc);
974                                         continue;
975                                 }
976                                                 
977                                 if (defined_names == null)
978                                         continue;
979                                 
980                                 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
981                                 
982                                 if (idx < 0){
983                                         if (RootContext.WarningLevel >= 4){
984                                                 if ((mc.ModFlags & Modifiers.NEW) != 0)
985                                                         Report109 (mc.Location, mc);
986                                         }
987                                         continue;
988                                 }
989
990                                 if (defined_names [idx] is PropertyInfo &&
991                                     ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
992                                         continue;
993                                 }
994                                     
995 #if WANT_TO_VERIFY_SIGNATURES_HERE
996                                 if (defined_names [idx] is MethodBase && mc is MethodCore){
997                                         MethodBase mb = (MethodBase) defined_names [idx];
998                                         MethodCore met = (MethodCore) mc;
999                                         
1000                                         if ((mb.IsVirtual || mb.IsAbstract) &&
1001                                             (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1002                                                 continue;
1003
1004                                         //
1005                                         // FIXME: Compare the signatures here.  If they differ,
1006                                         // then: `continue;' 
1007                                 }
1008 #endif
1009                                 Report108 (mc.Location, defined_names [idx]);
1010                         }
1011                         
1012                         foreach (object o in remove_list)
1013                                 list.Remove (o);
1014                         
1015                         remove_list.Clear ();
1016                 }
1017                 
1018                 /// <summary>
1019                 ///   Populates our TypeBuilder with fields and methods
1020                 /// </summary>
1021                 public override bool Define (TypeContainer parent)
1022                 {
1023                         MemberInfo [] defined_names = null;
1024
1025                         if (RootContext.WarningLevel > 1){
1026                                 Type ptype;
1027
1028                                 //
1029                                 // This code throws an exception in the comparer
1030                                 // I guess the string is not an object?
1031                                 //
1032                                 ptype = TypeBuilder.BaseType;
1033                                 if (ptype != null){
1034                                         defined_names = FindMembers (
1035                                                 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1036                                                 BindingFlags.Public | BindingFlags.Instance |
1037                                                 BindingFlags.Static, null, null);
1038
1039                                         Array.Sort (defined_names, mif_compare);
1040                                 }
1041                         }
1042                         
1043                         if (constants != null)
1044                                 DefineMembers (constants, defined_names);
1045
1046                         if (fields != null)
1047                                 DefineMembers (fields, defined_names);
1048
1049                         if (this is Class){
1050                                 if (instance_constructors == null){
1051                                         if (default_constructor == null) 
1052                                                 DefineDefaultConstructor (false);
1053                                 }
1054
1055                                 if (initialized_static_fields != null &&
1056                                     default_static_constructor == null)
1057                                         DefineDefaultConstructor (true);
1058                         }
1059
1060                         if (this is Struct){
1061                                 //
1062                                 // Structs can not have initialized instance
1063                                 // fields
1064                                 //
1065                                 if (initialized_static_fields != null &&
1066                                     default_static_constructor == null)
1067                                         DefineDefaultConstructor (true);
1068
1069                                 if (initialized_fields != null)
1070                                         ReportStructInitializedInstanceError ();
1071                         }
1072
1073                         RegisterRequiredImplementations ();
1074
1075                         //
1076                         // Constructors are not in the defined_names array
1077                         //
1078                         if (instance_constructors != null)
1079                                 DefineMembers (instance_constructors, null);
1080                 
1081                         if (default_static_constructor != null)
1082                                 default_static_constructor.Define (this);
1083                         
1084                         if (methods != null)
1085                                 DefineMembers (methods, null);
1086
1087                         if (properties != null)
1088                                 DefineMembers (properties, defined_names);
1089
1090                         if (events != null)
1091                                 DefineMembers (events, defined_names);
1092
1093                         //
1094                         // FIXME: Make Indexers MemberCores?
1095                         //
1096                         if (indexers != null) {
1097                                 foreach (Indexer i in Indexers)
1098                                         i.Define (this);
1099                         }
1100
1101                         if (operators != null)
1102                                 DefineMembers (operators, null);
1103
1104                         //
1105                         // FIXME: I think we want to make Enums (hence DeclSpace)
1106                         // a MemberCore so we can report 108 and 109 here.
1107                         //
1108                         if (enums != null)
1109                                 DefineMembers (enums, defined_names);
1110                         
1111                         if (delegates != null)
1112                                 DefineMembers (delegates, defined_names);
1113
1114                         return true;
1115                 }
1116
1117                 /// <summary>
1118                 ///   Looks up the alias for the name
1119                 /// </summary>
1120                 public string LookupAlias (string name)
1121                 {
1122                         if (Namespace != null)
1123                                 return Namespace.LookupAlias (name);
1124                         else
1125                                 return null;
1126                 }
1127                 
1128                 /// <summary>
1129                 ///   This function is based by a delegate to the FindMembers routine
1130                 /// </summary>
1131                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1132                 {
1133                         return true;
1134                 }
1135                 
1136                 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1137                 {
1138                         MethodInfo mi = (MethodInfo) m;
1139
1140                         return mi.IsAbstract;
1141                 }
1142
1143                 /// <summary>
1144                 ///   This filter is used by FindMembers, and we just keep
1145                 ///   a global for the filter to `AlwaysAccept'
1146                 /// </summary>
1147                 static MemberFilter accepting_filter;
1148                 
1149                 /// <summary>
1150                 ///    This delegate is a MemberFilter used to extract the 
1151                 ///    abstact methods from a type.  
1152                 /// </summary>
1153                 static MemberFilter abstract_method_filter;
1154
1155                 /// <summary>
1156                 ///   A member comparission method based on name only
1157                 /// </summary>
1158                 static IComparer mif_compare;
1159
1160                 static TypeContainer ()
1161                 {
1162                         abstract_method_filter = new MemberFilter (IsAbstractMethod);
1163                         accepting_filter = new MemberFilter (AlwaysAccept);
1164                         mif_compare = new MemberInfoCompare ();
1165                 }
1166                 
1167                 /// <summary>
1168                 ///   This method returns the members of this type just like Type.FindMembers would
1169                 ///   Only, we need to use this for types which are _being_ defined because MS' 
1170                 ///   implementation can't take care of that.
1171                 /// </summary>
1172                 //
1173                 // FIXME: return an empty static array instead of null, that cleans up
1174                 // some code and is consistent with some coding conventions I just found
1175                 // out existed ;-)
1176                 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1177                                                   MemberFilter filter, object criteria)
1178                 {
1179                         ArrayList members = new ArrayList ();
1180
1181                         if (filter == null)
1182                                 filter = accepting_filter; 
1183                         
1184                         if ((mt & MemberTypes.Field) != 0) {
1185                                 if (Fields != null) {
1186                                         foreach (Field f in Fields) {
1187                                                 FieldBuilder fb = f.FieldBuilder;
1188                                                 if (filter (fb, criteria) == true)
1189                                                         members.Add (fb);
1190                                         }
1191                                 }
1192
1193                                 if (Constants != null) {
1194                                         foreach (Const con in Constants) {
1195                                                 FieldBuilder fb = con.FieldBuilder;
1196                                                 if (filter (fb, criteria) == true)
1197                                                         members.Add (fb);
1198                                         }
1199                                 }
1200                         }
1201
1202                         if ((mt & MemberTypes.Method) != 0) {
1203                                 if (Methods != null) {
1204                                         foreach (Method m in Methods) {
1205                                                 MethodBuilder mb = m.MethodBuilder;
1206
1207                                                 // If we are in transit, ignore
1208                                                 // This case arises when we are still defining a PInvoke method
1209                                                 // and we hit FindMembers because of the need to resolve named
1210                                                 // arguments inside of Attribute.DefinePInvokeMethod
1211                                                 if (mb == null)
1212                                                         continue;
1213
1214                                                 if (filter (mb, criteria) == true)
1215                                                         members.Add (mb);
1216                                         }
1217                                 }
1218
1219                                 if (Operators != null){
1220                                         foreach (Operator o in Operators) {
1221                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1222
1223                                                 if (filter (ob, criteria) == true)
1224                                                         members.Add (ob);
1225                                         }
1226                                 }
1227                         }
1228
1229                         if ((mt & MemberTypes.Event) != 0) {
1230                                 if (Events != null)
1231                                         foreach (Event e in Events) {
1232                                                 if (filter (e.EventBuilder, criteria) == true)
1233                                                         members.Add (e.EventBuilder);
1234                                         }
1235                         }
1236                         
1237                         if ((mt & MemberTypes.Property) != 0){
1238                                 if (Properties != null)
1239                                         foreach (Property p in Properties) {
1240                                                 if (filter (p.PropertyBuilder, criteria) == true)
1241                                                         members.Add (p.PropertyBuilder);
1242                                         }
1243
1244                                 if (Indexers != null)
1245                                         foreach (Indexer ix in Indexers) {
1246                                                 if (filter (ix.PropertyBuilder, criteria) == true)
1247                                                         members.Add (ix.PropertyBuilder);
1248                                         }
1249                         }
1250                         
1251                         if ((mt & MemberTypes.NestedType) != 0) {
1252
1253                                 if (Types != null)
1254                                         foreach (TypeContainer t in Types)  
1255                                                 if (filter (t.TypeBuilder, criteria) == true)
1256                                                         members.Add (t.TypeBuilder);
1257
1258                                 if (Enums != null)
1259                                         foreach (Enum en in Enums)
1260                                                 if (filter (en.TypeBuilder, criteria) == true)
1261                                                         members.Add (en.TypeBuilder);
1262                                 
1263                         }
1264
1265                         if ((mt & MemberTypes.Constructor) != 0){
1266                                 if (instance_constructors != null){
1267                                         foreach (Constructor c in instance_constructors){
1268                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1269
1270                                                 if (filter (cb, criteria) == true)
1271                                                         members.Add (cb);
1272                                         }
1273                                 }
1274
1275                                 if (default_static_constructor != null){
1276                                         ConstructorBuilder cb =
1277                                                 default_static_constructor.ConstructorBuilder;
1278                                         
1279                                         if (filter (cb, criteria) == true)
1280                                                 members.Add (cb);
1281                                 }
1282                         }
1283
1284                         //
1285                         // Lookup members in parent if requested.
1286                         //
1287                         if ((bf & BindingFlags.DeclaredOnly) == 0){
1288                                 MemberInfo [] mi;
1289
1290                                 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1291                                 if (mi != null)
1292                                         members.AddRange (mi);
1293                         }
1294                         
1295                         int count = members.Count;
1296                         if (count > 0){
1297                                 MemberInfo [] mi = new MemberInfo [count];
1298                                 members.CopyTo (mi);
1299                                 return mi;
1300                         }
1301
1302                         return null;
1303                 }
1304
1305                 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1306                 {
1307                         EventInfo ei = event_expr.EventInfo;
1308
1309                         foreach (Event e in events) { 
1310
1311                                 if (e.FieldBuilder == null)
1312                                         continue;
1313                                 
1314                                 if (Type.FilterName (e.FieldBuilder, ei.Name))
1315                                         return e.FieldBuilder;
1316                         }
1317
1318                         return null;
1319                 }
1320
1321                 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1322                                                          MemberFilter filter, object criteria)
1323                 {
1324                         TypeContainer tc = TypeManager.LookupTypeContainer (t);
1325
1326                         if (tc != null)
1327                                 return tc.FindMembers (mt, bf, filter, criteria);
1328                         else
1329                                 return t.FindMembers (mt, bf, filter, criteria);
1330                 }
1331                 
1332                 /// <summary>
1333                 ///   Whether the specified method is an interface method implementation
1334                 /// </summary>
1335                 ///
1336                 /// <remarks>
1337                 ///   If a method in Type `t' (or null to look in all interfaces
1338                 ///   and the base abstract class) with name `Name', return type `ret_type' and
1339                 ///   arguments `args' implements an interface, this method will
1340                 ///   return the MethodInfo that this method implements.
1341                 ///
1342                 ///   This will remove the method from the list of "pending" methods
1343                 ///   that are required to be implemented for this class as a side effect.
1344                 /// 
1345                 /// </remarks>
1346                 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1347                                                      bool clear)
1348                 {
1349                         if (pending_implementations == null)
1350                                 return null;
1351
1352                         foreach (TypeAndMethods tm in pending_implementations){
1353                                 if (!(t == null || tm.type == t))
1354                                         continue;
1355
1356                                 int i = 0;
1357                                 foreach (MethodInfo m in tm.methods){
1358                                         if (m == null){
1359                                                 i++;
1360                                                 continue;
1361                                         }
1362
1363                                         if (Name != m.Name){
1364                                                 i++;
1365                                                 continue;
1366                                         }
1367
1368                                         if (ret_type != m.ReturnType){
1369                                                 i++;
1370                                                 continue;
1371                                         }
1372                                         
1373                                         if (args == null){
1374                                                 if (tm.args [i] == null || tm.args [i].Length == 0){
1375                                                         if (clear)
1376                                                                 tm.methods [i] = null;
1377                                                         tm.found [i] = true;
1378                                                         return m;
1379                                                 } 
1380                                                 i++;
1381                                                 continue;
1382                                         }
1383
1384                                         if (tm.args == null){
1385                                                 Console.WriteLine ("Type:    " + tm.type);
1386                                                 Console.WriteLine ("method:  " + tm.methods [i]);
1387                                         }
1388                                         
1389                                         if (tm.args [i] == null){
1390                                                 i++;
1391                                                 continue;
1392                                         }
1393
1394                                         //
1395                                         // Check if we have the same parameters
1396                                         //
1397                                         if (tm.args [i].Length != args.Length){
1398                                                 i++;
1399                                                 continue;
1400                                         }
1401                                         
1402                                         int j;
1403                                                 
1404                                         for (j = 0; j < args.Length; j++){
1405                                                 if (tm.args [i][j] != args[j]){
1406                                                         i++;
1407                                                         continue;
1408                                                 }
1409                                         }
1410
1411                                         if (clear)
1412                                                 tm.methods [i] = null;
1413                                         tm.found [i] = true;
1414                                         return m;
1415                                 }
1416
1417                                 // If a specific type was requested, we can stop now.
1418                                 if (tm.type == t)
1419                                         return null;
1420                         }
1421                         return null;
1422                 }
1423
1424                 /// <summary>
1425                 ///   Verifies that any pending abstract methods or interface methods
1426                 ///   were implemented.
1427                 /// </summary>
1428                 bool VerifyPendingMethods ()
1429                 {
1430                         int top = pending_implementations.Length;
1431                         bool errors = false;
1432                         int i;
1433                         
1434                         for (i = 0; i < top; i++){
1435                                 Type type = pending_implementations [i].type;
1436                                 int j = 0;
1437                                 
1438                                 foreach (MethodInfo mi in pending_implementations [i].methods){
1439                                         if (mi == null)
1440                                                 continue;
1441
1442                                         if (type.IsInterface){
1443                                                 string extra = "";
1444                                                 
1445                                                 if (pending_implementations [i].found [j])
1446                                                         extra = ".  (method might be private or static)";
1447                                                 Report.Error (
1448                                                         536, Location,
1449                                                         "`" + Name + "' does not implement " +
1450                                                         "interface member `" +
1451                                                         type.FullName + "." + mi.Name + "'" + extra);
1452                                         } else {
1453                                                 Report.Error (
1454                                                         534, Location,
1455                                                         "`" + Name + "' does not implement " +
1456                                                         "inherited abstract member `" +
1457                                                         type.FullName + "." + mi.Name + "'");
1458                                         }
1459                                         errors = true;
1460                                         j++;
1461                                 }
1462                         }
1463                         return errors;
1464                 }
1465
1466                 /// <summary>
1467                 ///   Emits the values for the constants
1468                 /// </summary>
1469                 public void EmitConstants ()
1470                 {
1471                         if (constants != null)
1472                                 foreach (Const con in constants)
1473                                         con.EmitConstant (this);
1474                         return;
1475                 }
1476                 
1477                 /// <summary>
1478                 ///   Emits the code, this step is performed after all
1479                 ///   the types, enumerations, constructors
1480                 /// </summary>
1481                 public void Emit ()
1482                 {
1483                         if (instance_constructors != null)
1484                                 foreach (Constructor c in instance_constructors)
1485                                         c.Emit (this);
1486
1487                         if (default_static_constructor != null)
1488                                 default_static_constructor.Emit (this);
1489                         
1490                         if (methods != null)
1491                                 foreach (Method m in methods)
1492                                         m.Emit (this);
1493
1494                         if (operators != null)
1495                                 foreach (Operator o in operators)
1496                                         o.Emit (this);
1497
1498                         if (properties != null)
1499                                 foreach (Property p in properties)
1500                                         p.Emit (this);
1501
1502                         if (indexers != null) {
1503                                 foreach (Indexer ix in indexers)
1504                                         ix.Emit (this);
1505
1506                                 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1507
1508                                 TypeBuilder.SetCustomAttribute (cb);
1509                         }
1510                         
1511                         if (fields != null)
1512                                 foreach (Field f in fields)
1513                                         f.Emit (this);
1514
1515                         if (events != null){
1516                                 foreach (Event e in Events)
1517                                         e.Emit (this);
1518                         }
1519
1520                         if (pending_implementations != null)
1521                                 if (!VerifyPendingMethods ())
1522                                         return;
1523
1524                         EmitContext ec = new EmitContext (
1525                                                   this, Mono.CSharp.Location.Null, null, null,
1526                                                   ModFlags, false);
1527
1528                         Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1529                         
1530 //                      if (types != null)
1531 //                              foreach (TypeContainer tc in types)
1532 //                                      tc.Emit ();
1533                 }
1534                 
1535                 public override void CloseType ()
1536                 {
1537                         try {
1538                                 if (!Created){
1539                                         Created = true;
1540                                         TypeBuilder.CreateType ();
1541                                 }
1542                         } catch (TypeLoadException){
1543                                 //
1544                                 // This is fine, the code still created the type
1545                                 //
1546 //                              Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1547 //                              Console.WriteLine (e.Message);
1548                         }
1549                         
1550                         if (Enums != null)
1551                                 foreach (Enum en in Enums)
1552                                         en.CloseType ();
1553                         
1554                         if (Types != null){
1555                                 foreach (TypeContainer tc in Types)
1556                                         if (tc is Struct)
1557                                                 tc.CloseType ();
1558
1559                                 foreach (TypeContainer tc in Types)
1560                                         if (!(tc is Struct))
1561                                                 tc.CloseType ();
1562                         }
1563
1564                         if (Delegates != null)
1565                                 foreach (Delegate d in Delegates)
1566                                         d.CloseDelegate ();
1567                 }
1568
1569                 public string MakeName (string n)
1570                 {
1571                         return "`" + Name + "." + n + "'";
1572                 }
1573
1574                 public void Report108 (Location l, MemberInfo mi)
1575                 {
1576                         Report.Warning (
1577                                 108, l, "The keyword new is required on " + 
1578                                 MakeName (mi.Name) + " because it hides `" +
1579                                 mi.ReflectedType.Name + "." + mi.Name + "'");
1580                 }
1581
1582                 public void Report109 (Location l, MemberCore mc)
1583                 {
1584                         Report.Warning (
1585                                 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1586                                 "inherited member, the keyword new is not required");
1587                 }
1588                 
1589                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1590                 {
1591                         return 0;
1592                 }
1593
1594                 //
1595                 // Performs the validation on a Method's modifiers (properties have
1596                 // the same properties).
1597                 //
1598                 public bool MethodModifiersValid (int flags, string n, Location loc)
1599                 {
1600                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1601                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1602                         bool ok = true;
1603                         string name = MakeName (n);
1604                         
1605                         //
1606                         // At most one of static, virtual or override
1607                         //
1608                         if ((flags & Modifiers.STATIC) != 0){
1609                                 if ((flags & vao) != 0){
1610                                         Report.Error (
1611                                                 112, loc, "static method " + name + "can not be marked " +
1612                                                 "as virtual, abstract or override");
1613                                         ok = false;
1614                                 }
1615                         }
1616
1617                         if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1618                                 Report.Error (
1619                                         113, loc, name +
1620                                         " marked as override cannot be marked as new or virtual");
1621                                 ok = false;
1622                         }
1623
1624                         //
1625                         // If the declaration includes the abstract modifier, then the
1626                         // declaration does not include static, virtual or extern
1627                         //
1628                         if ((flags & Modifiers.ABSTRACT) != 0){
1629                                 if ((flags & Modifiers.EXTERN) != 0){
1630                                         Report.Error (
1631                                                 180, loc, name + " can not be both abstract and extern");
1632                                         ok = false;
1633                                 }
1634
1635                                 if ((flags & Modifiers.VIRTUAL) != 0){
1636                                         Report.Error (
1637                                                 503, loc, name + " can not be both abstract and virtual");
1638                                         ok = false;
1639                                 }
1640
1641                                 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1642                                         Report.Error (
1643                                                 513, loc, name +
1644                                                 " is abstract but its container class is not");
1645                                         ok = false;
1646
1647                                 }
1648                         }
1649
1650                         if ((flags & Modifiers.PRIVATE) != 0){
1651                                 if ((flags & vao) != 0){
1652                                         Report.Error (
1653                                                 621, loc, name +
1654                                                 " virtual or abstract members can not be private");
1655                                         ok = false;
1656                                 }
1657                         }
1658
1659                         if ((flags & Modifiers.SEALED) != 0){
1660                                 if ((flags & Modifiers.OVERRIDE) == 0){
1661                                         Report.Error (
1662                                                 238, loc, name +
1663                                                 " cannot be sealed because it is not an override");
1664                                         ok = false;
1665                                 }
1666                         }
1667
1668                         return ok;
1669                 }
1670
1671                 //
1672                 // Returns true if `type' is as accessible as the flags `flags'
1673                 // given for this member
1674                 //
1675                 static public bool AsAccessible (Type type, int flags)
1676                 {
1677                         // FIXME: Implement me
1678                         return true;
1679                 }
1680         }
1681
1682         public class Class : TypeContainer {
1683                 // <summary>
1684                 //   Modifiers allowed in a class declaration
1685                 // </summary>
1686                 public const int AllowedModifiers =
1687                         Modifiers.NEW |
1688                         Modifiers.PUBLIC |
1689                         Modifiers.PROTECTED |
1690                         Modifiers.INTERNAL |
1691                         Modifiers.PRIVATE |
1692                         Modifiers.ABSTRACT |
1693                         Modifiers.SEALED;
1694
1695                 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1696                         : base (parent, name, l)
1697                 {
1698                         int accmods;
1699
1700                         if (parent.Parent == null)
1701                                 accmods = Modifiers.INTERNAL;
1702                         else
1703                                 accmods = Modifiers.PRIVATE;
1704
1705                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods);
1706                         this.attributes = attrs;
1707                 }
1708
1709                 //
1710                 // FIXME: How do we deal with the user specifying a different
1711                 // layout?
1712                 //
1713                 public override TypeAttributes TypeAttr {
1714                         get {
1715                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1716                         }
1717                 }
1718         }
1719
1720         public class Struct : TypeContainer {
1721                 // <summary>
1722                 //   Modifiers allowed in a struct declaration
1723                 // </summary>
1724                 public const int AllowedModifiers =
1725                         Modifiers.NEW |
1726                         Modifiers.PUBLIC |
1727                         Modifiers.PROTECTED |
1728                         Modifiers.INTERNAL |
1729                         Modifiers.PRIVATE;
1730
1731                 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1732                         : base (parent, name, l)
1733                 {
1734                         int accmods;
1735                         
1736                         if (parent.Parent == null)
1737                                 accmods = Modifiers.INTERNAL;
1738                         else
1739                                 accmods = Modifiers.PRIVATE;
1740                         
1741                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods);
1742
1743                         this.ModFlags |= Modifiers.SEALED;
1744                         this.attributes = attrs;
1745                         
1746                 }
1747
1748                 //
1749                 // FIXME: Allow the user to specify a different set of attributes
1750                 // in some cases (Sealed for example is mandatory for a class,
1751                 // but what SequentialLayout can be changed
1752                 //
1753                 public override TypeAttributes TypeAttr {
1754                         get {
1755                                 return base.TypeAttr |
1756                                         TypeAttributes.SequentialLayout |
1757                                         TypeAttributes.Sealed |
1758                                         TypeAttributes.BeforeFieldInit;
1759                         }
1760                 }
1761         }
1762
1763         public abstract class MethodCore : MemberCore {
1764                 public readonly Parameters Parameters;
1765                 Block block;
1766                 
1767                 //
1768                 // Parameters, cached for semantic analysis.
1769                 //
1770                 InternalParameters parameter_info;
1771                 
1772                 public MethodCore (string name, Parameters parameters, Location l)
1773                         : base (name, l)
1774                 {
1775                         Name = name;
1776                         Parameters = parameters;
1777                 }
1778                 
1779                 //
1780                 //  Returns the System.Type array for the parameters of this method
1781                 //
1782                 Type [] parameter_types;
1783                 static Type [] no_types = new Type [0];
1784                 public Type [] ParameterTypes (TypeContainer parent)
1785                 {
1786                         if (Parameters == null)
1787                                 return no_types;
1788                         
1789                         if (parameter_types == null)
1790                                 parameter_types = Parameters.GetParameterInfo (parent);
1791
1792                         return parameter_types;
1793                 }
1794
1795                 public InternalParameters ParameterInfo
1796                 {
1797                         get {
1798                                 return parameter_info;
1799                         }
1800
1801                         set {
1802                                 parameter_info = value;
1803                         }
1804                 }
1805                 
1806                 public Block Block {
1807                         get {
1808                                 return block;
1809                         }
1810
1811                         set {
1812                                 block = value;
1813                         }
1814                 }
1815
1816                 public CallingConventions GetCallingConvention (bool is_class)
1817                 {
1818                         CallingConventions cc = 0;
1819                         
1820                         cc = Parameters.GetCallingConvention ();
1821
1822                         if (is_class)
1823                                 if ((ModFlags & Modifiers.STATIC) == 0)
1824                                         cc |= CallingConventions.HasThis;
1825
1826                         // FIXME: How is `ExplicitThis' used in C#?
1827                         
1828                         return cc;
1829                 }
1830         }
1831         
1832         public class Method : MethodCore {
1833                 public readonly string ReturnType;
1834                 public MethodBuilder MethodBuilder;
1835                 public readonly Attributes OptAttributes;
1836
1837                 MethodAttributes flags;
1838
1839                 /// <summary>
1840                 ///   Modifiers allowed in a class declaration
1841                 /// </summary>
1842                 const int AllowedModifiers =
1843                         Modifiers.NEW |
1844                         Modifiers.PUBLIC |
1845                         Modifiers.PROTECTED |
1846                         Modifiers.INTERNAL |
1847                         Modifiers.PRIVATE |
1848                         Modifiers.STATIC |
1849                         Modifiers.VIRTUAL |
1850                         Modifiers.SEALED |
1851                         Modifiers.OVERRIDE |
1852                         Modifiers.ABSTRACT |
1853                         Modifiers.EXTERN;
1854
1855                 //
1856                 // return_type can be "null" for VOID values.
1857                 //
1858                 public Method (string return_type, int mod, string name, Parameters parameters,
1859                                Attributes attrs, Location l)
1860                         : base (name, parameters, l)
1861                 {
1862                         ReturnType = return_type;
1863                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1864                         OptAttributes = attrs;
1865                 }
1866
1867                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1868                 {
1869                         MethodInfo mi;
1870
1871                         if (! (m is MethodInfo))
1872                                 return false;
1873
1874                         MethodSignature sig = (MethodSignature) filter_criteria;
1875
1876                         if (m.Name != sig.Name)
1877                                 return false;
1878                         
1879                         mi = (MethodInfo) m;
1880
1881                         if (mi.ReturnType != sig.RetType)
1882                                 return false;
1883
1884                         Type [] args = TypeManager.GetArgumentTypes (mi);
1885                         Type [] sigp = sig.Parameters;
1886
1887                         if (args.Length != sigp.Length)
1888                                 return false;
1889
1890                         for (int i = args.Length; i > 0; ){
1891                                 i--;
1892                                 if (args [i] != sigp [i])
1893                                         return false;
1894                         }
1895                         return true;
1896                 }
1897                 
1898                 /// <summary>
1899                 ///    This delegate is used to extract methods which have the
1900                 ///    same signature as the argument
1901                 /// </summary>
1902                 static MemberFilter method_signature_filter;
1903                 
1904                 static Method ()
1905                 {
1906                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
1907                         return;
1908                 }
1909                 
1910                 //
1911                 // Returns the `System.Type' for the ReturnType of this
1912                 // function.  Provides a nice cache.  (used between semantic analysis
1913                 // and actual code generation
1914                 //
1915                 Type type_return_type;
1916                 
1917                 public Type GetReturnType (TypeContainer parent)
1918                 {
1919                         if (type_return_type == null)
1920                                 type_return_type = RootContext.LookupType (
1921                                         parent, ReturnType, false, Location);
1922                         
1923                         return type_return_type;
1924                 }
1925
1926                 void DuplicatEntryPoint (MethodInfo b)
1927                 {
1928                         Report.Error (
1929                                 17, Location,
1930                                 "Program `" + RootContext.CodeGen.FileName +
1931                                 "'  has more than one entry point defined: `" +
1932                                 b.DeclaringType.Name + "." + b.Name + "'");
1933                 }
1934                 
1935                 //
1936                 // Creates the type
1937                 //
1938                 public override bool Define (TypeContainer parent)
1939                 {
1940                         Type ret_type = GetReturnType (parent);
1941                         Type [] parameters = ParameterTypes (parent);
1942                         bool error = false;
1943                         MethodInfo implementing;
1944                         Type iface_type = null;
1945                         string iface = "", short_name;
1946
1947                         // Check if the return type and arguments were correct
1948                         if (ret_type == null || parameters == null)
1949                                 return false;
1950                         
1951                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
1952                                 return false;
1953
1954                         //
1955                         // verify accessibility
1956                         //
1957                         if (!TypeContainer.AsAccessible (ret_type, ModFlags))
1958                                 return false;
1959
1960                         foreach (Type partype in parameters)
1961                                 if (!TypeContainer.AsAccessible (partype, ModFlags))
1962                                         error = true;
1963
1964                         if (error)
1965                                 return false;
1966
1967                         //
1968                         // Verify if the parent has a type with the same name, and then
1969                         // check whether we have to create a new slot for it or not.
1970                         //
1971                         Type ptype = parent.TypeBuilder.BaseType;
1972
1973                         // ptype is only null for System.Object while compiling corlib.
1974                         if (ptype != null){
1975                                 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1976                                 MemberInfo [] mi, mi_static, mi_instance;
1977
1978                                 mi_static = TypeContainer.FindMembers (
1979                                         ptype, MemberTypes.Method,
1980                                         BindingFlags.Public | BindingFlags.Static, method_signature_filter,
1981                                         ms);
1982
1983                                 mi_instance = TypeContainer.FindMembers (
1984                                         ptype, MemberTypes.Method,
1985                                         BindingFlags.Public | BindingFlags.Instance, method_signature_filter,
1986                                         ms);
1987
1988                                 if (mi_instance != null && mi_instance.Length > 0){
1989                                         mi = mi_instance;
1990                                 } else if (mi_static != null && mi_static.Length > 0)
1991                                         mi = mi_static;
1992                                 else
1993                                         mi = null;
1994                                 
1995                                 if (mi != null && mi.Length > 0){
1996                                         if (!CheckMethodAgainstBase (parent, (MethodInfo) mi [0])){
1997                                                 return false;
1998                                         }
1999                                 } else {
2000                                         if ((ModFlags & Modifiers.NEW) != 0)
2001                                                 WarningNotHiding (parent);
2002                                         
2003                                         if ((ModFlags & Modifiers.OVERRIDE) != 0)
2004                                                 Report.Error (115, Location,
2005                                                               parent.MakeName (Name) +
2006                                                               " no suitable methods found to override");
2007                                 }
2008                         } else if ((ModFlags & Modifiers.NEW) != 0)
2009                                 WarningNotHiding (parent);
2010
2011                         //
2012                         // If we implement an interface, extract the interface name.
2013                         //
2014                         flags = Modifiers.MethodAttr (ModFlags);
2015
2016                         if (Name.IndexOf (".") != -1){
2017                                 int pos = Name.LastIndexOf (".");
2018                                 iface = Name.Substring (0, pos);
2019
2020                                 iface_type = RootContext.LookupType (parent, iface, false, Location);
2021                                 short_name = Name.Substring (pos + 1);
2022
2023                                 if (iface_type == null)
2024                                         return false;
2025
2026                                 // Compute the full name that we need to export
2027                                 Name = iface_type.FullName + "." + short_name;
2028                         } else
2029                                 short_name = Name;
2030
2031                         //
2032                         // Check if we are an implementation of an interface method or
2033                         // a method
2034                         //
2035                         implementing = parent.IsInterfaceMethod (
2036                                 iface_type, short_name, ret_type, parameters, false);
2037                                 
2038                         //
2039                         // For implicit implementations, make sure we are public, for
2040                         // explicit implementations, make sure we are private.
2041                         //
2042                         if (implementing != null){
2043                                 //
2044                                 // Setting null inside this block will trigger a more
2045                                 // verbose error reporting for missing interface implementations
2046                                 //
2047                                 // The "candidate" function has been flagged already
2048                                 // but it wont get cleared
2049                                 //
2050                                 if (iface_type == null){
2051                                         if ((ModFlags & Modifiers.PUBLIC) == 0)
2052                                                 implementing = null;
2053
2054                                         if ((ModFlags & Modifiers.STATIC) != 0)
2055                                                 implementing = null;
2056                                 } else {
2057                                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2058                                                 Report.Error (
2059                                                         106, Location, "`public' or `abstract' modifiers "+
2060                                                         "are not allowed in explicit interface declarations"
2061                                                         );
2062                                                 implementing = null;
2063                                         }
2064                                 }
2065                         }
2066                         
2067                         //
2068                         // If implementing is still valid, set flags
2069                         //
2070                         if (implementing != null){
2071                                 flags |=
2072                                         MethodAttributes.Virtual |
2073                                         MethodAttributes.NewSlot |
2074                                         MethodAttributes.HideBySig;
2075
2076                                 // If not abstract, then we can set Final.
2077                                 if (((flags & MethodAttributes.Abstract) == 0) &&
2078                                     implementing.DeclaringType.IsInterface)
2079                                         flags |= MethodAttributes.Final;
2080
2081                                 //
2082                                 // clear the flag
2083                                 //
2084                                 parent.IsInterfaceMethod (
2085                                         iface_type, short_name, ret_type, parameters, true);
2086                         } 
2087
2088                         Attribute dllimport_attr = null;
2089                         if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2090                                 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2091                                         if (asec.Attributes == null)
2092                                                 continue;
2093                                         
2094                                         foreach (Attribute a in asec.Attributes)
2095                                                 if (a.Name.IndexOf ("DllImport") != -1) {
2096                                                         flags |= MethodAttributes.PinvokeImpl;
2097                                                         dllimport_attr = a;
2098                                                 }
2099                                 }
2100                         }
2101
2102                         //
2103                         // Finally, define the method
2104                         //
2105
2106                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2107                                 EmitContext ec = new EmitContext (
2108                                         parent, Location, null, GetReturnType (parent), ModFlags);
2109                                 
2110                                 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2111                                         ec, parent.TypeBuilder,
2112                                         Name, flags, ret_type, parameters);
2113                         } else {
2114                                 MethodBuilder = parent.TypeBuilder.DefineMethod (
2115                                         Name, flags,
2116                                         GetCallingConvention (parent is Class),
2117                                         ret_type, parameters);
2118
2119                                 if (implementing != null){
2120                                         parent.TypeBuilder.DefineMethodOverride (
2121                                                 MethodBuilder, implementing);
2122                                 }
2123                         }
2124
2125                         if (MethodBuilder == null)
2126                                 return false;
2127
2128                         //
2129                         // HACK because System.Reflection.Emit is lame
2130                         //
2131                         ParameterInfo = new InternalParameters (parent, Parameters);
2132
2133                         if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2134                                                          parameters)) {
2135                                 Report.Error (
2136                                         111, Location,
2137                                         "Class `" + parent.Name + "' already contains a definition with " +
2138                                         " the same return value and parameter types for method `" +
2139                                         Name + "'");
2140                                 return false;
2141                         }
2142                         
2143                         //
2144                         // This is used to track the Entry Point,
2145                         //
2146                         // FIXME: Allow pluggable entry point, check arguments, etc.
2147                         //
2148                         if (Name == "Main" &&
2149                             ((ModFlags & Modifiers.STATIC) != 0) && 
2150                             (RootContext.MainClass == null ||
2151                              RootContext.MainClass == parent.TypeBuilder.FullName)){
2152                                 if (RootContext.EntryPoint != null){
2153                                         DuplicatEntryPoint (MethodBuilder);
2154                                         DuplicatEntryPoint (RootContext.EntryPoint);
2155                                 } else 
2156                                         RootContext.EntryPoint = MethodBuilder;
2157                                 
2158                                 //
2159                                 // FIXME: Verify that the method signature
2160                                 // is valid for an entry point, and report
2161                                 // error 28 if not.
2162                                 //
2163                         }
2164                         
2165                         //
2166                         // Define each type attribute (in/out/ref) and
2167                         // the argument names.
2168                         //
2169                         Parameter [] p = Parameters.FixedParameters;
2170                         if (p != null){
2171                                 int i;
2172                                 
2173                                 for (i = 0; i < p.Length; i++) 
2174                                         MethodBuilder.DefineParameter (
2175                                                       i + 1, p [i].Attributes, p [i].Name);
2176                                         
2177                                 if (i != parameters.Length) {
2178                                         ParameterBuilder pb;
2179                                         
2180                                         Parameter array_param = Parameters.ArrayParameter;
2181                                         pb = MethodBuilder.DefineParameter (
2182                                                 i + 1, array_param.Attributes,
2183                                                 array_param.Name);
2184
2185                                         CustomAttributeBuilder a = new CustomAttributeBuilder (
2186                                                 TypeManager.cons_param_array_attribute, new object [0]);
2187
2188                                         pb.SetCustomAttribute (a);
2189                                 }
2190                         }
2191
2192                         return true;
2193                 }
2194
2195                 //
2196                 // Emits the code
2197                 // 
2198                 public void Emit (TypeContainer parent)
2199                 {
2200                         if ((flags & MethodAttributes.PinvokeImpl) != 0)
2201                                 return;
2202
2203                         ILGenerator ig = MethodBuilder.GetILGenerator ();
2204                         EmitContext ec = new EmitContext (parent, Location, ig,
2205                                                           GetReturnType (parent), ModFlags);
2206
2207                         Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2208                         
2209                         
2210                         //
2211                         // abstract or extern methods have no bodies
2212                         //
2213                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2214                                 return;
2215
2216                         //
2217                         // Handle destructors specially
2218                         //
2219                         // FIXME: This code generates buggy code
2220                         //
2221                         if (Name == "Finalize" && type_return_type == TypeManager.void_type){
2222                                 Label end = ig.BeginExceptionBlock ();
2223                                 Label finish = ig.DefineLabel ();
2224                                 bool old_in_try = ec.InTry;
2225                                 ec.InTry = true;
2226                                 ec.EmitTopBlock (Block, Location);
2227                                 ig.Emit (OpCodes.Leave, finish);
2228                                 ec.InTry = old_in_try;
2229
2230                                 bool old_in_finally = ec.InFinally;
2231                                 ec.InFinally = true;
2232                                 ig.BeginFinallyBlock ();
2233 //                              throw new Exception ("IMPLEMENT BASE ACCESS!");
2234                                 // DONT FORGET TO SET THE EC VARIABLES.
2235                                 Console.WriteLine ("Implement base access here");
2236
2237                                 ec.InFinally = old_in_finally;
2238                                 ig.EndExceptionBlock ();
2239                         } else
2240                                 ec.EmitTopBlock (Block, Location);
2241                 }
2242         }
2243
2244         public abstract class ConstructorInitializer {
2245                 ArrayList argument_list;
2246                 ConstructorInfo parent_constructor;
2247                 Location location;
2248                 
2249                 public ConstructorInitializer (ArrayList argument_list, Location location)
2250                 {
2251                         this.argument_list = argument_list;
2252                         this.location = location;
2253                 }
2254
2255                 public ArrayList Arguments {
2256                         get {
2257                                 return argument_list;
2258                         }
2259                 }
2260
2261                 public bool Resolve (EmitContext ec)
2262                 {
2263                         Expression parent_constructor_group;
2264                         Type t;
2265                         
2266                         if (argument_list != null){
2267                                 for (int i = argument_list.Count; i > 0; ){
2268                                         --i;
2269
2270                                         Argument a = (Argument) argument_list [i];
2271                                         if (!a.Resolve (ec, location))
2272                                                 return false;
2273                                 }
2274                         }
2275
2276                         if (this is ConstructorBaseInitializer)
2277                                 t = ec.TypeContainer.TypeBuilder.BaseType;
2278                         else
2279                                 t = ec.TypeContainer.TypeBuilder;
2280                         
2281                         parent_constructor_group = Expression.MemberLookup (
2282                                 ec, t, ".ctor", true,
2283                                 MemberTypes.Constructor,
2284                                 BindingFlags.Public | BindingFlags.Instance, location);
2285                         
2286                         if (parent_constructor_group == null){
2287                                 Console.WriteLine ("Could not find a constructor in our parent");
2288                                 return false;
2289                         }
2290                         
2291                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2292                                 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2293                         
2294                         if (parent_constructor == null){
2295                                 Console.WriteLine ("Could not locate a proper overload function");
2296                                 return false;
2297                         }
2298                         
2299                         return true;
2300                 }
2301
2302                 public void Emit (EmitContext ec)
2303                 {
2304                         ec.ig.Emit (OpCodes.Ldarg_0);
2305                         if (argument_list != null)
2306                                 Invocation.EmitArguments (ec, null, argument_list);
2307                         ec.ig.Emit (OpCodes.Call, parent_constructor);
2308                 }
2309         }
2310
2311         public class ConstructorBaseInitializer : ConstructorInitializer {
2312                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2313                 {
2314                 }
2315         }
2316
2317         public class ConstructorThisInitializer : ConstructorInitializer {
2318                 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2319                 {
2320                 }
2321         }
2322         
2323         public class Constructor : MethodCore {
2324                 public ConstructorBuilder ConstructorBuilder;
2325                 public ConstructorInitializer Initializer;
2326                 public Attributes OptAttributes;
2327
2328                 // <summary>
2329                 //   Modifiers allowed for a constructor.
2330                 // </summary>
2331                 const int AllowedModifiers =
2332                         Modifiers.PUBLIC |
2333                         Modifiers.PROTECTED |
2334                         Modifiers.INTERNAL |
2335                         Modifiers.STATIC |
2336                         Modifiers.PRIVATE;
2337
2338                 //
2339                 // The spec claims that static is not permitted, but
2340                 // my very own code has static constructors.
2341                 //
2342                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2343                         : base (name, args, l)
2344                 {
2345                         Initializer = init;
2346                 }
2347
2348                 //
2349                 // Returns true if this is a default constructor
2350                 //
2351                 public bool IsDefault ()
2352                 {
2353                         if ((ModFlags & Modifiers.STATIC) != 0)
2354                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2355                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2356                         
2357                         else
2358                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2359                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2360                                         (Initializer is ConstructorBaseInitializer) &&
2361                                         (Initializer.Arguments == null);
2362                 }
2363
2364                 //
2365                 // Creates the ConstructorBuilder
2366                 //
2367                 public override bool Define (TypeContainer parent)
2368                 {
2369                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2370                                                MethodAttributes.SpecialName);
2371
2372                         Type [] parameters = ParameterTypes (parent);
2373
2374                         if ((ModFlags & Modifiers.STATIC) != 0)
2375                                 ca |= MethodAttributes.Static;
2376                         else {
2377                                 if (parent is Struct && parameters.Length == 0){
2378                                         Report.Error (
2379                                                 568, Location, 
2380                                                 "Structs can not contain explicit parameterless " +
2381                                                 "constructors");
2382                                         return false;
2383                                 }
2384                                 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2385                         }
2386
2387                         foreach (Type partype in parameters)
2388                                 if (!TypeContainer.AsAccessible (partype, ModFlags))
2389                                         return false;
2390
2391                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2392                                 ca, GetCallingConvention (parent is Class), parameters);
2393
2394                         //
2395                         // HACK because System.Reflection.Emit is lame
2396                         //
2397                         ParameterInfo = new InternalParameters (parent, Parameters);
2398
2399                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2400                                 Report.Error (
2401                                         111, Location,
2402                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2403                                         "same return value and parameter types for constructor `" + Name
2404                                         + "'");
2405                                 return false;
2406                         }
2407                                 
2408                         return true;
2409                 }
2410
2411                 //
2412                 // Emits the code
2413                 //
2414                 public void Emit (TypeContainer parent)
2415                 {
2416                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2417                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2418
2419                         if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2420                                 if (Initializer == null)
2421                                         Initializer = new ConstructorBaseInitializer (null, parent.Location);
2422                                 
2423                                 if (!Initializer.Resolve (ec)){
2424                                         Console.WriteLine ("Could not resolve initializer: " + parent.Name);
2425                                 }
2426                         }
2427
2428                         //
2429                         // Classes can have base initializers and instance field initializers.
2430                         //
2431                         if (parent is Class){
2432                                 if ((ModFlags & Modifiers.STATIC) == 0){
2433                                         Initializer.Emit (ec);
2434                                         parent.EmitFieldInitializers (ec, false);
2435                                 }
2436                         }
2437                         
2438                         if ((ModFlags & Modifiers.STATIC) != 0)
2439                                 parent.EmitFieldInitializers (ec, true);
2440
2441                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2442
2443                         ec.EmitTopBlock (Block, Location);
2444                 }
2445         }
2446         
2447         public class Field : MemberCore {
2448                 public readonly string Type;
2449                 public readonly Object Initializer;
2450                 public readonly Attributes OptAttributes;
2451                 public FieldBuilder  FieldBuilder;
2452                 
2453                 // <summary>
2454                 //   Modifiers allowed in a class declaration
2455                 // </summary>
2456                 const int AllowedModifiers =
2457                         Modifiers.NEW |
2458                         Modifiers.PUBLIC |
2459                         Modifiers.PROTECTED |
2460                         Modifiers.INTERNAL |
2461                         Modifiers.PRIVATE |
2462                         Modifiers.STATIC |
2463                         Modifiers.READONLY;
2464
2465                 public Field (string type, int mod, string name, Object expr_or_array_init,
2466                               Attributes attrs, Location loc)
2467                         : base (name, loc)
2468                 {
2469                         Type = type;
2470                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
2471                         Initializer = expr_or_array_init;
2472                         OptAttributes = attrs;
2473                 }
2474
2475                 public override bool Define (TypeContainer parent)
2476                 {
2477                         Type t = RootContext.LookupType (parent, Type, false, Location);
2478
2479                         if (t == null)
2480                                 return false;
2481
2482                         if (!TypeContainer.AsAccessible (t, ModFlags))
2483                                 return false;
2484
2485                         if (RootContext.WarningLevel > 1){
2486                                 Type ptype = parent.TypeBuilder.BaseType;
2487
2488                                 // ptype is only null for System.Object while compiling corlib.
2489                                 if (ptype != null){
2490                                         MemberInfo [] mi;
2491                                         
2492                                         mi = TypeContainer.FindMembers (
2493                                                 ptype, MemberTypes.Method,
2494                                                 BindingFlags.Public |
2495                                                 BindingFlags.Static | BindingFlags.Instance,
2496                                                 System.Type.FilterName, Name);
2497                                 }
2498                         }
2499                         
2500                         FieldBuilder = parent.TypeBuilder.DefineField (
2501                                 Name, t, Modifiers.FieldAttr (ModFlags));
2502
2503                         return true;
2504                 }
2505
2506                 public void Emit (TypeContainer tc)
2507                 {
2508                         EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
2509
2510                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location); 
2511                 }
2512         }
2513
2514         public class Property : MemberCore {
2515                 public readonly string Type;
2516                 public Block           Get, Set;
2517                 public PropertyBuilder PropertyBuilder;
2518                 public Attributes OptAttributes;
2519                 MethodBuilder GetBuilder, SetBuilder;
2520
2521                 //
2522                 // The type, once we compute it.
2523                 
2524                 Type PropertyType;
2525
2526                 const int AllowedModifiers =
2527                         Modifiers.NEW |
2528                         Modifiers.PUBLIC |
2529                         Modifiers.PROTECTED |
2530                         Modifiers.INTERNAL |
2531                         Modifiers.PRIVATE |
2532                         Modifiers.STATIC |
2533                         Modifiers.SEALED |
2534                         Modifiers.OVERRIDE |
2535                         Modifiers.ABSTRACT |
2536                         Modifiers.VIRTUAL;
2537
2538                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2539                                  Attributes attrs, Location loc)
2540                         : base (name, loc)
2541                 {
2542                         Type = type;
2543                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2544                         Get = get_block;
2545                         Set = set_block;
2546                         OptAttributes = attrs;
2547                 }
2548
2549                 //
2550                 // Checks our base implementation if any
2551                 //
2552                 bool CheckBase (TypeContainer parent)
2553                 {
2554                         //
2555                         // Find properties with the same name on the base class
2556                         //
2557                         MemberInfo [] props;
2558                         MemberInfo [] props_static = TypeContainer.FindMembers (
2559                                 parent.TypeBuilder.BaseType,
2560                                 MemberTypes.All, BindingFlags.Public | BindingFlags.Static,
2561                                 System.Type.FilterName, Name);
2562
2563                         MemberInfo [] props_instance = TypeContainer.FindMembers (
2564                                 parent.TypeBuilder.BaseType,
2565                                 MemberTypes.All, BindingFlags.Public | BindingFlags.Instance,
2566                                 System.Type.FilterName, Name);
2567
2568                         //
2569                         // Find if we have anything
2570                         //
2571                         if (props_static != null && props_static.Length > 0)
2572                                 props = props_static;
2573                         else if (props_instance != null && props_instance.Length > 0)
2574                                 props = props_instance;
2575                         else
2576                                 props = null;
2577
2578                         //
2579                         // If we have something on the base.
2580                         if (props != null && props.Length > 0){
2581                                 //
2582                                 // FIXME:
2583                                 // Currently we expect only to get 1 match at most from our
2584                                 // base class, maybe we can get more than one, investigate
2585                                 // whether this is possible
2586                                 //
2587                                 if (props.Length > 1)
2588                                         throw new Exception ("How do we handle this?");
2589                                 
2590                                 PropertyInfo pi = (PropertyInfo) props [0];
2591
2592                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2593                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2594
2595                                 MethodInfo reference = inherited_get == null ?
2596                                         inherited_set : inherited_get;
2597                                 
2598                                 if (!CheckMethodAgainstBase (parent, reference))
2599                                         return false;
2600                         } else {
2601                                 if ((ModFlags & Modifiers.NEW) != 0)
2602                                         WarningNotHiding (parent);
2603                                 
2604                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2605                                         Report.Error (115, Location,
2606                                                       parent.MakeName (Name) +
2607                                                       " no suitable methods found to override");
2608                                         return false;
2609                                 }
2610                         }
2611                         return true;
2612                 }
2613
2614                 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name, bool is_get)
2615                 {
2616                         MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2617                         Type [] parameters = null;
2618                         MethodInfo implementing;
2619                         Type fn_type;
2620                         string name;
2621
2622                         flags |= MethodAttributes.HideBySig |
2623                                 MethodAttributes.SpecialName;
2624                         
2625                         if (is_get){
2626                                 fn_type = PropertyType;
2627                                 name = "get_" + short_name;
2628                         } else {
2629                                 name = "set_" + short_name;
2630                                 parameters = new Type [1];
2631                                 parameters [0] = PropertyType;
2632                                 fn_type = TypeManager.void_type;
2633                         }
2634
2635                         implementing = parent.IsInterfaceMethod (
2636                                 iface_type, name, fn_type, parameters, false);
2637
2638                         //
2639                         // For implicit implementations, make sure we are public, for
2640                         // explicit implementations, make sure we are private.
2641                         //
2642                         if (implementing != null){
2643                                 //
2644                                 // Setting null inside this block will trigger a more
2645                                 // verbose error reporting for missing interface implementations
2646                                 //
2647                                 // The "candidate" function has been flagged already
2648                                 // but it wont get cleared
2649                                 //
2650                                 if (iface_type == null){
2651                                         if ((ModFlags & Modifiers.PUBLIC) == 0)
2652                                                 implementing = null;
2653                                         if ((ModFlags & Modifiers.STATIC) != 0)
2654                                                 implementing = null;
2655                                 } else {
2656                                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2657                                                 Report.Error (
2658                                                         106, Location, "`public' or `abstract' modifiers "+
2659                                                         "are not allowed in explicit interface declarations"
2660                                                         );
2661                                                 implementing = null;
2662                                         }
2663                                 }
2664                         }
2665                         
2666                         //
2667                         // If implementing is still valid, set flags
2668                         //
2669                         if (implementing != null){
2670                                 flags |=
2671                                         MethodAttributes.Virtual |
2672                                         MethodAttributes.NewSlot |
2673                                         MethodAttributes.HideBySig;
2674
2675                                 // If an interface implementation, then we can set Final.
2676                                 if (((flags & MethodAttributes.Abstract) == 0) &&
2677                                     implementing.DeclaringType.IsInterface)
2678                                         flags |= MethodAttributes.Final;
2679                                 
2680                                 //
2681                                 // clear the pending flag
2682                                 //
2683                                 parent.IsInterfaceMethod (
2684                                         iface_type, name, fn_type, parameters, true);
2685                         } 
2686                         
2687                         if (is_get){
2688                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2689                                         name, flags, PropertyType, null);
2690                                 PropertyBuilder.SetGetMethod (GetBuilder);
2691                         
2692                                 if (implementing != null)
2693                                         parent.TypeBuilder.DefineMethodOverride (
2694                                                 GetBuilder, implementing);
2695                                 
2696                                 //
2697                                 // HACK because System.Reflection.Emit is lame
2698                                 //
2699                                 InternalParameters ip = new InternalParameters (
2700                                         parent, Parameters.GetEmptyReadOnlyParameters ());
2701                                 
2702                                 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2703                                         Report.Error (111, Location,
2704                                                       "Class `" + parent.Name +
2705                                                       "' already contains a definition with the " +
2706                                                       "same return value and parameter types as the " +
2707                                                       "'get' method of property `" + Name + "'");
2708                                         return false;
2709                                 }
2710                         } else {
2711                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2712                                         name, flags, null, parameters);
2713                                 
2714                                 if (implementing != null)
2715                                         parent.TypeBuilder.DefineMethodOverride (
2716                                                 SetBuilder, implementing);
2717                                 
2718                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
2719                                 PropertyBuilder.SetSetMethod (SetBuilder);
2720
2721                                 //
2722                                 // HACK because System.Reflection.Emit is lame
2723                                 //
2724                                 Parameter [] parms = new Parameter [1];
2725                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2726                                 InternalParameters ip = new InternalParameters (
2727                                         parent, new Parameters (parms, null, Location));
2728
2729                                 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
2730                                         Report.Error (
2731                                                 111, Location,
2732                                                 "Class `" + parent.Name +
2733                                                 "' already contains a definition with the " +
2734                                                 "same return value and parameter types as the " +
2735                                                 "'set' method of property `" + Name + "'");
2736                                         return false;
2737                                 }
2738                         }
2739
2740                         return true;
2741                 }
2742
2743                 public override bool Define (TypeContainer parent)
2744                 {
2745                         Type iface_type = null;
2746                         string short_name;
2747                         
2748                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2749                                 return false;
2750
2751                         // Lookup Type, verify validity
2752                         PropertyType = RootContext.LookupType (parent, Type, false, Location);
2753                         if (PropertyType == null)
2754                                 return false;
2755
2756                         // verify accessibility
2757                         if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
2758                                 return false;
2759                         
2760                         if (!CheckBase (parent))
2761                                 return false;
2762
2763                         //
2764                         // Check for explicit interface implementation
2765                         //
2766                         if (Name.IndexOf (".") != -1){
2767                                 int pos = Name.LastIndexOf (".");
2768                                 string iface = Name.Substring (0, pos);
2769
2770                                 iface_type = RootContext.LookupType (parent, iface, false, Location);
2771                                 if (iface_type == null)
2772                                         return false;
2773
2774                                 short_name = Name.Substring (pos + 1);
2775
2776                                 // Compute the full name that we need to export.
2777                                 Name = iface_type.FullName + "." + short_name;
2778                         } else
2779                                 short_name = Name;
2780
2781                         // FIXME - PropertyAttributes.HasDefault ?
2782
2783                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2784                                                        PropertyAttributes.SpecialName;
2785                 
2786                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2787                                 Name, prop_attr, PropertyType, null);
2788
2789                         if (Get != null)
2790                                 if (!DefineMethod (parent, iface_type, short_name, true))
2791                                         return false;
2792                         
2793                         if (Set != null)
2794                                 if (!DefineMethod (parent, iface_type, short_name, false))
2795                                         return false;
2796                         
2797                         //
2798                         // HACK for the reasons exposed above
2799                         //
2800                         if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2801                                 Report.Error (
2802                                         111, Location,
2803                                         "Class `" + parent.Name +
2804                                         "' already contains a definition for the property `" +
2805                                         Name + "'");
2806                                 return false;
2807                         }
2808
2809                         return true;
2810                 }
2811                 
2812                 public void Emit (TypeContainer tc)
2813                 {
2814                         ILGenerator ig;
2815                         EmitContext ec;
2816
2817                         ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
2818                         Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
2819                         
2820
2821                         //
2822                         // abstract or extern properties have no bodies
2823                         //
2824                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2825                                 return;
2826
2827                         if (Get != null){
2828                                 ig = GetBuilder.GetILGenerator ();
2829                                 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
2830                                 
2831                                 ec.EmitTopBlock (Get, Location);
2832                         }
2833
2834                         if (Set != null){
2835                                 ig = SetBuilder.GetILGenerator ();
2836                                 ec = new EmitContext (tc, Location, ig, null, ModFlags);
2837                                 
2838                                 ec.EmitTopBlock (Set, Location);
2839                         }
2840                 }
2841         }
2842
2843
2844         /// </summary>
2845         ///  Gigantic workaround  for lameness in SRE follows :
2846         ///  This class derived from EventInfo and attempts to basically
2847         ///  wrap around the EventBuilder so that FindMembers can quickly
2848         ///  return this in it search for members
2849         /// </summary>
2850         public class MyEventBuilder : EventInfo {
2851                 
2852                 //
2853                 // We use this to "point" to our Builder which is
2854                 // not really a MemberInfo
2855                 //
2856                 EventBuilder MyBuilder;
2857                 
2858                 //
2859                 // We "catch" and wrap these methods
2860                 //
2861                 MethodInfo raise, remove, add;
2862
2863                 EventAttributes attributes;
2864                 Type declaring_type, reflected_type, event_type;
2865                 string name;
2866
2867                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
2868                 {
2869                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
2870
2871                         // And now store the values in our own fields.
2872                         
2873                         declaring_type = type_builder;
2874
2875                         // FIXME : This is supposed to be MyBuilder but since that doesn't
2876                         // derive from Type, I have no clue what to do with this.
2877                         reflected_type = null;
2878                         
2879                         attributes = event_attr;
2880                         this.name = name;
2881                         this.event_type = event_type;
2882                 }
2883                 
2884                 //
2885                 // Methods that you have to override.  Note that you only need 
2886                 // to "implement" the variants that take the argument (those are
2887                 // the "abstract" methods, the others (GetAddMethod()) are 
2888                 // regular.
2889                 //
2890                 public override MethodInfo GetAddMethod (bool nonPublic)
2891                 {
2892                         return add;
2893                 }
2894                 
2895                 public override MethodInfo GetRemoveMethod (bool nonPublic)
2896                 {
2897                         return remove;
2898                 }
2899                 
2900                 public override MethodInfo GetRaiseMethod (bool nonPublic)
2901                 {
2902                         return raise;
2903                 }
2904                 
2905                 //
2906                 // These methods make "MyEventInfo" look like a Builder
2907                 //
2908                 public void SetRaiseMethod (MethodBuilder raiseMethod)
2909                 {
2910                         raise = raiseMethod;
2911                         MyBuilder.SetRaiseMethod (raiseMethod);
2912                 }
2913
2914                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
2915                 {
2916                         remove = removeMethod;
2917                         MyBuilder.SetRemoveOnMethod (removeMethod);
2918                 }
2919
2920                 public void SetAddOnMethod (MethodBuilder addMethod)
2921                 {
2922                         add = addMethod;
2923                         MyBuilder.SetAddOnMethod (addMethod);
2924                 }
2925
2926                 public void SetCustomAttribute (CustomAttributeBuilder cb)
2927                 {
2928                         MyBuilder.SetCustomAttribute (cb);
2929                 }
2930                 
2931                 public override object [] GetCustomAttributes (bool inherit)
2932                 {
2933                         // FIXME : There's nothing which can be seemingly done here because
2934                         // we have no way of getting at the custom attribute objects of the
2935                         // EventBuilder !
2936                         return null;
2937                 }
2938
2939                 public override object [] GetCustomAttributes (Type t, bool inherit)
2940                 {
2941                         // FIXME : Same here !
2942                         return null;
2943                 }
2944
2945                 public override bool IsDefined (Type t, bool b)
2946                 {
2947                         return true;
2948                 }
2949
2950                 public override EventAttributes Attributes {
2951                         get {
2952                                 return attributes;
2953                         }
2954                 }
2955
2956                 public override string Name {
2957                         get {
2958                                 return name;
2959                         }
2960                 }
2961
2962                 public override Type DeclaringType {
2963                         get {
2964                                 return declaring_type;
2965                         }
2966                 }
2967
2968                 public override Type ReflectedType {
2969                         get {
2970                                 return reflected_type;
2971                         }
2972                 }
2973
2974                 public Type EventType {
2975                         get {
2976                                 return event_type;
2977                         }
2978                 }
2979         }
2980         
2981         public class Event : MemberCore {
2982                 
2983                 const int AllowedModifiers =
2984                         Modifiers.NEW |
2985                         Modifiers.PUBLIC |
2986                         Modifiers.PROTECTED |
2987                         Modifiers.INTERNAL |
2988                         Modifiers.PRIVATE |
2989                         Modifiers.STATIC |
2990                         Modifiers.VIRTUAL |
2991                         Modifiers.SEALED |
2992                         Modifiers.OVERRIDE |
2993                         Modifiers.ABSTRACT;
2994
2995                 public readonly string    Type;
2996                 public readonly Object    Initializer;
2997                 public readonly Block     Add;
2998                 public readonly Block     Remove;
2999                 public MyEventBuilder     EventBuilder;
3000                 public FieldBuilder       FieldBuilder;
3001                 public Attributes         OptAttributes;
3002
3003                 Type EventType;
3004                 MethodBuilder AddBuilder, RemoveBuilder;
3005                 
3006
3007                 public Event (string type, string name, Object init, int flags, Block add_block,
3008                               Block rem_block, Attributes attrs, Location loc)
3009                         : base (name, loc)
3010                 {
3011                         Type = type;
3012                         Initializer = init;
3013                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
3014                         Add = add_block;
3015                         Remove = rem_block;
3016                         OptAttributes = attrs;
3017                 }
3018
3019                 public override bool Define (TypeContainer parent)
3020                 {
3021                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3022                                 return false;
3023
3024                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3025                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3026
3027                         EventType = RootContext.LookupType (parent, Type, false, Location);
3028                         if (EventType == null)
3029                                 return false;
3030
3031                         if (!TypeContainer.AsAccessible (EventType, ModFlags))
3032                                 return false;
3033                         
3034
3035                         if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3036                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3037                                               "' : event must be of a delegate type");
3038                                 return false;
3039                         }
3040                         
3041                         Type [] parameters = new Type [1];
3042                         parameters [0] = EventType;
3043
3044                         EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3045
3046                         if (Add == null && Remove == null)
3047                                 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3048                         
3049                         //
3050                         // Now define the accessors
3051                         //
3052                         
3053                         AddBuilder = parent.TypeBuilder.DefineMethod (
3054                                                          "add_" + Name, m_attr, null, parameters);
3055                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3056                         EventBuilder.SetAddOnMethod (AddBuilder);
3057
3058                         //
3059                         // HACK because System.Reflection.Emit is lame
3060                         //
3061                         Parameter [] parms = new Parameter [1];
3062                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3063                         InternalParameters ip = new InternalParameters (
3064                                                             parent, new Parameters (parms, null, Location)); 
3065                         
3066                         if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3067                                 Report.Error (111, Location,
3068                                               "Class `" + parent.Name + "' already contains a definition with the " +
3069                                               "same return value and parameter types for the " +
3070                                               "'add' method of event `" + Name + "'");
3071                                 return false;
3072                         }
3073                 
3074                         RemoveBuilder = parent.TypeBuilder.DefineMethod (
3075                                                             "remove_" + Name, m_attr, null, parameters);
3076                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3077                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3078
3079                         //
3080                         // HACK because System.Reflection.Emit is lame
3081                         //
3082
3083                         if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3084                                 Report.Error (111, Location,    
3085                                               "Class `" + parent.Name + "' already contains a definition with the " +
3086                                               "same return value and parameter types for the " +
3087                                               "'remove' method of event `" + Name + "'");
3088                                 return false;
3089                         }
3090                         
3091                         if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3092                                 Report.Error (111, Location,
3093                                         "Class `" + parent.Name +
3094                                         "' already contains a definition for the event `" +
3095                                         Name + "'");
3096                                 return false;
3097                         }
3098                         
3099                         return true;
3100                 }
3101
3102                 void EmitDefaultMethod (EmitContext ec, bool is_add)
3103                 {
3104                         ILGenerator ig = ec.ig;
3105                         MethodInfo method = null;
3106                         
3107                         if (is_add)
3108                                 method = TypeManager.delegate_combine_delegate_delegate;
3109                         else
3110                                 method = TypeManager.delegate_remove_delegate_delegate;
3111                         
3112                         ig.Emit (OpCodes.Ldarg_0);
3113                         ig.Emit (OpCodes.Ldarg_0);
3114                         ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3115                         ig.Emit (OpCodes.Ldarg_1);
3116                         ig.Emit (OpCodes.Call, method);
3117                         ig.Emit (OpCodes.Castclass, EventType);
3118                         ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3119                         ig.Emit (OpCodes.Ret);
3120                 }
3121
3122                 public void Emit (TypeContainer tc)
3123                 {
3124                         EmitContext ec;
3125                         ILGenerator ig;
3126
3127                         ig = AddBuilder.GetILGenerator ();
3128                         ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3129
3130                         if (Add != null)
3131                                 ec.EmitTopBlock (Add, Location);
3132                         else
3133                                 EmitDefaultMethod (ec, true);
3134
3135                         ig = RemoveBuilder.GetILGenerator ();
3136                         ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3137                         
3138                         if (Remove != null)
3139                                 ec.EmitTopBlock (Remove, Location);
3140                         else
3141                                 EmitDefaultMethod (ec, false);
3142
3143                         ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3144                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3145                         
3146                 }
3147                 
3148         }
3149
3150         //
3151         // FIXME: This does not handle:
3152         //
3153         //   int INTERFACENAME [ args ]
3154         //
3155         // Only:
3156         // 
3157         // int this [ args ]
3158  
3159         public class Indexer : MemberCore {
3160
3161                 const int AllowedModifiers =
3162                         Modifiers.NEW |
3163                         Modifiers.PUBLIC |
3164                         Modifiers.PROTECTED |
3165                         Modifiers.INTERNAL |
3166                         Modifiers.PRIVATE |
3167                         Modifiers.VIRTUAL |
3168                         Modifiers.SEALED |
3169                         Modifiers.OVERRIDE |
3170                         Modifiers.ABSTRACT;
3171
3172                 public readonly string     Type;
3173                 public readonly string     InterfaceType;
3174                 public readonly Parameters FormalParameters;
3175                 public readonly Block      Get;
3176                 public readonly Block      Set;
3177                 public Attributes          OptAttributes;
3178                 public MethodBuilder       GetBuilder;
3179                 public MethodBuilder       SetBuilder;
3180                 public PropertyBuilder PropertyBuilder;
3181                 public Type IndexerType;
3182
3183                 public Indexer (string type, string int_type, int flags, Parameters parms,
3184                                 Block get_block, Block set_block, Attributes attrs, Location loc)
3185                         : base ("", loc)
3186                 {
3187
3188                         Type = type;
3189                         InterfaceType = int_type;
3190                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
3191                         FormalParameters = parms;
3192                         Get = get_block;
3193                         Set = set_block;
3194                         OptAttributes = attrs;
3195                 }
3196
3197                 void DefineMethod (TypeContainer parent, Type iface_type,
3198                                    Type ret_type, string name,
3199                                    Type [] parameters, bool is_get)
3200                 {
3201                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3202                         MethodInfo implementing;
3203
3204                         implementing = parent.IsInterfaceMethod (
3205                                 iface_type, name, ret_type, parameters, false);
3206
3207                         //
3208                         // Setting null inside this block will trigger a more
3209                         // verbose error reporting for missing interface implementations
3210                         //
3211                         // The "candidate" function has been flagged already
3212                         // but it wont get cleared
3213                         //
3214                         if (implementing != null){
3215                                 if (iface_type == null){
3216                                         if ((ModFlags & Modifiers.PUBLIC) == 0)
3217                                                 implementing = null;
3218                                         if ((ModFlags & Modifiers.STATIC) != 0)
3219                                                 implementing = null;
3220                                 } else {
3221                                         if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3222                                                 Report.Error (
3223                                                         106, Location,
3224                                                         "`public' or `abstract' modifiers are not "+
3225                                                         "allowed in explicit interface declarations"
3226                                                         );
3227                                                 implementing = null;
3228                                         }
3229                                 }
3230                         }
3231                         if (implementing != null){
3232                                 attr |=
3233                                         MethodAttributes.Virtual |
3234                                         MethodAttributes.NewSlot |
3235                                         MethodAttributes.HideBySig;
3236
3237                                 // If an interface implementing, then we can set final.
3238                                 if (((attr & MethodAttributes.Abstract) == 0) &&
3239                                     implementing.DeclaringType.IsInterface)
3240                                         attr |= MethodAttributes.Final;
3241                                 
3242                                 //
3243                                 // clear the pending flag
3244                                 //
3245                                 parent.IsInterfaceMethod (
3246                                         iface_type, name, ret_type, parameters, true);
3247                         }
3248
3249                         if (is_get){
3250                                 GetBuilder = parent.TypeBuilder.DefineMethod (
3251                                         "get_Item", attr, IndexerType, parameters);
3252                                 if (implementing != null)
3253                                         parent.TypeBuilder.DefineMethodOverride (
3254                                                 GetBuilder, implementing);
3255
3256                                 PropertyBuilder.SetGetMethod (GetBuilder);
3257                         } else {
3258                                 SetBuilder = parent.TypeBuilder.DefineMethod (
3259                                         "set_Item", attr, null, parameters);
3260                                 if (implementing != null)
3261                                         parent.TypeBuilder.DefineMethodOverride (
3262                                                 SetBuilder, implementing);
3263                                         
3264                                 PropertyBuilder.SetSetMethod (SetBuilder);
3265                         }
3266                 }
3267                         
3268                 public override bool Define (TypeContainer parent)
3269                 {
3270                         PropertyAttributes prop_attr =
3271                                 PropertyAttributes.RTSpecialName |
3272                                 PropertyAttributes.SpecialName;
3273                         bool error = false;
3274                         
3275                         IndexerType = RootContext.LookupType (parent, Type, false, Location);
3276                         Type [] parameters = FormalParameters.GetParameterInfo (parent);
3277
3278                         // Check if the return type and arguments were correct
3279                         if (IndexerType == null || parameters == null)
3280                                 return false;
3281
3282                         //
3283                         // verify accessibility
3284                         //
3285                         if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3286                                 return false;
3287
3288                         foreach (Type partype in parameters)
3289                                 if (!TypeContainer.AsAccessible (partype, ModFlags))
3290                                         error = true;
3291
3292                         if (error)
3293                                 return false;
3294                         
3295                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
3296                                 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3297                                 prop_attr, IndexerType, parameters);
3298
3299                         //
3300                         // FIXME: Implement explicit implementation
3301                         //
3302                         Type iface_type = null;
3303                         
3304                         if (Get != null){
3305                                 DefineMethod (parent, iface_type, IndexerType, "get_Item", parameters, true);
3306                                 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3307                                 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3308                                         Report.Error (111, Location,
3309                                                       "Class `" + parent.Name +
3310                                                       "' already contains a definition with the " +
3311                                                       "same return value and parameter types for the " +
3312                                                       "'get' indexer");
3313                                         return false;
3314                                 }
3315                         }
3316                         
3317                         if (Set != null){
3318                                 int top = parameters.Length;
3319                                 Type [] set_pars = new Type [top + 1];
3320                                 parameters.CopyTo (set_pars, 0);
3321                                 set_pars [top] = IndexerType;
3322
3323                                 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3324
3325                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3326
3327                                 fixed_parms.CopyTo (tmp, 0);
3328                                 tmp [fixed_parms.Length] = new Parameter (
3329                                         Type, "value", Parameter.Modifier.NONE, null);
3330
3331                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
3332                                 
3333                                 DefineMethod (
3334                                         parent, iface_type, TypeManager.void_type,
3335                                         "set_Item", set_pars, false);
3336
3337                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3338                                 
3339                                 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3340                                         Report.Error (
3341                                                 111, Location,
3342                                                 "Class `" + parent.Name + "' already contains a " +
3343                                                 "definition with the " +
3344                                                 "same return value and parameter types for the " +
3345                                                 "'set' indexer");
3346                                         return false;
3347                                 }
3348                         }
3349
3350                         //
3351                         // Now name the parameters
3352                         //
3353                         Parameter [] p = FormalParameters.FixedParameters;
3354                         if (p != null) {
3355                                 int i;
3356                                 
3357                                 for (i = 0; i < p.Length; ++i) {
3358                                         if (Get != null)
3359                                                 GetBuilder.DefineParameter (
3360                                                         i + 1, p [i].Attributes, p [i].Name);
3361
3362                                         if (Set != null)
3363                                                 SetBuilder.DefineParameter (
3364                                                         i + 1, p [i].Attributes, p [i].Name);
3365                                 }
3366
3367                                 if (Set != null)
3368                                         SetBuilder.DefineParameter (
3369                                                 i + 1, ParameterAttributes.None, "value");
3370                                         
3371                                 if (i != parameters.Length) {
3372                                         Parameter array_param = FormalParameters.ArrayParameter;
3373                                         SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3374                                                                     array_param.Name);
3375                                 }
3376                         }
3377
3378                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3379
3380                         return true;
3381                 }
3382
3383                 public void Emit (TypeContainer tc)
3384                 {
3385                         ILGenerator ig;
3386                         EmitContext ec;
3387
3388                         ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3389                         Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3390
3391                         if (Get != null){
3392                                 ig = GetBuilder.GetILGenerator ();
3393                                 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3394                                 
3395                                 ec.EmitTopBlock (Get, Location);
3396                         }
3397
3398                         if (Set != null){
3399                                 ig = SetBuilder.GetILGenerator ();
3400                                 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3401                                 
3402                                 ec.EmitTopBlock (Set, Location);
3403                         }
3404                 }
3405         }
3406
3407         public class Operator : MemberCore {
3408
3409                 const int AllowedModifiers =
3410                         Modifiers.PUBLIC |
3411                         Modifiers.STATIC;
3412
3413                 const int RequiredModifiers =
3414                         Modifiers.PUBLIC |
3415                         Modifiers.STATIC;
3416
3417                 public enum OpType : byte {
3418
3419                         // Unary operators
3420                         LogicalNot,
3421                         OnesComplement,
3422                         Increment,
3423                         Decrement,
3424                         True,
3425                         False,
3426
3427                         // Unary and Binary operators
3428                         Addition,
3429                         Subtraction,
3430
3431                         UnaryPlus,
3432                         UnaryNegation,
3433                         
3434                         // Binary operators
3435                         Multiply,
3436                         Division,
3437                         Modulus,
3438                         BitwiseAnd,
3439                         BitwiseOr,
3440                         ExclusiveOr,
3441                         LeftShift,
3442                         RightShift,
3443                         Equality,
3444                         Inequality,
3445                         GreaterThan,
3446                         LessThan,
3447                         GreaterThanOrEqual,
3448                         LessThanOrEqual,
3449
3450                         // Implicit and Explicit
3451                         Implicit,
3452                         Explicit
3453                 };
3454
3455                 public readonly OpType OperatorType;
3456                 public readonly string ReturnType;
3457                 public readonly string FirstArgType;
3458                 public readonly string FirstArgName;
3459                 public readonly string SecondArgType;
3460                 public readonly string SecondArgName;
3461                 public readonly Block  Block;
3462                 public Attributes      OptAttributes;
3463                 public MethodBuilder   OperatorMethodBuilder;
3464                 
3465                 public string MethodName;
3466                 public Method OperatorMethod;
3467
3468                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3469                                  string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3470                         : base ("", loc)
3471                 {
3472                         OperatorType = type;
3473                         ReturnType = ret_type;
3474                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
3475                         FirstArgType = arg1type;
3476                         FirstArgName = arg1name;
3477                         SecondArgType = arg2type;
3478                         SecondArgName = arg2name;
3479                         Block = block;
3480                         OptAttributes = attrs;
3481                 }
3482
3483                 string Prototype (TypeContainer parent)
3484                 {
3485                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3486                                 SecondArgType + ")";
3487                 }
3488                 
3489                 public override bool Define (TypeContainer parent)
3490                 {
3491                         int length = 1;
3492                         MethodName = "op_" + OperatorType;
3493                         
3494                         if (SecondArgType != null)
3495                                 length = 2;
3496                         
3497                         Parameter [] param_list = new Parameter [length];
3498
3499                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3500                                 Report.Error (
3501                                         558, Location, 
3502                                         "User defined operators `" +
3503                                         Prototype (parent) +
3504                                         "' must be declared static and public");
3505                                 return false;
3506                         }
3507
3508                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
3509                                                        Parameter.Modifier.NONE, null);
3510                         if (SecondArgType != null)
3511                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3512                                                                Parameter.Modifier.NONE, null);
3513                         
3514                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3515                                                      new Parameters (param_list, null, Location),
3516                                                      OptAttributes, Mono.CSharp.Location.Null);
3517                         
3518                         OperatorMethod.Define (parent);
3519
3520                         if (OperatorMethod.MethodBuilder == null)
3521                                 return false;
3522                         
3523                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3524
3525                         Type [] param_types = OperatorMethod.ParameterTypes (parent);
3526                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
3527                         Type return_type = OperatorMethod.GetReturnType (parent);
3528                         Type first_arg_type = param_types [0];
3529
3530                         // Rules for conversion operators
3531                         
3532                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3533                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
3534                                         Report.Error (
3535                                                 555, Location,
3536                                                 "User-defined conversion cannot take an object of the " +
3537                                                 "enclosing type and convert to an object of the enclosing" +
3538                                                 " type");
3539                                         return false;
3540                                 }
3541                                 
3542                                 if (first_arg_type != declaring_type && return_type != declaring_type){
3543                                         Report.Error (
3544                                                 556, Location, 
3545                                                 "User-defined conversion must convert to or from the " +
3546                                                 "enclosing type");
3547                                         return false;
3548                                 }
3549                                 
3550                                 if (first_arg_type == TypeManager.object_type ||
3551                                     return_type == TypeManager.object_type){
3552                                         Report.Error (
3553                                                 -8, Location,
3554                                                 "User-defined conversion cannot convert to or from " +
3555                                                 "object type");
3556                                         return false;
3557                                 }
3558
3559                                 if (first_arg_type.IsInterface || return_type.IsInterface){
3560                                         Report.Error (
3561                                                 552, Location,
3562                                                 "User-defined conversion cannot convert to or from an " +
3563                                                 "interface type");
3564                                         return false;
3565                                 }
3566                                 
3567                                 if (first_arg_type.IsSubclassOf (return_type) ||
3568                                     return_type.IsSubclassOf (first_arg_type)){
3569                                         Report.Error (
3570                                                 -10, Location,
3571                                                 "User-defined conversion cannot convert between types " +
3572                                                 "that derive from each other");
3573                                         return false;
3574                                 }
3575                         } else if (SecondArgType == null) {
3576                                 // Checks for Unary operators
3577                                 
3578                                 if (first_arg_type != declaring_type){
3579                                         Report.Error (
3580                                                 562, Location,
3581                                                 "The parameter of a unary operator must be the " +
3582                                                 "containing type");
3583                                         return false;
3584                                 }
3585                                 
3586                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3587                                         if (return_type != declaring_type){
3588                                                 Report.Error (
3589                                                         559, Location,
3590                                                         "The parameter and return type for ++ and -- " +
3591                                                         "must be the containing type");
3592                                                 return false;
3593                                         }
3594                                         
3595                                 }
3596                                 
3597                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3598                                         if (return_type != TypeManager.bool_type){
3599                                                 Report.Error (
3600                                                         215, Location,
3601                                                         "The return type of operator True or False " +
3602                                                         "must be bool");
3603                                                 return false;
3604                                         }
3605                                 }
3606                                 
3607                         } else {
3608                                 // Checks for Binary operators
3609                                 
3610                                 if (first_arg_type != declaring_type &&
3611                                     param_types [1] != declaring_type){
3612                                         Report.Error (
3613                                                 563, Location,
3614                                                 "One of the parameters of a binary operator must " +
3615                                                 "be the containing type");
3616                                         return false;
3617                                 }
3618                         }
3619
3620                         return true;
3621                 }
3622                 
3623                 public void Emit (TypeContainer parent)
3624                 {
3625                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3626                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3627                         
3628                         OperatorMethod.Block = Block;
3629                         OperatorMethod.Emit (parent);
3630                 }
3631         }
3632
3633         //
3634         // This is used to compare method signatures
3635         //
3636         struct MethodSignature {
3637                 public string Name;
3638                 public Type RetType;
3639                 public Type [] Parameters;
3640                 
3641                 public MethodSignature (string name, Type ret_type, Type [] parameters)
3642                 {
3643                         Name = name;
3644                         RetType = ret_type;
3645                         Parameters = parameters;
3646                 }
3647                 
3648                 public override int GetHashCode ()
3649                 {
3650                         return Name.GetHashCode ();
3651                 }
3652
3653                 public override bool Equals (Object o)
3654                 {
3655                         MethodSignature other = (MethodSignature) o;
3656
3657                         if (other.Name != Name)
3658                                 return false;
3659
3660                         if (other.RetType != RetType)
3661                                 return false;
3662                         
3663                         if (Parameters == null){
3664                                 if (other.Parameters == null)
3665                                         return true;
3666                                 return false;
3667                         }
3668
3669                         if (other.Parameters == null)
3670                                 return false;
3671                         
3672                         int c = Parameters.Length;
3673                         if (other.Parameters.Length != c)
3674                                 return false;
3675
3676                         for (int i = 0; i < c; i++)
3677                                 if (other.Parameters [i] != Parameters [i])
3678                                         return false;
3679
3680                         return true;
3681                 }
3682         }               
3683 }