2001-10-17 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / class.cs
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 //
11
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System;
16
17 namespace CIR {
18         
19         public class TypeContainer : DeclSpace {
20                 protected int mod_flags;
21
22                 // Holds a list of classes and structures
23                 ArrayList types;
24
25                 // Holds the list of properties
26                 ArrayList properties;
27
28                 // Holds the list of enumerations
29                 ArrayList enums;
30
31                 // Holds the list of delegates
32                 ArrayList delegates;
33                 
34                 // Holds the list of constructors
35                 ArrayList constructors;
36
37                 // Holds the list of fields
38                 ArrayList fields;
39
40                 // Holds a list of fields that have initializers
41                 ArrayList initialized_fields;
42
43                 // Holds a list of static fields that have initializers
44                 ArrayList initialized_static_fields;
45
46                 // Holds the list of constants
47                 ArrayList constants;
48
49                 // Holds the list of
50                 ArrayList interfaces;
51
52                 // Holds the methods.
53                 ArrayList methods;
54
55                 // Holds the events
56                 ArrayList events;
57
58                 // Holds the indexers
59                 ArrayList indexers;
60
61                 // Holds the operators
62                 ArrayList operators;
63
64                 // Maps MethodBuilders to Methods
65                 static Hashtable method_builders_to_methods;
66                 
67                 //
68                 // Pointers to the default constructor and the default static constructor
69                 //
70                 Constructor default_constructor;
71                 Constructor default_static_constructor;
72
73                 //
74                 // Whether we have seen a static constructor for this class or not
75                 //
76                 bool have_static_constructor = false;
77                 
78                 //
79                 // This is the namespace in which this typecontainer
80                 // was declared.  We use this to resolve names.
81                 //
82                 Namespace my_namespace;
83                 
84                 //
85                 // This one is computed after we can distinguish interfaces
86                 // from classes from the arraylist `type_bases' 
87                 //
88                 string     base_class_name;
89
90                 TypeContainer parent;
91                 ArrayList type_bases;
92
93                 //
94                 // This behaves like a property ;-)
95                 //
96                 public readonly RootContext RootContext;
97
98                 // Attributes for this type
99                 protected Attributes attributes;
100
101                 public TypeContainer (RootContext rc, TypeContainer parent, string name, Location l)
102                         : base (name, l)
103                 {
104                         string n;
105                         types = new ArrayList ();
106                         this.parent = parent;
107                         RootContext = rc;
108
109                         if (parent == null)
110                                 n = "";
111                         else
112                                 n = parent.Name;
113
114                         base_class_name = null;
115                         
116                         //Console.WriteLine ("New class " + name + " inside " + n);
117                 }
118
119                 public AdditionResult AddConstant (Constant constant)
120                 {
121                         AdditionResult res;
122                         string name = constant.Name;
123
124                         if ((res = IsValid (name)) != AdditionResult.Success)
125                                 return res;
126                         
127                         if (constants == null)
128                                 constants = new ArrayList ();
129
130                         constants.Add (constant);
131                         DefineName (name, constant);
132
133                         return AdditionResult.Success;
134                 }
135
136                 public AdditionResult AddEnum (CIR.Enum e)
137                 {
138                         AdditionResult res;
139                         string name = e.Name;
140
141                         if ((res = IsValid (name)) != AdditionResult.Success)
142                                 return res;
143
144                         if (enums == null)
145                                 enums = new ArrayList ();
146
147                         enums.Add (e);
148                         DefineName (name, e);
149
150                         return AdditionResult.Success;
151                 }
152                 
153                 public AdditionResult AddClass (Class c)
154                 {
155                         AdditionResult res;
156                         string name = c.Name;
157
158
159                         if ((res = IsValid (name)) != AdditionResult.Success)
160                                 return res;
161
162                         DefineName (name, c);
163                         types.Add (c);
164
165                         return AdditionResult.Success;
166                 }
167
168                 public AdditionResult AddStruct (Struct s)
169                 {
170                         AdditionResult res;
171                         string name = s.Name;
172                         
173                         if ((res = IsValid (name)) != AdditionResult.Success)
174                                 return res;
175
176                         DefineName (name, s);
177                         types.Add (s);
178
179                         return AdditionResult.Success;
180                 }
181
182                 public AdditionResult AddDelegate (Delegate d)
183                 {
184                         AdditionResult res;
185                         string name = d.Name;
186
187                         if ((res = IsValid (name)) != AdditionResult.Success)
188                                 return res;
189
190                         if (delegates == null)
191                                 delegates = new ArrayList ();
192                         
193                         DefineName (name, d);
194                         delegates.Add (d);
195
196                         return AdditionResult.Success;
197                 }
198
199                 public AdditionResult AddMethod (Method method)
200                 {
201                         string name = method.Name;
202                         Object value = defined_names [name];
203                         
204                         if (value != null && (!(value is Method)))
205                                 return AdditionResult.NameExists;
206
207                         if (methods == null)
208                                 methods = new ArrayList ();
209
210                         methods.Add (method);
211                         if (value != null)
212                                 DefineName (name, method);
213
214                         return AdditionResult.Success;
215                 }
216
217                 public AdditionResult AddConstructor (Constructor c)
218                 {
219                         if (c.Name != Basename) 
220                                 return AdditionResult.NotAConstructor;
221
222                         if (constructors == null)
223                                 constructors = new ArrayList ();
224
225                         constructors.Add (c);
226
227                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
228                         
229                         if (is_static)
230                                 have_static_constructor = true;
231
232                         if (c.IsDefault ()) {
233                                 if (is_static)
234                                         default_static_constructor = c;
235                                 else
236                                         default_constructor = c;
237                         }
238                         
239                         return AdditionResult.Success;
240                 }
241                 
242                 public AdditionResult AddInterface (Interface iface)
243                 {
244                         AdditionResult res;
245                         string name = iface.Name;
246
247                         if ((res = IsValid (name)) != AdditionResult.Success)
248                                 return res;
249                         
250                         if (interfaces == null)
251                                 interfaces = new ArrayList ();
252                         interfaces.Add (iface);
253                         DefineName (name, iface);
254                         
255                         return AdditionResult.Success;
256                 }
257
258                 public AdditionResult AddField (Field field)
259                 {
260                         AdditionResult res;
261                         string name = field.Name;
262                         
263                         if ((res = IsValid (name)) != AdditionResult.Success)
264                                 return res;
265
266                         if (fields == null)
267                                 fields = new ArrayList ();
268
269                         fields.Add (field);
270                         if (field.Initializer != null){
271                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
272                                         if (initialized_static_fields == null)
273                                                 initialized_static_fields = new ArrayList ();
274
275                                         initialized_static_fields.Add (field);
276
277                                         //
278                                         // We have not seen a static constructor,
279                                         // but we will provide static initialization of fields
280                                         //
281                                         have_static_constructor = true;
282                                 } else {
283                                         if (initialized_fields == null)
284                                                 initialized_fields = new ArrayList ();
285                                 
286                                         initialized_fields.Add (field);
287                                 }
288                         }
289                         
290                         DefineName (name, field);
291                         return AdditionResult.Success;
292                 }
293
294                 public AdditionResult AddProperty (Property prop)
295                 {
296                         AdditionResult res;
297                         string name = prop.Name;
298
299                         if ((res = IsValid (name)) != AdditionResult.Success)
300                                 return res;
301
302                         if (properties == null)
303                                 properties = new ArrayList ();
304
305                         properties.Add (prop);
306                         DefineName (name, prop);
307
308                         return AdditionResult.Success;
309                 }
310
311                 public AdditionResult AddEvent (Event e)
312                 {
313                         AdditionResult res;
314                         string name = e.Name;
315
316                         if ((res = IsValid (name)) != AdditionResult.Success)
317                                 return res;
318
319                         if (events == null)
320                                 events = new ArrayList ();
321                         
322                         events.Add (e);
323                         DefineName (name, e);
324
325                         return AdditionResult.Success;
326                 }
327
328                 public AdditionResult AddIndexer (Indexer i)
329                 {
330                         if (indexers == null)
331                                 indexers = new ArrayList ();
332
333                         indexers.Add (i);
334
335                         return AdditionResult.Success;
336                 }
337
338                 public AdditionResult AddOperator (Operator op)
339                 {
340                         if (operators == null)
341                                 operators = new ArrayList ();
342
343                         operators.Add (op);
344
345                         return AdditionResult.Success;
346                 }
347                 
348                 public TypeContainer Parent {
349                         get {
350                                 return parent;
351                         }
352                 }
353
354                 public ArrayList Types {
355                         get {
356                                 return types;
357                         }
358                 }
359
360                 public ArrayList Methods {
361                         get {
362                                 return methods;
363                         }
364                 }
365
366                 public ArrayList Constants {
367                         get {
368                                 return constants;
369                         }
370                 }
371
372                 public ArrayList Interfaces {
373                         get {
374                                 return interfaces;
375                         }
376                 }
377                 
378                 public int ModFlags {
379                         get {
380                                 return mod_flags;
381                         }
382                 }
383
384                 public string Base {
385                         get {
386                                 return base_class_name;
387                         }
388                 }
389                 
390                 public ArrayList Bases {
391                         get {
392                                 return type_bases;
393                         }
394
395                         set {
396                                 type_bases = value;
397                         }
398                 }
399
400                 public ArrayList Fields {
401                         get {
402                                 return fields;
403                         }
404                 }
405
406                 public ArrayList Constructors {
407                         get {
408                                 return constructors;
409                         }
410                 }
411
412                 public ArrayList Properties {
413                         get {
414                                 return properties;
415                         }
416                 }
417
418                 public ArrayList Events {
419                         get {
420                                 return events;
421                         }
422                 }
423                 
424                 public ArrayList Enums {
425                         get {
426                                 return enums;
427                         }
428                 }
429
430                 public ArrayList Indexers {
431                         get {
432                                 return indexers;
433                         }
434                 }
435
436                 public ArrayList Operators {
437                         get {
438                                 return operators;
439                         }
440                 }
441
442                 public ArrayList Delegates {
443                         get {
444                                 return delegates;
445                         }
446                 }
447                 
448                 public Attributes OptAttributes {
449                         get {
450                                 return attributes;
451                         }
452                 }
453                 
454                 public Namespace Namespace {
455                         get {
456                                 return my_namespace;
457                         }
458
459                         set {
460                                 my_namespace = value;
461                         }
462                 }
463
464                 // 
465                 // root_types contains all the types.  All TopLevel types
466                 // hence have a parent that points to `root_types', that is
467                 // why there is a non-obvious test down here.
468                 //
469                 public bool IsTopLevel {
470                         get {
471                                 if (parent != null){
472                                         if (parent.Parent == null)
473                                                 return true;
474                                 }
475                                 return false;
476                         }
477                 }
478                         
479                 public bool HaveStaticConstructor {
480                         get {
481                                 return have_static_constructor;
482                         }
483                 }
484                 
485                 public virtual TypeAttributes TypeAttr {
486                         get {
487                                 return Modifiers.TypeAttr (mod_flags, this);
488                         }
489                 }
490
491                 //
492                 // Emits the instance field initializers
493                 //
494                 public bool EmitFieldInitializers (EmitContext ec, bool is_static)
495                 {
496                         ArrayList fields;
497                         ILGenerator ig = ec.ig;
498                         
499                         if (is_static)
500                                 fields = initialized_static_fields;
501                         else
502                                 fields = initialized_fields;
503
504                         if (fields == null)
505                                 return true;
506                         
507                         foreach (Field f in fields){
508                                 Object init = f.Initializer;
509
510                                 if (init is Expression){
511                                         Expression e = (Expression) init;
512
513                                         e = e.Resolve (ec);
514                                         if (e == null)
515                                                 return false;
516
517                                         if (!is_static)
518                                                 ig.Emit (OpCodes.Ldarg_0);
519                                         
520                                         e.Emit (ec);
521
522                                         if (is_static)
523                                                 ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
524                                         else
525                                                 ig.Emit (OpCodes.Stfld, f.FieldBuilder);
526                                 }
527                         }
528
529                         return true;
530                 }
531
532                 //
533                 // Defines the default constructors
534                 //
535                 void DefineDefaultConstructor (bool is_static)
536                 {
537                         Constructor c;
538                         int mods = 0;
539
540                         c = new Constructor (Basename, new Parameters (null, null),
541                                              new ConstructorBaseInitializer (null, new Location (-1)),
542                                              new Location (-1));
543                         
544                         AddConstructor (c);
545                         
546                         c.Block = new Block (null);
547                         
548                         if (is_static)
549                                 mods = Modifiers.STATIC;
550
551                         c.ModFlags = mods;
552
553                 }
554
555                 public void ReportStructInitializedInstanceError ()
556                 {
557                         string n = TypeBuilder.FullName;
558                         
559                         foreach (Field f in initialized_fields){
560                                 Report.Error (
561                                         573, Location,
562                                         "`" + n + "." + f.Name + "': can not have " +
563                                         "instance field initializers in structs");
564                         }
565                 }
566
567                 public void RegisterRequiredImplementations ()
568                 {
569                         Type [] ifaces = TypeBuilder.GetInterfaces ();
570                         Type b = TypeBuilder.BaseType;
571                         
572                         if (ifaces != null)
573                                 SetRequiredInterfaces (ifaces);
574
575                         if (b.IsAbstract){
576                                 MemberInfo [] abstract_methods;
577
578                                 abstract_methods = FindMembers (
579                                         TypeBuilder.BaseType,
580                                         MemberTypes.Method, BindingFlags.Public,
581                                         abstract_method_filter, null);
582
583                                 if (abstract_methods != null){
584                                         MethodInfo [] mi = new MethodInfo [abstract_methods.Length];
585
586                                         abstract_methods.CopyTo (mi, 0);
587                                         RequireMethods (mi, b);
588                                 }
589                         }
590                         
591                 }
592
593                 static object MakeKey (MethodBase mb)
594                 {
595                         if (mb is MethodBuilder || mb is ConstructorBuilder)
596                                 return mb.ReflectedType.FullName + ":" + mb;
597                         else
598                                 return mb.MethodHandle.ToString ();
599                 }
600
601
602                 public static string MakeFQN (string nsn, string name)
603                 {
604                         string prefix = (nsn == "" ? "" : nsn + ".");
605
606                         return prefix + name;
607                 }
608                        
609                 Type LookupInterfaceOrClass (object builder, string ns, string name, bool is_class, out bool error)
610                 {
611                         TypeContainer parent;
612                         Type t;
613
614                         error = false;
615                         name = MakeFQN (ns, name);
616                         
617                         t  = RootContext.TypeManager.LookupType (name);
618                         if (t != null)
619                                 return t;
620
621                         if (is_class){
622                                 parent = (Class) RootContext.Tree.Classes [name];
623                         } else {
624                                 parent = (Struct) RootContext.Tree.Structs [name];
625                         }
626                         
627                         if (parent != null){
628                                 t = parent.DefineType (builder);
629                                 if (t == null){
630                                         Report.Error (146, "Class definition is circular: `"+name+"'");
631                                         error = true;
632                                         return null;
633                                 }
634
635                                 return t;
636                         }
637
638                         return null;
639                 }
640                 
641                 //
642                 // returns the type for an interface or a class, this will recursively
643                 // try to define the types that it depends on.
644                 //
645                 Type GetInterfaceOrClass (object builder, string name, bool is_class)
646                 {
647                         Type t;
648                         bool error;
649
650                         //
651                         // Attempt to lookup the class on our namespace
652                         //
653                         t = LookupInterfaceOrClass (builder, Namespace.Name, name, is_class, out error);
654                         if (error)
655                                 return null;
656                         
657                         if (t != null) 
658                                 return t;
659
660                         //
661                         // Attempt to lookup the class on any of the `using'
662                         // namespaces
663                         //
664
665                         for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
666                                 ArrayList using_list = ns.UsingTable;
667                                 
668                                 if (using_list == null)
669                                         continue;
670
671                                 foreach (string n in using_list){
672                                         t = LookupInterfaceOrClass (builder, n, name, is_class, out error);
673                                         if (error)
674                                                 return null;
675
676                                         if (t != null)
677                                                 return t;
678                                 }
679                                 
680                         }
681                         Report.Error (246, "Can not find type `"+name+"'");
682                         return null;
683                 }
684
685                 //
686                 // This function computes the Base class and also the
687                 // list of interfaces that the class or struct @c implements.
688                 //
689                 // The return value is an array (might be null) of
690                 // interfaces implemented (as Types).
691                 //
692                 // The @parent argument is set to the parent object or null
693                 // if this is `System.Object'. 
694                 //
695                 Type [] GetClassBases (object builder, bool is_class, out Type parent, out bool error)
696                 {
697                         ArrayList bases = Bases;
698                         int count;
699                         int start, j, i;
700
701                         error = false;
702
703                         if (is_class)
704                                 parent = null;
705                         else
706                                 parent = TypeManager.value_type;
707
708                         if (bases == null){
709                                 if (is_class){
710                                         if (RootContext.StdLib)
711                                                 parent = TypeManager.object_type;
712                                         else if (Name != "System.Object")
713                                                 parent = TypeManager.object_type;
714                                 } else {
715                                         //
716                                         // If we are compiling our runtime,
717                                         // and we are defining ValueType, then our
718                                         // parent is `System.Object'.
719                                         //
720                                         if (!RootContext.StdLib && Name == "System.ValueType")
721                                                 parent = TypeManager.object_type;
722                                 }
723
724                                 return null;
725                         }
726
727                         //
728                         // Bases should be null if there are no bases at all
729                         //
730                         count = bases.Count;
731
732                         if (is_class){
733                                 string name = (string) bases [0];
734                                 Type first = GetInterfaceOrClass (builder, name, is_class);
735
736                                 if (first == null){
737                                         error = true;
738                                         return null;
739                                 }
740                                 
741                                 if (first.IsClass){
742                                         parent = first;
743                                         start = 1;
744                                 } else {
745                                         parent = TypeManager.object_type;
746                                         start = 0;
747                                 }
748                         } else {
749                                 start = 0;
750                         }
751
752                         Type [] ifaces = new Type [count-start];
753                         
754                         for (i = start, j = 0; i < count; i++, j++){
755                                 string name = (string) bases [i];
756                                 Type t = GetInterfaceOrClass (builder, name, is_class);
757                                 
758                                 if (t == null){
759                                         error = true;
760                                         return null;
761                                 }
762
763                                 if (is_class == false && !t.IsInterface){
764                                         Report.Error (527, "In Struct `" + Name + "', type `"+
765                                                       name +"' is not an interface");
766                                         error = true;
767                                         return null;
768                                 }
769                                 
770                                 if (t.IsSealed) {
771                                         string detail = "";
772                                         
773                                         if (t.IsValueType)
774                                                 detail = " (a class can not inherit from a struct)";
775                                                         
776                                         Report.Error (509, "class `"+ Name +
777                                                       "': Cannot inherit from sealed class `"+
778                                                       bases [i]+"'"+detail);
779                                         error = true;
780                                         return null;
781                                 }
782
783                                 if (t.IsClass) {
784                                         if (parent != null){
785                                                 Report.Error (527, "In Class `" + Name + "', type `"+
786                                                               name+"' is not an interface");
787                                                 error = true;
788                                                 return null;
789                                         }
790                                 }
791                                 
792                                 ifaces [j] = t;
793                         }
794
795                         return ifaces;
796                 }
797                 
798                 //
799                 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
800                 //
801                 public TypeBuilder DefineType (object parent_builder)
802                 {
803                         Type parent;
804                         Type [] ifaces;
805                         bool error;
806                         bool is_class;
807                         
808                         if (InTransit)
809                                 return null;
810                         
811                         InTransit = true;
812                         
813                         if (this is Class)
814                                 is_class = true;
815                         else
816                                 is_class = false;
817                         
818                         ifaces = GetClassBases (parent_builder, is_class, out parent, out error); 
819                         
820                         if (error)
821                                 return null;
822                         
823                         if (parent_builder is ModuleBuilder) {
824                                 ModuleBuilder builder = (ModuleBuilder) parent_builder;
825                                 
826                                 //
827                                 // Structs with no fields need to have a ".size 1"
828                                 // appended
829                                 //
830                                 if (!is_class && Fields == null)
831                                         TypeBuilder = builder.DefineType (Name,
832                                                                           TypeAttr,
833                                                                           parent, 
834                                                                           PackingSize.Unspecified, 1);
835                                 else
836                                 //
837                                 // classes or structs with fields
838                                 //
839                                         TypeBuilder = builder.DefineType (Name,
840                                                                           TypeAttr,
841                                                                           parent,
842                                                                           ifaces);
843
844                         } else {
845                                 TypeBuilder builder = (TypeBuilder) parent_builder;
846                                 
847                                 //
848                                 // Structs with no fields need to have a ".size 1"
849                                 // appended
850                                 //
851                                 if (!is_class && Fields == null)
852                                         TypeBuilder = builder.DefineNestedType (Name,
853                                                                                 TypeAttr,
854                                                                                 parent, 
855                                                                                 PackingSize.Unspecified);
856                                 else
857                                 //
858                                 // classes or structs with fields
859                                 //
860                                         TypeBuilder = builder.DefineNestedType (Name,
861                                                                                 TypeAttr,
862                                                                                 parent,
863                                                                                 ifaces);
864                         }
865
866                         RootContext.TypeManager.AddUserType (Name, TypeBuilder, this);
867
868                         if (Types != null) {
869                                 foreach (TypeContainer tc in Types)
870                                         tc.DefineType (TypeBuilder);
871                         }
872
873                         if (Delegates != null) {
874                                 foreach (Delegate d in Delegates)
875                                         d.DefineDelegate (TypeBuilder);
876                         }
877                         
878                         InTransit = false;
879                         return TypeBuilder;
880                 }
881                 
882                 //
883                 // Populates our TypeBuilder with fields and methods
884                 //
885                 public void Populate ()
886                 {
887                         if (Constants != null){
888                                 foreach (Constant c in Constants)
889                                         c.EmitConstant (RootContext, this);
890                         }
891
892                         if (Fields != null){
893                                 foreach (Field f in Fields)
894                                         f.Define (this);
895                         } 
896
897                         if (this is Class && constructors == null){
898                                 if (default_constructor == null) 
899                                         DefineDefaultConstructor (false);
900
901                                 if (initialized_static_fields != null &&
902                                     default_static_constructor == null)
903                                         DefineDefaultConstructor (true);
904                         }
905
906                         if (this is Struct){
907                                 //
908                                 // Structs can not have initialized instance
909                                 // fields
910                                 //
911                                 if (initialized_static_fields != null &&
912                                     default_static_constructor == null)
913                                         DefineDefaultConstructor (true);
914
915                                 if (initialized_fields != null)
916                                         ReportStructInitializedInstanceError ();
917                         }
918
919                         RegisterRequiredImplementations ();
920                         
921                         ArrayList remove_list = new ArrayList ();
922
923                         if (constructors != null || methods != null ||
924                             properties != null || operators != null){
925                                 if (method_builders_to_methods == null)
926                                         method_builders_to_methods = new Hashtable ();
927                         }
928                         
929                         if (constructors != null){
930                                 foreach (Constructor c in constructors){
931                                         MethodBase builder = c.Define (this);
932                                         
933                                         if (builder == null)
934                                                 remove_list.Add (c);
935                                         else
936                                                 method_builders_to_methods.Add (MakeKey (builder), c);
937                                 }
938
939                                 foreach (object o in remove_list)
940                                         constructors.Remove (o);
941                                 
942                                 remove_list.Clear ();
943                         } 
944
945                         if (Methods != null){
946                                 foreach (Method m in methods){
947                                         MethodBase key = m.Define (this);
948
949                                         //
950                                         // FIXME:
951                                         // The following key is not enoug
952                                         // class x { public void X ()  {} }
953                                         // class y : x { public void X () {}}
954                                         // fails
955                                         
956                                         if (key == null)
957                                                 remove_list.Add (m);
958                                         else
959                                                 method_builders_to_methods.Add (MakeKey (key), m);
960                                 }
961                                 foreach (object o in remove_list)
962                                         methods.Remove (o);
963                                 
964                                 remove_list.Clear ();
965                         }
966
967                         if (Properties != null) {
968                                 foreach (Property p in Properties)
969                                         p.Define (this);
970                         }
971
972                         if (Enums != null) {
973                                 foreach (Enum e in Enums)
974                                         e.Define (this);
975                         }
976
977                         if (Events != null) {
978                                 foreach (Event e in Events)
979                                         e.Define (this);
980                         }
981
982                         if (Indexers != null) {
983                                 foreach (Indexer i in Indexers)
984                                         i.Define (this);
985                         }
986
987                         if (Operators != null) {
988                                 foreach (Operator o in Operators) {
989                                         o.Define (this);
990                                         
991                                         method_builders_to_methods.Add (
992                                                 MakeKey (o.OperatorMethodBuilder), o.OperatorMethod);
993                                 }
994                         }
995
996                         if (Delegates != null) {
997                                 foreach (Delegate d in Delegates) 
998                                         d.Populate (this);
999                         }
1000                         
1001                         if (Types != null) {
1002                                 foreach (TypeContainer tc in Types)
1003                                         tc.Populate ();
1004                         }
1005                         
1006                 }
1007
1008                 //
1009                 // the `mb' must be a MethodBuilder or a
1010                 // ConstructorBuilder, we return the method that
1011                 // defines it.
1012                 // 
1013                 static public MethodCore LookupMethodByBuilder (MethodBase mb)
1014                 {
1015                         return (MethodCore) method_builders_to_methods [MakeKey (mb)];
1016                 }
1017                 
1018                 public Type LookupType (string name, bool silent)
1019                 {
1020                         return RootContext.LookupType (this, name, silent);
1021                 }
1022
1023                 public string LookupAlias (string Name)
1024                 {
1025                         //
1026                         // Read the comments on `mcs/mcs/TODO' for details
1027                         // 
1028                         return null;
1029                 }
1030                 
1031                 //
1032                 // This function is based by a delegate to the FindMembers routine
1033                 //
1034                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1035                 {
1036                         return true;
1037                 }
1038                 
1039                 //
1040                 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1041                 {
1042                         MethodInfo mi = (MethodInfo) m;
1043
1044                         return mi.IsAbstract;
1045                 }
1046
1047                 // This filter is used by FindMembers, and we just keep
1048                 // a global for the filter to `AlwaysAccept'
1049                 //
1050                 static MemberFilter accepting_filter;
1051                 
1052                 // <summary>
1053                 //    This delegate is a MemberFilter used to extract the 
1054                 //    abstact methods from a type.  
1055                 // </summary>
1056                 static MemberFilter abstract_method_filter;
1057
1058                 static TypeContainer ()
1059                 {
1060                         abstract_method_filter = new MemberFilter (IsAbstractMethod);
1061                         accepting_filter = new MemberFilter (AlwaysAccept);
1062                 }
1063                 
1064                 // <summary>
1065                 //   This method returns the members of this type just like Type.FindMembers would
1066                 //   Only, we need to use this for types which are _being_ defined because MS' 
1067                 //   implementation can't take care of that.
1068                 // </summary>
1069                 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1070                                                   MemberFilter filter, object criteria)
1071                 {
1072                         ArrayList members = new ArrayList ();
1073
1074                         if (filter == null)
1075                                 filter = accepting_filter; 
1076                         
1077                         if ((mt & MemberTypes.Field) != 0 && Fields != null) {
1078                                 foreach (Field f in Fields) {
1079                                         if (filter (f.FieldBuilder, criteria) == true)
1080                                                 members.Add (f.FieldBuilder);
1081                                 }
1082                         }
1083
1084                         if ((mt & MemberTypes.Method) != 0) {
1085                                 if (Methods != null){
1086                                         foreach (Method m in Methods) {
1087                                                 MethodBuilder mb = m.MethodBuilder;
1088
1089                                                 if (filter (mb, criteria) == true)
1090                                                         members.Add (mb);
1091                                         }
1092                                 }
1093
1094                                 if (Operators != null){
1095                                         foreach (Operator o in Operators) {
1096                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1097
1098                                                 if (filter (ob, criteria) == true)
1099                                                         members.Add (ob);
1100                                         }
1101                                 }
1102                         }
1103
1104                         // FIXME : This ain't right because EventBuilder is not a
1105                         // MemberInfo. What do we do ?
1106                         
1107                         if ((mt & MemberTypes.Event) != 0 && Events != null) {
1108                                 //foreach (Event e in Events) {
1109                                 //      if (filter (e.EventBuilder, criteria) == true)
1110                                 //              mi [i++] = e.EventBuilder;
1111                                 //}
1112                         }
1113
1114                         if ((mt & MemberTypes.Property) != 0 && Properties != null) {
1115                                 foreach (Property p in Properties) {
1116                                         if (filter (p.PropertyBuilder, criteria) == true)
1117                                                 members.Add (p.PropertyBuilder);
1118                                 }
1119                         }
1120                         
1121                         if ((mt & MemberTypes.NestedType) != 0 && Types != null) {
1122                                 foreach (TypeContainer t in Types) { 
1123                                         if (filter (t.TypeBuilder, criteria) == true)
1124                                                 members.Add (t.TypeBuilder);
1125                                 }
1126                         }
1127
1128                         if ((mt & MemberTypes.Constructor) != 0){
1129                                 if (Constructors != null){
1130                                         foreach (Constructor c in Constructors){
1131                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1132
1133                                                 if (filter (cb, criteria) == true)
1134                                                         members.Add (cb);
1135                                         }
1136                                 }
1137                         }
1138
1139                         //
1140                         // Lookup members in parent if requested.
1141                         //
1142                         if ((bf & BindingFlags.DeclaredOnly) == 0){
1143                                 MemberInfo [] mi;
1144
1145                                 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1146                                 if (mi != null)
1147                                         members.AddRange (mi);
1148                         }
1149                         
1150                         int count = members.Count;
1151                         if (count > 0){
1152                                 MemberInfo [] mi = new MemberInfo [count];
1153                                 members.CopyTo (mi);
1154                                 return mi;
1155                         }
1156
1157                         return null;
1158                 }
1159
1160                 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1161                                                          MemberFilter filter, object criteria)
1162                 {
1163                         TypeContainer tc = TypeManager.LookupTypeContainer (t);
1164
1165                         if (tc != null)
1166                                 return tc.FindMembers (mt, bf, filter, criteria);
1167                         else
1168                                 return t.FindMembers (mt, bf, filter, criteria);
1169                 }
1170                 
1171
1172                 Hashtable pending_implementations;
1173                 
1174                 // <summary>
1175                 //   Requires that the methods in `mi' be implemented for this
1176                 //   class
1177                 // </summary>
1178                 public void RequireMethods (MethodInfo [] mi, object data)
1179                 {
1180                         if (pending_implementations == null)
1181                                 pending_implementations = new Hashtable ();
1182
1183                         foreach (MethodInfo m in mi){
1184                                 Type [] types = TypeManager.GetArgumentTypes (m);
1185
1186                                 pending_implementations.Add (
1187                                         new MethodSignature 
1188                                                 (m.Name, m.ReturnType, types), data);
1189                         }
1190                 }
1191
1192                 // <summary>
1193                 //   Used to set the list of interfaces that this typecontainer
1194                 //   must implement.
1195                 // </summary>
1196                 //
1197                 // <remarks>
1198                 //   For each element exposed by the type, we create a MethodSignature
1199                 //   struct that we will label as `implemented' as we define the various
1200                 //   methods.
1201                 // </remarks>
1202                 public void SetRequiredInterfaces (Type [] ifaces)
1203                 {
1204                         foreach (Type t in ifaces){
1205                                 MethodInfo [] mi;
1206
1207                                 if (t is TypeBuilder){
1208                                         Interface iface = RootContext.TypeManager.LookupInterface (t);
1209
1210                                         mi = iface.GetMethods ();
1211                                 } else
1212                                         mi = t.GetMethods ();
1213
1214                                 RequireMethods (mi, t);
1215                         }
1216                 }
1217
1218                 // <summary>
1219                 //   If a method with name `Name', return type `ret_type' and
1220                 //   arguments `args' implements an interface, this method will
1221                 //   return true.
1222                 //
1223                 //   This will remove the method from the list of "pending" methods
1224                 //   that are required to be implemented for this class as a side effect.
1225                 // 
1226                 // </summary>
1227                 public bool IsInterfaceMethod (string Name, Type ret_type, Type [] args)
1228                 {
1229                         MethodSignature query;
1230
1231                         if (pending_implementations == null)
1232                                 return false;
1233
1234                         query = new MethodSignature (Name, ret_type, args);
1235
1236                         if (pending_implementations.Contains (query)){
1237                                 pending_implementations.Remove (query);
1238                                 return true;
1239                         }
1240
1241                         return false;
1242                 }
1243
1244                 // <summary>
1245                 //   Verifies that any pending abstract methods or interface methods
1246                 //   were implemented.
1247                 // </summary>
1248                 void VerifyPendingMethods ()
1249                 {
1250                         int pending = 0;
1251                         
1252                         foreach (object m in pending_implementations){
1253                                 DictionaryEntry de = (DictionaryEntry) m;
1254                                 Type t = (Type) de.Value;
1255                                 pending++;
1256
1257                                 MethodSignature method = (MethodSignature) de.Key;
1258
1259                                 if (t.IsInterface)
1260                                         Report.Error (
1261                                                 536, Location,
1262                                                 "`" + Name + "' does not implement interface member `" +
1263                                                 t.FullName + "." + method.Name + "'");
1264                                 else
1265                                         Report.Error (
1266                                                 534, Location,
1267                                                 "`" + Name + "' does not implement inherited abstract " +
1268                                                 "member `" + t.FullName + "." + method.Name + "'");
1269                         }
1270                 }
1271                 
1272                 // <summary>
1273                 //   Emits the code, this step is performed after all
1274                 //   the types, enumerations, constructors
1275                 // </summary>
1276                 public void Emit ()
1277                 {
1278                         if (Constructors != null)
1279                                 foreach (Constructor c in Constructors)
1280                                         c.Emit (this);
1281                         
1282                         if (methods != null)
1283                                 foreach (Method m in methods)
1284                                         m.Emit (this);
1285
1286                         if (operators != null)
1287                                 foreach (Operator o in operators)
1288                                         o.Emit (this);
1289
1290                         if (properties != null)
1291                                 foreach (Property p in properties)
1292                                         p.Emit (this);
1293
1294                         if (pending_implementations != null)
1295                                 VerifyPendingMethods ();
1296
1297                         if (types != null)
1298                                 foreach (TypeContainer tc in types)
1299                                         tc.Emit ();
1300
1301                 }
1302
1303                 public void CloseType ()
1304                 {
1305                         TypeBuilder.CreateType ();
1306                         
1307                         foreach (TypeContainer tc in Types)
1308                                 tc.CloseType ();
1309
1310                         if (Delegates != null)
1311                                 foreach (Delegate d in Delegates)
1312                                         d.CloseDelegate ();
1313                 }
1314
1315                 string MakeName (string n)
1316                 {
1317                         return "`" + Name + "." + n + "'";
1318                 }
1319                 
1320                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1321                 {
1322                         return 0;
1323                 }
1324         }
1325
1326         public class Class : TypeContainer {
1327                 // <summary>
1328                 //   Modifiers allowed in a class declaration
1329                 // </summary>
1330                 public const int AllowedModifiers =
1331                         Modifiers.NEW |
1332                         Modifiers.PUBLIC |
1333                         Modifiers.PROTECTED |
1334                         Modifiers.INTERNAL |
1335                         Modifiers.PRIVATE |
1336                         Modifiers.ABSTRACT |
1337                         Modifiers.SEALED;
1338
1339                 public Class (RootContext rc, TypeContainer parent, string name, int mod,
1340                               Attributes attrs, Location l)
1341                         : base (rc, parent, name, l)
1342                 {
1343                         int accmods;
1344
1345                         if (parent.Parent == null)
1346                                 accmods = Modifiers.INTERNAL;
1347                         else
1348                                 accmods = Modifiers.PRIVATE;
1349                         
1350                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1351                         this.attributes = attrs;
1352                 }
1353
1354                 //
1355                 // FIXME: How do we deal with the user specifying a different
1356                 // layout?
1357                 //
1358                 public override TypeAttributes TypeAttr {
1359                         get {
1360                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1361                         }
1362                 }
1363         }
1364
1365         public class Struct : TypeContainer {
1366                 // <summary>
1367                 //   Modifiers allowed in a struct declaration
1368                 // </summary>
1369                 public const int AllowedModifiers =
1370                         Modifiers.NEW |
1371                         Modifiers.PUBLIC |
1372                         Modifiers.PROTECTED |
1373                         Modifiers.INTERNAL |
1374                         Modifiers.PRIVATE;
1375
1376                 public Struct (RootContext rc, TypeContainer parent, string name, int mod,
1377                                Attributes attrs, Location l)
1378                         : base (rc, parent, name, l)
1379                 {
1380                         int accmods;
1381                         
1382                         if (parent.Parent == null)
1383                                 accmods = Modifiers.INTERNAL;
1384                         else
1385                                 accmods = Modifiers.PRIVATE;
1386                         
1387                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1388
1389                         this.mod_flags |= Modifiers.SEALED;
1390                         this.attributes = attrs;
1391                         
1392                 }
1393
1394                 //
1395                 // FIXME: Allow the user to specify a different set of attributes
1396                 // in some cases (Sealed for example is mandatory for a class,
1397                 // but what SequentialLayout can be changed
1398                 //
1399                 public override TypeAttributes TypeAttr {
1400                         get {
1401                                 return base.TypeAttr |
1402                                         TypeAttributes.SequentialLayout |
1403                                         TypeAttributes.Sealed |
1404                                         TypeAttributes.BeforeFieldInit;
1405                         }
1406                 }
1407         }
1408
1409         public class MethodCore {
1410                 public readonly Parameters Parameters;
1411                 public readonly string Name;
1412                 public int ModFlags;
1413                 Block block;
1414                 public readonly Location Location;
1415                 
1416                 //
1417                 // Parameters, cached for semantic analysis.
1418                 //
1419                 InternalParameters parameter_info;
1420                 
1421                 public MethodCore (string name, Parameters parameters, Location l)
1422                 {
1423                         Name = name;
1424                         Parameters = parameters;
1425                         Location = l;
1426                 }
1427                 
1428                 //
1429                 //  Returns the System.Type array for the parameters of this method
1430                 //
1431                 Type [] parameter_types;
1432                 public Type [] ParameterTypes (TypeContainer parent)
1433                 {
1434                         if (Parameters == null)
1435                                 return null;
1436                         
1437                         if (parameter_types == null)
1438                                 parameter_types = Parameters.GetParameterInfo (parent);
1439
1440                         return parameter_types;
1441                 }
1442
1443                 public InternalParameters ParameterInfo
1444                 {
1445                         get {
1446                                 return parameter_info;
1447                         }
1448
1449                         set {
1450                                 parameter_info = value;
1451                         }
1452                 }
1453                 
1454                 public Block Block {
1455                         get {
1456                                 return block;
1457                         }
1458
1459                         set {
1460                                 block = value;
1461                         }
1462                 }
1463
1464                 public CallingConventions GetCallingConvention (bool is_class)
1465                 {
1466                         CallingConventions cc = 0;
1467                         
1468                         cc = Parameters.GetCallingConvention ();
1469
1470                         if (is_class)
1471                                 if ((ModFlags & Modifiers.STATIC) == 0)
1472                                         cc |= CallingConventions.HasThis;
1473
1474                         // FIXME: How is `ExplicitThis' used in C#?
1475                         
1476                         return cc;
1477                 }
1478         }
1479         
1480         public class Method : MethodCore {
1481                 public readonly string ReturnType;
1482                 public MethodBuilder MethodBuilder;
1483                 public readonly Attributes OptAttributes;
1484
1485                 // <summary>
1486                 //   Modifiers allowed in a class declaration
1487                 // </summary>
1488                 const int AllowedModifiers =
1489                         Modifiers.NEW |
1490                         Modifiers.PUBLIC |
1491                         Modifiers.PROTECTED |
1492                         Modifiers.INTERNAL |
1493                         Modifiers.PRIVATE |
1494                         Modifiers.STATIC |
1495                         Modifiers.VIRTUAL |
1496                         Modifiers.SEALED |
1497                         Modifiers.OVERRIDE |
1498                         Modifiers.ABSTRACT |
1499                         Modifiers.EXTERN;
1500                 
1501                 // return_type can be "null" for VOID values.
1502                 public Method (string return_type, int mod, string name, Parameters parameters,
1503                                Attributes attrs, Location l)
1504                         : base (name, parameters, l)
1505                 {
1506                         ReturnType = return_type;
1507                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1508                         OptAttributes = attrs;
1509                 }
1510
1511                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1512                 {
1513                         MethodInfo mi;
1514                         
1515                         if (! (m is MethodInfo))
1516                                 return false;
1517
1518                         MethodSignature sig = (MethodSignature) filter_criteria;
1519                         
1520                         if (m.Name != sig.Name)
1521                                 return false;
1522                         
1523                         mi = (MethodInfo) m;
1524
1525                         if (mi.ReturnType != sig.RetType)
1526                                 return false;
1527
1528                         Type [] args = TypeManager.GetArgumentTypes (mi);
1529                         Type [] sigp = sig.Parameters;
1530
1531                         //
1532                         // FIXME: remove this assumption if we manage to
1533                         // not enter a null as a the Parameters in TypeManager's 
1534                         // MethodBase to Type argument mapper.
1535                         //
1536                         if (args == null){
1537                                 if (sigp != null)
1538                                         return false;
1539                                 else
1540                                         return true;
1541                         } else if (sigp == null)
1542                                 return false;
1543                         
1544                         if (args.Length != sigp.Length)
1545                                 return false;
1546
1547                         for (int i = args.Length; i > 0; ){
1548                                 i--;
1549                                 if (args [i] != sigp [i])
1550                                         return false;
1551                         }
1552                         return true;
1553                 }
1554                 
1555                 // <summary>
1556                 //    This delegate is used to extract methods which have the
1557                 //    same signature as the argument
1558                 // </summary>
1559                 static MemberFilter method_signature_filter;
1560                 
1561                 static Method ()
1562                 {
1563                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
1564                 }
1565                 
1566                 //
1567                 // Returns the `System.Type' for the ReturnType of this
1568                 // function.  Provides a nice cache.  (used between semantic analysis
1569                 // and actual code generation
1570                 //
1571                 Type type_return_type;
1572                 public Type GetReturnType (TypeContainer parent)
1573                 {
1574                         if (type_return_type == null)
1575                                 type_return_type = parent.LookupType (ReturnType, false);
1576                         
1577                         return type_return_type;
1578                 }
1579
1580                 void WarningNotHiding (TypeContainer parent)
1581                 {
1582                         Report.Warning (
1583                                 109, Location,
1584                                 "The member `" + parent.Name + "." + Name + "' does not hide an " +
1585                                 "inherited member.  The keyword new is not required");
1586                                                            
1587                 }
1588
1589                 string MakeName (TypeContainer parent)
1590                 {
1591                         return "`" + parent.Name + "." + Name + "'";
1592                 }
1593
1594                 string MethodBaseName (MethodBase mb)
1595                 {
1596                         return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
1597                 }
1598                 
1599                 bool CheckMethod (TypeContainer parent, MemberInfo [] mi)
1600                 {
1601                         MethodInfo mb = (MethodInfo) mi [0];
1602
1603                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1604                                 Report.Warning (
1605                                         108, Location, "The keyword new is required on " + 
1606                                         MakeName (parent) + " because it hides `" +
1607                                         mb.ReflectedType.Name + "." +
1608                                         mb.Name + "'");
1609                         }
1610
1611                         if (mb.IsVirtual || mb.IsAbstract){
1612                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1613                                         Report.Warning (
1614                                                 114, Location, MakeName (parent) + 
1615                                                 "hides inherited member " + MethodBaseName (mb) +
1616                                                 ".  To make the current member override that " +
1617                                                 "implementation, add the override keyword, " +
1618                                                 "otherwise use the new keyword");
1619                                 }
1620                                 
1621                         }
1622
1623                         return true;
1624                 }
1625                 
1626                 //
1627                 // Creates the type
1628                 // 
1629                 public MethodBuilder Define (TypeContainer parent)
1630                 {
1631                         Type ret_type = GetReturnType (parent);
1632                         Type [] parameters = ParameterTypes (parent);
1633                         MethodAttributes flags;
1634                         bool error = false;
1635                         
1636                         //
1637                         // Verify if the parent has a type with the same name, and then
1638                         // check whether we have to create a new slot for it or not.
1639                         //
1640                         Type ptype = parent.TypeBuilder.BaseType;
1641
1642                         // ptype is only null for System.Object while compiling corlib.
1643                         if (ptype != null){
1644                                 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1645                                 MemberInfo [] mi;
1646                                 
1647                                 mi = TypeContainer.FindMembers (
1648                                         ptype, MemberTypes.Method,
1649                                         BindingFlags.Public, method_signature_filter,
1650                                         ms);
1651
1652                                 if (mi != null && mi.Length > 0){
1653                                         CheckMethod (parent, mi);
1654                                 } else {
1655                                         if ((ModFlags & Modifiers.NEW) != 0)
1656                                                 WarningNotHiding (parent);
1657                                         
1658                                         if ((ModFlags & Modifiers.OVERRIDE) != 0)
1659                                                 Report.Error (115, Location,
1660                                                               MakeName (parent) +
1661                                                               " no suitable methods found to override");
1662                                 }
1663                         } else if ((ModFlags & Modifiers.NEW) != 0)
1664                                 WarningNotHiding (parent);
1665
1666                         //
1667                         // If we implement an interface, then set the proper flags.
1668                         //
1669                         flags = Modifiers.MethodAttr (ModFlags);
1670
1671                         if (parent.IsInterfaceMethod (Name, ret_type, parameters))
1672                                 flags |= MethodAttributes.Virtual;
1673
1674                         //
1675                         // Catch invalid uses of virtual and abtract modifiers
1676                         //
1677                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1678                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1679                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1680
1681                         if ((ModFlags & va) == va){
1682                                 if ((ModFlags & va) == va){
1683                                         Report.Error (
1684                                                 503, Location, "The abstract method " +
1685                                                 MakeName (parent) + "can not be marked virtual");
1686                                         error = true;
1687                                 }
1688                         }
1689
1690                         if ((ModFlags & Modifiers.ABSTRACT) != 0){
1691                                 if ((parent.ModFlags & Modifiers.ABSTRACT) == 0){
1692                                         Report.Error (
1693                                                 513, Location, MakeName (parent) +
1694                                                 " is abstract but its container class is not");
1695                                         error = true;
1696                                 }
1697                         }
1698
1699                         if ((ModFlags & va) != 0 && ((ModFlags & Modifiers.PRIVATE) != 0)){
1700                                 Report.Error (
1701                                         621, Location, MakeName (parent) +
1702                                         " virtual or abstract members can not be private");
1703                                 error = true;
1704                         }
1705
1706                         if ((ModFlags & Modifiers.STATIC) != 0){
1707                                 if ((ModFlags & vao) != 0){
1708                                         Report.Error (
1709                                                 112, Location, "static method " + MakeName (parent) +
1710                                                 " can not be marked as virtual, abstract or override");
1711
1712                                         error = true;
1713                                 }
1714                         }
1715                         
1716                         if ((ModFlags & Modifiers.OVERRIDE) != 0 && ((ModFlags & nv) != 0)){
1717                                 Report.Error (
1718                                         113, Location, MakeName (parent) +
1719                                         "marked as override cannot be marked as new or virtual");
1720                                 error = true;
1721                         }
1722
1723                         if (error)
1724                                 return null;
1725
1726                         //
1727                         // Finally, define the method
1728                         //
1729                         
1730                         MethodBuilder = parent.TypeBuilder.DefineMethod (
1731                                 Name, flags,
1732                                 GetCallingConvention (parent is Class),
1733                                 ret_type, parameters);
1734
1735                         //
1736                         // HACK because System.Reflection.Emit is lame
1737                         //
1738                         TypeManager.RegisterMethod (MethodBuilder, parameters);
1739                         
1740                         ParameterInfo = new InternalParameters (parameters);
1741
1742                         //
1743                         // This is used to track the Entry Point,
1744                         //
1745                         // FIXME: Allow pluggable entry point, check arguments, etc.
1746                         //
1747                         if (Name == "Main"){
1748                                 if ((ModFlags & Modifiers.STATIC) != 0){
1749                                         parent.RootContext.EntryPoint = MethodBuilder;
1750                                 }
1751                         }
1752                         
1753                         //
1754                         // Define each type attribute (in/out/ref) and
1755                         // the argument names.
1756                         //
1757                         Parameter [] p = Parameters.FixedParameters;
1758                         if (p != null){
1759                                 int i;
1760                                 
1761                                 for (i = 0; i < p.Length; i++)
1762                                         MethodBuilder.DefineParameter (
1763                                                 i + 1, p [i].Attributes, p [i].Name);
1764
1765                                 if (i != parameters.Length)
1766                                         Console.WriteLine ("Implement the type definition for params");
1767                         }
1768
1769                         return MethodBuilder;
1770                 }
1771
1772                 //
1773                 // Emits the code
1774                 // 
1775                 public void Emit (TypeContainer parent)
1776                 {
1777                         ILGenerator ig = MethodBuilder.GetILGenerator ();
1778                         EmitContext ec = new EmitContext (parent, ig, GetReturnType (parent), ModFlags);
1779                         
1780                         ec.EmitTopBlock (Block);
1781                 }
1782         }
1783
1784         public abstract class ConstructorInitializer {
1785                 ArrayList argument_list;
1786                 ConstructorInfo parent_constructor;
1787                 Location location;
1788                 
1789                 public ConstructorInitializer (ArrayList argument_list, Location location)
1790                 {
1791                         this.argument_list = argument_list;
1792                         this.location = location;
1793                 }
1794
1795                 public ArrayList Arguments {
1796                         get {
1797                                 return argument_list;
1798                         }
1799                 }
1800
1801                 public bool Resolve (EmitContext ec)
1802                 {
1803                         Expression parent_constructor_group;
1804                         
1805                         if (argument_list != null){
1806                                 for (int i = argument_list.Count; i > 0; ){
1807                                         --i;
1808
1809                                         Argument a = (Argument) argument_list [i];
1810                                         if (!a.Resolve (ec))
1811                                                 return false;
1812                                 }
1813                         }
1814
1815                         parent_constructor_group = Expression.MemberLookup (
1816                                 ec,
1817                                 ec.TypeContainer.TypeBuilder.BaseType, ".ctor", false,
1818                                 MemberTypes.Constructor,
1819                                 BindingFlags.Public | BindingFlags.Instance, location);
1820
1821                         if (parent_constructor_group == null){
1822                                 Console.WriteLine ("Could not find a constructor in our parent");
1823                                 return false;
1824                         }
1825                         
1826                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
1827                                 (MethodGroupExpr) parent_constructor_group, argument_list, location);
1828                         
1829                         if (parent_constructor == null)
1830                                 return false;
1831                         
1832                         return true;
1833                 }
1834
1835                 public void Emit (EmitContext ec)
1836                 {
1837                         ec.ig.Emit (OpCodes.Ldarg_0);
1838                         if (argument_list != null)
1839                                 Invocation.EmitArguments (ec, parent_constructor, argument_list);
1840                         ec.ig.Emit (OpCodes.Call, parent_constructor);
1841                 }
1842         }
1843
1844         public class ConstructorBaseInitializer : ConstructorInitializer {
1845                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1846                 {
1847                 }
1848         }
1849
1850         public class ConstructorThisInitializer : ConstructorInitializer {
1851                 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1852                 {
1853                 }
1854         }
1855         
1856         public class Constructor : MethodCore {
1857                 public ConstructorBuilder ConstructorBuilder;
1858                 public ConstructorInitializer Initializer;
1859
1860                 // <summary>
1861                 //   Modifiers allowed for a constructor.
1862                 // </summary>
1863                 const int AllowedModifiers =
1864                         Modifiers.PUBLIC |
1865                         Modifiers.PROTECTED |
1866                         Modifiers.INTERNAL |
1867                         Modifiers.STATIC |
1868                         Modifiers.PRIVATE;
1869
1870                 //
1871                 // The spec claims that static is not permitted, but
1872                 // my very own code has static constructors.
1873                 //
1874                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
1875                         : base (name, args, l)
1876                 {
1877                         Initializer = init;
1878                 }
1879
1880                 //
1881                 // Returns true if this is a default constructor
1882                 //
1883                 public bool IsDefault ()
1884                 {
1885                         return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
1886                                 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
1887                                 (Initializer is ConstructorBaseInitializer) &&
1888                                 (Initializer.Arguments == null);
1889                 }
1890
1891                 //
1892                 // Creates the ConstructorBuilder
1893                 //
1894                 public ConstructorBuilder Define (TypeContainer parent)
1895                 {
1896                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
1897                                                MethodAttributes.SpecialName);
1898
1899                         Type [] parameters = ParameterTypes (parent);
1900
1901                         if ((ModFlags & Modifiers.STATIC) != 0)
1902                                 ca |= MethodAttributes.Static;
1903                         else {
1904                                 if (parent is Struct && parameters == null){
1905                                         Report.Error (
1906                                                 568, Location, 
1907                                                 "Structs can not contain explicit parameterless " +
1908                                                 "constructors");
1909                                         return null;
1910                                 }
1911                         }
1912
1913                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
1914                                 ca, GetCallingConvention (parent is Class),
1915                                 parameters);
1916                         //
1917                         // HACK because System.Reflection.Emit is lame
1918                         //
1919                         TypeManager.RegisterMethod (ConstructorBuilder, parameters);
1920
1921                         ParameterInfo = new InternalParameters (parameters);
1922
1923                         return ConstructorBuilder;
1924                 }
1925
1926                 //
1927                 // Emits the code
1928                 //
1929                 public void Emit (TypeContainer parent)
1930                 {
1931                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
1932                         EmitContext ec = new EmitContext (parent, ig, null, ModFlags, true);
1933
1934                         if (parent is Class){
1935                                 if (Initializer == null)
1936                                         Initializer = new ConstructorBaseInitializer (null, parent.Location);
1937
1938                                 if (!Initializer.Resolve (ec))
1939                                         return;
1940                         }
1941
1942                         //
1943                         // Classes can have base initializers and instance field initializers.
1944                         //
1945                         if (parent is Class){
1946                                 if ((ModFlags & Modifiers.STATIC) == 0)
1947                                         Initializer.Emit (ec);
1948                                 parent.EmitFieldInitializers (ec, false);
1949                         }
1950                         
1951                         if ((ModFlags & Modifiers.STATIC) != 0)
1952                                 parent.EmitFieldInitializers (ec, true);
1953
1954                         ec.EmitTopBlock (Block);
1955                 }
1956         }
1957         
1958         public class Field {
1959                 public readonly string Type;
1960                 public readonly Object Initializer;
1961                 public readonly string Name;
1962                 public readonly int    ModFlags;
1963                 public readonly Attributes OptAttributes;
1964                 public FieldBuilder  FieldBuilder;
1965                 
1966                 
1967                 // <summary>
1968                 //   Modifiers allowed in a class declaration
1969                 // </summary>
1970                 const int AllowedModifiers =
1971                         Modifiers.NEW |
1972                         Modifiers.PUBLIC |
1973                         Modifiers.PROTECTED |
1974                         Modifiers.INTERNAL |
1975                         Modifiers.PRIVATE |
1976                         Modifiers.STATIC |
1977                         Modifiers.READONLY;
1978
1979                 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
1980                 {
1981                         Type = type;
1982                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1983                         Name = name;
1984                         Initializer = expr_or_array_init;
1985                         OptAttributes = attrs;
1986                 }
1987
1988                 public void Define (TypeContainer parent)
1989                 {
1990                         Type t = parent.LookupType (Type, false);
1991
1992                         if (t == null)
1993                                 return;
1994                         
1995                         FieldBuilder = parent.TypeBuilder.DefineField (
1996                                 Name, t, Modifiers.FieldAttr (ModFlags));
1997                 }
1998         }
1999
2000         public class Property {
2001                 
2002                 public readonly string Type;
2003                 public readonly string Name;
2004                 public readonly int    ModFlags;
2005                 public Block           Get, Set;
2006                 public PropertyBuilder PropertyBuilder;
2007                 public Attributes OptAttributes;
2008                 MethodBuilder GetBuilder, SetBuilder;
2009
2010                 //
2011                 // The type, once we compute it.
2012                 
2013                 Type PropertyType;
2014
2015                 const int AllowedModifiers =
2016                         Modifiers.NEW |
2017                         Modifiers.PUBLIC |
2018                         Modifiers.PROTECTED |
2019                         Modifiers.INTERNAL |
2020                         Modifiers.PRIVATE |
2021                         Modifiers.STATIC |
2022                         Modifiers.SEALED |
2023                         Modifiers.OVERRIDE |
2024                         Modifiers.ABSTRACT |
2025                         Modifiers.VIRTUAL;
2026                 
2027                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
2028                 {
2029                         Type = type;
2030                         Name = name;
2031                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2032                         Get = get_block;
2033                         Set = set_block;
2034                         OptAttributes = attrs;
2035                 }
2036
2037                 public void Define (TypeContainer parent)
2038                 {
2039
2040                         MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
2041                                         
2042                         // FIXME - PropertyAttributes.HasDefault ?
2043
2044                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2045                                                        PropertyAttributes.SpecialName;
2046                 
2047                 
2048                         PropertyType = parent.LookupType (Type, false);
2049                         Type [] parameters = new Type [1];
2050                         parameters [0] = PropertyType;
2051
2052                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2053                                 Name, prop_attr, PropertyType, null);
2054
2055                         if (Get != null)
2056                         {
2057                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2058                                         "get_" + Name, method_attr, PropertyType, null);
2059                                 PropertyBuilder.SetGetMethod (GetBuilder);
2060                                 //
2061                                 // HACK because System.Reflection.Emit is lame
2062                                 //
2063                                 TypeManager.RegisterMethod (GetBuilder, null);
2064                         }
2065                         
2066                         if (Set != null)
2067                         {
2068                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2069                                         "set_" + Name, method_attr, null, parameters);
2070                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
2071                                 PropertyBuilder.SetSetMethod (SetBuilder);
2072                                 //
2073                                 // HACK because System.Reflection.Emit is lame
2074                                 //
2075                                 TypeManager.RegisterMethod (SetBuilder, parameters);
2076                         }
2077
2078                         //
2079                         // HACK for the reasons exposed above
2080                         //
2081                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2082                 }
2083
2084                 public void Emit (TypeContainer tc)
2085                 {
2086                         ILGenerator ig;
2087                         EmitContext ec;
2088
2089                         if (Get != null){
2090                                 ig = GetBuilder.GetILGenerator ();
2091                                 ec = new EmitContext (tc, ig, PropertyType, ModFlags);
2092                                 
2093                                 ec.EmitTopBlock (Get);
2094                         }
2095
2096                         if (Set != null){
2097                                 ig = SetBuilder.GetILGenerator ();
2098                                 ec = new EmitContext (tc, ig, null, ModFlags);
2099                                 
2100                                 ec.EmitTopBlock (Set);
2101                         }
2102                 }
2103         }
2104
2105         public class Event {
2106                 
2107                 const int AllowedModifiers =
2108                         Modifiers.NEW |
2109                         Modifiers.PUBLIC |
2110                         Modifiers.PROTECTED |
2111                         Modifiers.INTERNAL |
2112                         Modifiers.PRIVATE |
2113                         Modifiers.STATIC |
2114                         Modifiers.VIRTUAL |
2115                         Modifiers.SEALED |
2116                         Modifiers.OVERRIDE |
2117                         Modifiers.ABSTRACT;
2118
2119                 public readonly string    Type;
2120                 public readonly string    Name;
2121                 public readonly Object    Initializer;
2122                 public readonly int       ModFlags;
2123                 public readonly Block     Add;
2124                 public readonly Block     Remove;
2125                 public EventBuilder       EventBuilder;
2126                 public Attributes         OptAttributes;
2127                 
2128                 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
2129                               Attributes attrs)
2130                 {
2131                         Type = type;
2132                         Name = name;
2133                         Initializer = init;
2134                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
2135                         Add = add_block;
2136                         Remove = rem_block;
2137                         OptAttributes = attrs;
2138                 }
2139
2140                 public void Define (TypeContainer parent)
2141                 {
2142                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
2143
2144                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
2145                         
2146                         MethodBuilder mb;
2147
2148                         Type t = parent.LookupType (Type, false);
2149                         Type [] parameters = new Type [1];
2150                         parameters [0] = t;
2151                         
2152                         EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
2153                         
2154                         if (Add != null) {
2155                                 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null,
2156                                                                       parameters);
2157                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2158                                 EventBuilder.SetAddOnMethod (mb);
2159                                 //
2160                                 // HACK because System.Reflection.Emit is lame
2161                                 //
2162                                 TypeManager.RegisterMethod (mb, parameters);
2163                         }
2164
2165                         if (Remove != null) {
2166                                 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null,
2167                                                                       parameters);
2168                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2169                                 EventBuilder.SetRemoveOnMethod (mb);
2170
2171                                 //
2172                                 // HACK because System.Reflection.Emit is lame
2173                                 //
2174                                 TypeManager.RegisterMethod (mb, parameters);
2175                         }
2176                 }
2177                 
2178         }
2179
2180         public class Indexer {
2181
2182                 const int AllowedModifiers =
2183                         Modifiers.NEW |
2184                         Modifiers.PUBLIC |
2185                         Modifiers.PROTECTED |
2186                         Modifiers.INTERNAL |
2187                         Modifiers.PRIVATE |
2188                         Modifiers.VIRTUAL |
2189                         Modifiers.SEALED |
2190                         Modifiers.OVERRIDE |
2191                         Modifiers.ABSTRACT;
2192
2193                 public readonly string     Type;
2194                 public readonly string     InterfaceType;
2195                 public readonly Parameters FormalParameters;
2196                 public readonly int        ModFlags;
2197                 public readonly Block      Get;
2198                 public readonly Block      Set;
2199                 public Attributes          OptAttributes;
2200                 public MethodBuilder GetMethodBuilder;
2201                 public MethodBuilder SetMethodBuilder;
2202                 
2203
2204                 public Indexer (string type, string int_type, int flags, Parameters parms,
2205                                 Block get_block, Block set_block, Attributes attrs)
2206                 {
2207
2208                         Type = type;
2209                         InterfaceType = int_type;
2210                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
2211                         FormalParameters = parms;
2212                         Get = get_block;
2213                         Set = set_block;
2214                         OptAttributes = attrs;
2215                 }
2216
2217                 public void Define (TypeContainer parent)
2218                 {
2219                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
2220                         
2221                         Type ret_type = parent.LookupType (Type, false);
2222                         Type [] parameters = FormalParameters.GetParameterInfo (parent);
2223
2224                         GetMethodBuilder = parent.TypeBuilder.DefineMethod (
2225                                 "get_Item", attr, ret_type, parameters);
2226                         SetMethodBuilder = parent.TypeBuilder.DefineMethod (
2227                                 "set_Item", attr, ret_type, parameters);
2228
2229                         //
2230                         // HACK because System.Reflection.Emit is lame
2231                         //
2232                         TypeManager.RegisterMethod (GetMethodBuilder, parameters);
2233                         TypeManager.RegisterMethod (SetMethodBuilder, parameters);
2234
2235                         Parameter [] p = FormalParameters.FixedParameters;
2236
2237                         if (p != null) {
2238                                 int i;
2239                                 
2240                                 for (i = 0; i < p.Length; ++i) {
2241                                         GetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
2242                                         SetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
2243                                 }
2244                                 
2245                                 if (i != parameters.Length)
2246                                         Console.WriteLine ("Implement type definition for params");
2247                         }
2248
2249                 }
2250                 
2251         }
2252
2253         public class Operator {
2254
2255                 const int AllowedModifiers =
2256                         Modifiers.PUBLIC |
2257                         Modifiers.STATIC;
2258
2259                 const int RequiredModifiers =
2260                         Modifiers.PUBLIC |
2261                         Modifiers.STATIC;
2262
2263                 public enum OpType {
2264
2265                         // Unary operators
2266                         Negate,
2267                         BitComplement,
2268                         Increment,
2269                         Decrement,
2270                         True,
2271                         False,
2272
2273                         // Unary and Binary operators
2274                         Addition,
2275                         Subtraction,
2276                         
2277                         // Binary operators
2278                         Multiply,
2279                         Division,
2280                         Modulus,
2281                         BitwiseAnd,
2282                         BitwiseOr,
2283                         ExclusiveOr,
2284                         LeftShift,
2285                         RightShift,
2286                         Equality,
2287                         Inequality,
2288                         GreaterThan,
2289                         LessThan,
2290                         GreaterThanOrEqual,
2291                         LessThanOrEqual,
2292
2293                         // Implicit and Explicit
2294                         Implicit,
2295                         Explicit
2296                 };
2297
2298                 public readonly OpType OperatorType;
2299                 public readonly string ReturnType;
2300                 public readonly string FirstArgType;
2301                 public readonly string FirstArgName;
2302                 public readonly string SecondArgType;
2303                 public readonly string SecondArgName;
2304                 public readonly int    ModFlags;
2305                 public readonly Block  Block;
2306                 public Attributes      OptAttributes;
2307                 public MethodBuilder   OperatorMethodBuilder;
2308                 public Location        Location;
2309                 
2310                 public string MethodName;
2311                 public Method OperatorMethod;
2312
2313                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
2314                                  string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
2315                 {
2316                         OperatorType = type;
2317                         ReturnType = ret_type;
2318                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
2319                         FirstArgType = arg1type;
2320                         FirstArgName = arg1name;
2321                         SecondArgType = arg2type;
2322                         SecondArgName = arg2name;
2323                         Block = block;
2324                         OptAttributes = attrs;
2325                         Location = loc;
2326                 }
2327
2328                 string Prototype (TypeContainer parent)
2329                 {
2330                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
2331                                 SecondArgType + ")";
2332                 }
2333                 
2334                 public void Define (TypeContainer parent)
2335                 {
2336                         int length = 1;
2337                         MethodName = "op_" + OperatorType;
2338                         
2339                         if (SecondArgType != null)
2340                                 length = 2;
2341                         
2342                         Parameter [] param_list = new Parameter [length];
2343
2344                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2345                                 Report.Error (
2346                                         558, Location, 
2347                                         "User defined operators `" +
2348                                         Prototype (parent) +
2349                                         "' must be declared static and public");
2350                         }
2351
2352                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
2353                                                        Parameter.Modifier.NONE, null);
2354                         if (SecondArgType != null)
2355                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
2356                                                                Parameter.Modifier.NONE, null);
2357                         
2358                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
2359                                                      new Parameters (param_list, null),
2360                                                      OptAttributes, Location.Null);
2361                         
2362                         OperatorMethod.Define (parent);
2363                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
2364
2365                         Type [] param_types = OperatorMethod.ParameterTypes (parent);
2366                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
2367                         Type return_type = OperatorMethod.GetReturnType (parent);
2368                         Type first_arg_type = param_types [0];
2369
2370                         // Rules for conversion operators
2371                         
2372                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2373                                 
2374                                 if (first_arg_type == return_type && first_arg_type == declaring_type)
2375                                         Report.Error (555, Location,
2376                                                "User-defined conversion cannot take an object of the enclosing type " +
2377                                                "and convert to an object of the enclosing type");
2378                                 
2379                                 if (first_arg_type != declaring_type && return_type != declaring_type)
2380                                         Report.Error (556, Location, 
2381                                                "User-defined conversion must convert to or from the enclosing type");
2382                                 
2383                                 if (first_arg_type == TypeManager.object_type || return_type == TypeManager.object_type)
2384                                         Report.Error (-8, Location,
2385                                                "User-defined conversion cannot convert to or from object type");
2386                                 
2387                                 if (first_arg_type.IsInterface || return_type.IsInterface)
2388                                         Report.Error (-9, Location,
2389                                                "User-defined conversion cannot convert to or from an interface type");   
2390                                 
2391                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type))
2392                                         Report.Error (-10, Location,
2393                                                 "User-defined conversion cannot convert between types that " +
2394                                                 "derive from each other"); 
2395                                 
2396                         } else if (SecondArgType == null) {
2397                                 // Checks for Unary operators
2398                                 
2399                                 if (first_arg_type != declaring_type) 
2400                                         Report.Error (562, Location,
2401                                                    "The parameter of a unary operator must be the containing type");
2402                                 
2403                                 
2404                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2405                                         if (return_type != declaring_type)
2406                                                 Report.Error (559, Location,
2407                                                        "The parameter and return type for ++ and -- " +
2408                                                        "must be the containing type");
2409                                         
2410                                 }
2411                                 
2412                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2413                                         if (return_type != TypeManager.bool_type)
2414                                                 Report.Error (215, Location,
2415                                                        "The return type of operator True or False " +
2416                                                        "must be bool");
2417                                 }
2418                                 
2419                         } else {
2420                                 // Checks for Binary operators
2421                                 
2422                                 if (first_arg_type != declaring_type &&
2423                                     param_types [1] != declaring_type)
2424                                         Report.Error (563, Location,
2425                                                "One of the parameters of a binary operator must be the containing type");
2426                         }
2427                         
2428                 
2429                         
2430                 }
2431                 
2432                 public void Emit (TypeContainer parent)
2433                 {
2434                         OperatorMethod.Block = Block;
2435                         OperatorMethod.Emit (parent);
2436                 }
2437                 
2438
2439         }
2440
2441         //
2442         // This is used to compare method signatures
2443         //
2444         struct MethodSignature {
2445                 public string Name;
2446                 public Type RetType;
2447                 public Type [] Parameters;
2448                 
2449                 public MethodSignature (string name, Type ret_type, Type [] parameters)
2450                 {
2451                         Name = name;
2452                         RetType = ret_type;
2453                         Parameters = parameters;
2454
2455                         if (parameters != null){
2456                                 if (parameters.Length == 0)
2457                                         Parameters = null;
2458                         } 
2459                 }
2460                 
2461                 public override int GetHashCode ()
2462                 {
2463                         return Name.GetHashCode ();
2464                 }
2465
2466                 public override bool Equals (Object o)
2467                 {
2468                         MethodSignature other = (MethodSignature) o;
2469
2470                         if (other.Name != Name)
2471                                 return false;
2472
2473                         if (other.RetType != RetType)
2474                                 return false;
2475                         
2476                         if (Parameters == null){
2477                                 if (other.Parameters == null)
2478                                         return true;
2479                                 return false;
2480                         }
2481
2482                         if (other.Parameters == null)
2483                                 return false;
2484                         
2485                         int c = Parameters.Length;
2486                         if (other.Parameters.Length != c)
2487                                 return false;
2488
2489                         for (int i = 0; i < c; i++)
2490                                 if (other.Parameters [i] != Parameters [i])
2491                                         return false;
2492
2493                         return true;
2494                 }
2495         }               
2496 }