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