2001-10-22 Ravi Pratap <ravi@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_parameters;
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_parameters == null)
926                                         method_builders_to_parameters = 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                                                 InternalParameters ip = c.ParameterInfo;
937                                                 
938                                                 method_builders_to_parameters.Add (MakeKey (builder), ip);
939                                         }
940                                 }
941
942                                 foreach (object o in remove_list)
943                                         constructors.Remove (o);
944                                 
945                                 remove_list.Clear ();
946                         } 
947
948                         if (Methods != null){
949                                 foreach (Method m in methods){
950                                         MethodBase key = m.Define (this);
951
952                                         //
953                                         // FIXME:
954                                         // The following key is not enoug
955                                         // class x { public void X ()  {} }
956                                         // class y : x { public void X () {}}
957                                         // fails
958                                         
959                                         if (key == null)
960                                                 remove_list.Add (m);
961                                         else {
962                                                 InternalParameters ip = m.ParameterInfo;
963                                                 method_builders_to_parameters.Add (MakeKey (key), ip);
964                                         }
965                                 }
966                                 foreach (object o in remove_list)
967                                         methods.Remove (o);
968                                 
969                                 remove_list.Clear ();
970                         }
971
972                         if (Properties != null) {
973                                 foreach (Property p in Properties)
974                                         p.Define (this);
975                         }
976
977                         if (Enums != null) {
978                                 foreach (Enum e in Enums)
979                                         e.Define (this);
980                         }
981
982                         if (Events != null) {
983                                 foreach (Event e in Events)
984                                         e.Define (this);
985                         }
986
987                         if (Indexers != null) {
988                                 foreach (Indexer i in Indexers)
989                                         i.Define (this);
990                         }
991
992                         if (Operators != null) {
993                                 foreach (Operator o in Operators) {
994                                         o.Define (this);
995
996                                         InternalParameters ip = o.OperatorMethod.ParameterInfo;
997                                         
998                                         method_builders_to_parameters.Add (
999                                                 MakeKey (o.OperatorMethodBuilder), ip);
1000                                 }
1001                         }
1002
1003                         if (Delegates != null) {
1004                                 foreach (Delegate d in Delegates) 
1005                                         d.Populate (this);
1006                         }
1007                         
1008                         if (Types != null) {
1009                                 foreach (TypeContainer tc in Types)
1010                                         tc.Populate ();
1011                         }
1012                         
1013                 }
1014
1015                 // <summary>
1016                 //   Since System.Reflection.Emit can not retrieve parameter information
1017                 //   from methods that are dynamically defined, we have to look those
1018                 //   up ourselves using this
1019                 // </summary>
1020                 static public ParameterData LookupParametersByBuilder (MethodBase mb)
1021                 {
1022                         return (ParameterData) method_builders_to_parameters [MakeKey (mb)];
1023                 }
1024
1025                 // <summary>
1026                 //   Indexers and properties can register more than one method at once,
1027                 //   so we need to provide a mechanism for those to register their
1028                 //   various methods to parameter info mappers.
1029                 // </summary>
1030                 static public void RegisterParameterForBuilder (MethodBase mb, InternalParameters pi)
1031                 {
1032                         method_builders_to_parameters.Add (MakeKey (mb), pi);
1033                 }
1034                 
1035                 public Type LookupType (string name, bool silent)
1036                 {
1037                         return RootContext.LookupType (this, name, silent);
1038                 }
1039
1040                 public string LookupAlias (string Name)
1041                 {
1042                         //
1043                         // Read the comments on `mcs/mcs/TODO' for details
1044                         // 
1045                         return null;
1046                 }
1047                 
1048                 //
1049                 // This function is based by a delegate to the FindMembers routine
1050                 //
1051                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1052                 {
1053                         return true;
1054                 }
1055                 
1056                 //
1057                 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1058                 {
1059                         MethodInfo mi = (MethodInfo) m;
1060
1061                         return mi.IsAbstract;
1062                 }
1063
1064                 // This filter is used by FindMembers, and we just keep
1065                 // a global for the filter to `AlwaysAccept'
1066                 //
1067                 static MemberFilter accepting_filter;
1068                 
1069                 // <summary>
1070                 //    This delegate is a MemberFilter used to extract the 
1071                 //    abstact methods from a type.  
1072                 // </summary>
1073                 static MemberFilter abstract_method_filter;
1074
1075                 static TypeContainer ()
1076                 {
1077                         abstract_method_filter = new MemberFilter (IsAbstractMethod);
1078                         accepting_filter = new MemberFilter (AlwaysAccept);
1079                 }
1080                 
1081                 // <summary>
1082                 //   This method returns the members of this type just like Type.FindMembers would
1083                 //   Only, we need to use this for types which are _being_ defined because MS' 
1084                 //   implementation can't take care of that.
1085                 // </summary>
1086                 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1087                                                   MemberFilter filter, object criteria)
1088                 {
1089                         ArrayList members = new ArrayList ();
1090
1091                         if (filter == null)
1092                                 filter = accepting_filter; 
1093                         
1094                         if ((mt & MemberTypes.Field) != 0 && Fields != null) {
1095                                 foreach (Field f in Fields) {
1096                                         if (filter (f.FieldBuilder, criteria) == true)
1097                                                 members.Add (f.FieldBuilder);
1098                                 }
1099                         }
1100
1101                         if ((mt & MemberTypes.Method) != 0) {
1102                                 if (Methods != null){
1103                                         foreach (Method m in Methods) {
1104                                                 MethodBuilder mb = m.MethodBuilder;
1105
1106                                                 if (filter (mb, criteria) == true)
1107                                                         members.Add (mb);
1108                                         }
1109                                 }
1110
1111                                 if (Operators != null){
1112                                         foreach (Operator o in Operators) {
1113                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1114
1115                                                 if (filter (ob, criteria) == true)
1116                                                         members.Add (ob);
1117                                         }
1118                                 }
1119                         }
1120
1121                         // FIXME : This ain't right because EventBuilder is not a
1122                         // MemberInfo. What do we do ?
1123                         
1124                         if ((mt & MemberTypes.Event) != 0 && Events != null) {
1125                                 //foreach (Event e in Events) {
1126                                 //      if (filter (e.EventBuilder, criteria) == true)
1127                                 //              mi [i++] = e.EventBuilder;
1128                                 //}
1129                         }
1130
1131                         if ((mt & MemberTypes.Property) != 0){
1132                                 if (Properties != null)
1133                                         foreach (Property p in Properties) {
1134                                                 if (filter (p.PropertyBuilder, criteria) == true)
1135                                                         members.Add (p.PropertyBuilder);
1136                                         }
1137
1138                                 if (Indexers != null)
1139                                         foreach (Indexer ix in Indexers){
1140                                                 if (filter (ix.PropertyBuilder, criteria) == true)
1141                                                         members.Add (ix.PropertyBuilder);
1142                                         }
1143                         }
1144                         
1145                         if ((mt & MemberTypes.NestedType) != 0 && Types != null) {
1146                                 foreach (TypeContainer t in Types) { 
1147                                         if (filter (t.TypeBuilder, criteria) == true)
1148                                                 members.Add (t.TypeBuilder);
1149                                 }
1150                         }
1151
1152                         if ((mt & MemberTypes.Constructor) != 0){
1153                                 if (Constructors != null){
1154                                         foreach (Constructor c in Constructors){
1155                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1156
1157                                                 if (filter (cb, criteria) == true)
1158                                                         members.Add (cb);
1159                                         }
1160                                 }
1161                         }
1162
1163                         //
1164                         // Lookup members in parent if requested.
1165                         //
1166                         if ((bf & BindingFlags.DeclaredOnly) == 0){
1167                                 MemberInfo [] mi;
1168
1169                                 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1170                                 if (mi != null)
1171                                         members.AddRange (mi);
1172                         }
1173                         
1174                         int count = members.Count;
1175                         if (count > 0){
1176                                 MemberInfo [] mi = new MemberInfo [count];
1177                                 members.CopyTo (mi);
1178                                 return mi;
1179                         }
1180
1181                         return null;
1182                 }
1183
1184                 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1185                                                          MemberFilter filter, object criteria)
1186                 {
1187                         TypeContainer tc = TypeManager.LookupTypeContainer (t);
1188
1189                         if (tc != null)
1190                                 return tc.FindMembers (mt, bf, filter, criteria);
1191                         else
1192                                 return t.FindMembers (mt, bf, filter, criteria);
1193                 }
1194                 
1195
1196                 Hashtable pending_implementations;
1197                 
1198                 // <summary>
1199                 //   Requires that the methods in `mi' be implemented for this
1200                 //   class
1201                 // </summary>
1202                 public void RequireMethods (MethodInfo [] mi, object data)
1203                 {
1204                         if (pending_implementations == null)
1205                                 pending_implementations = new Hashtable ();
1206
1207                         foreach (MethodInfo m in mi){
1208                                 Type [] types = TypeManager.GetArgumentTypes (m);
1209
1210                                 pending_implementations.Add (
1211                                         new MethodSignature 
1212                                                 (m.Name, m.ReturnType, types), data);
1213                         }
1214                 }
1215
1216                 // <summary>
1217                 //   Used to set the list of interfaces that this typecontainer
1218                 //   must implement.
1219                 // </summary>
1220                 //
1221                 // <remarks>
1222                 //   For each element exposed by the type, we create a MethodSignature
1223                 //   struct that we will label as `implemented' as we define the various
1224                 //   methods.
1225                 // </remarks>
1226                 public void SetRequiredInterfaces (Type [] ifaces)
1227                 {
1228                         foreach (Type t in ifaces){
1229                                 MethodInfo [] mi;
1230
1231                                 if (t is TypeBuilder){
1232                                         Interface iface = RootContext.TypeManager.LookupInterface (t);
1233
1234                                         mi = iface.GetMethods ();
1235                                 } else
1236                                         mi = t.GetMethods ();
1237
1238                                 RequireMethods (mi, t);
1239                         }
1240                 }
1241
1242                 // <summary>
1243                 //   If a method with name `Name', return type `ret_type' and
1244                 //   arguments `args' implements an interface, this method will
1245                 //   return true.
1246                 //
1247                 //   This will remove the method from the list of "pending" methods
1248                 //   that are required to be implemented for this class as a side effect.
1249                 // 
1250                 // </summary>
1251                 public bool IsInterfaceMethod (string Name, Type ret_type, Type [] args)
1252                 {
1253                         MethodSignature query;
1254
1255                         if (pending_implementations == null)
1256                                 return false;
1257
1258                         query = new MethodSignature (Name, ret_type, args);
1259
1260                         if (pending_implementations.Contains (query)){
1261                                 pending_implementations.Remove (query);
1262                                 return true;
1263                         }
1264
1265                         return false;
1266                 }
1267
1268                 // <summary>
1269                 //   Verifies that any pending abstract methods or interface methods
1270                 //   were implemented.
1271                 // </summary>
1272                 void VerifyPendingMethods ()
1273                 {
1274                         int pending = 0;
1275                         
1276                         foreach (object m in pending_implementations){
1277                                 DictionaryEntry de = (DictionaryEntry) m;
1278                                 Type t = (Type) de.Value;
1279                                 pending++;
1280
1281                                 MethodSignature method = (MethodSignature) de.Key;
1282
1283                                 if (t.IsInterface)
1284                                         Report.Error (
1285                                                 536, Location,
1286                                                 "`" + Name + "' does not implement interface member `" +
1287                                                 t.FullName + "." + method.Name + "'");
1288                                 else
1289                                         Report.Error (
1290                                                 534, Location,
1291                                                 "`" + Name + "' does not implement inherited abstract " +
1292                                                 "member `" + t.FullName + "." + method.Name + "'");
1293                         }
1294                 }
1295                 
1296                 // <summary>
1297                 //   Emits the code, this step is performed after all
1298                 //   the types, enumerations, constructors
1299                 // </summary>
1300                 public void Emit ()
1301                 {
1302                         if (Constructors != null)
1303                                 foreach (Constructor c in Constructors)
1304                                         c.Emit (this);
1305                         
1306                         if (methods != null)
1307                                 foreach (Method m in methods)
1308                                         m.Emit (this);
1309
1310                         if (operators != null)
1311                                 foreach (Operator o in operators)
1312                                         o.Emit (this);
1313
1314                         if (properties != null)
1315                                 foreach (Property p in properties)
1316                                         p.Emit (this);
1317
1318                         if (pending_implementations != null)
1319                                 VerifyPendingMethods ();
1320
1321                         if (types != null)
1322                                 foreach (TypeContainer tc in types)
1323                                         tc.Emit ();
1324
1325                 }
1326
1327                 public void CloseType ()
1328                 {
1329                         TypeBuilder.CreateType ();
1330                         
1331                         foreach (TypeContainer tc in Types)
1332                                 tc.CloseType ();
1333
1334                         if (Delegates != null)
1335                                 foreach (Delegate d in Delegates)
1336                                         d.CloseDelegate ();
1337                 }
1338
1339                 string MakeName (string n)
1340                 {
1341                         return "`" + Name + "." + n + "'";
1342                 }
1343                 
1344                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1345                 {
1346                         return 0;
1347                 }
1348         }
1349
1350         public class Class : TypeContainer {
1351                 // <summary>
1352                 //   Modifiers allowed in a class declaration
1353                 // </summary>
1354                 public const int AllowedModifiers =
1355                         Modifiers.NEW |
1356                         Modifiers.PUBLIC |
1357                         Modifiers.PROTECTED |
1358                         Modifiers.INTERNAL |
1359                         Modifiers.PRIVATE |
1360                         Modifiers.ABSTRACT |
1361                         Modifiers.SEALED;
1362
1363                 public Class (RootContext rc, TypeContainer parent, string name, int mod,
1364                               Attributes attrs, Location l)
1365                         : base (rc, parent, name, l)
1366                 {
1367                         int accmods;
1368
1369                         if (parent.Parent == null)
1370                                 accmods = Modifiers.INTERNAL;
1371                         else
1372                                 accmods = Modifiers.PRIVATE;
1373                         
1374                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1375                         this.attributes = attrs;
1376                 }
1377
1378                 //
1379                 // FIXME: How do we deal with the user specifying a different
1380                 // layout?
1381                 //
1382                 public override TypeAttributes TypeAttr {
1383                         get {
1384                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1385                         }
1386                 }
1387         }
1388
1389         public class Struct : TypeContainer {
1390                 // <summary>
1391                 //   Modifiers allowed in a struct declaration
1392                 // </summary>
1393                 public const int AllowedModifiers =
1394                         Modifiers.NEW |
1395                         Modifiers.PUBLIC |
1396                         Modifiers.PROTECTED |
1397                         Modifiers.INTERNAL |
1398                         Modifiers.PRIVATE;
1399
1400                 public Struct (RootContext rc, TypeContainer parent, string name, int mod,
1401                                Attributes attrs, Location l)
1402                         : base (rc, parent, name, l)
1403                 {
1404                         int accmods;
1405                         
1406                         if (parent.Parent == null)
1407                                 accmods = Modifiers.INTERNAL;
1408                         else
1409                                 accmods = Modifiers.PRIVATE;
1410                         
1411                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1412
1413                         this.mod_flags |= Modifiers.SEALED;
1414                         this.attributes = attrs;
1415                         
1416                 }
1417
1418                 //
1419                 // FIXME: Allow the user to specify a different set of attributes
1420                 // in some cases (Sealed for example is mandatory for a class,
1421                 // but what SequentialLayout can be changed
1422                 //
1423                 public override TypeAttributes TypeAttr {
1424                         get {
1425                                 return base.TypeAttr |
1426                                         TypeAttributes.SequentialLayout |
1427                                         TypeAttributes.Sealed |
1428                                         TypeAttributes.BeforeFieldInit;
1429                         }
1430                 }
1431         }
1432
1433         public class MethodCore {
1434                 public readonly Parameters Parameters;
1435                 public readonly string Name;
1436                 public int ModFlags;
1437                 Block block;
1438                 public readonly Location Location;
1439                 
1440                 //
1441                 // Parameters, cached for semantic analysis.
1442                 //
1443                 InternalParameters parameter_info;
1444                 
1445                 public MethodCore (string name, Parameters parameters, Location l)
1446                 {
1447                         Name = name;
1448                         Parameters = parameters;
1449                         Location = l;
1450                 }
1451                 
1452                 //
1453                 //  Returns the System.Type array for the parameters of this method
1454                 //
1455                 Type [] parameter_types;
1456                 public Type [] ParameterTypes (TypeContainer parent)
1457                 {
1458                         if (Parameters == null)
1459                                 return null;
1460                         
1461                         if (parameter_types == null)
1462                                 parameter_types = Parameters.GetParameterInfo (parent);
1463
1464                         return parameter_types;
1465                 }
1466
1467                 public InternalParameters ParameterInfo
1468                 {
1469                         get {
1470                                 return parameter_info;
1471                         }
1472
1473                         set {
1474                                 parameter_info = value;
1475                         }
1476                 }
1477                 
1478                 public Block Block {
1479                         get {
1480                                 return block;
1481                         }
1482
1483                         set {
1484                                 block = value;
1485                         }
1486                 }
1487
1488                 public CallingConventions GetCallingConvention (bool is_class)
1489                 {
1490                         CallingConventions cc = 0;
1491                         
1492                         cc = Parameters.GetCallingConvention ();
1493
1494                         if (is_class)
1495                                 if ((ModFlags & Modifiers.STATIC) == 0)
1496                                         cc |= CallingConventions.HasThis;
1497
1498                         // FIXME: How is `ExplicitThis' used in C#?
1499                         
1500                         return cc;
1501                 }
1502         }
1503         
1504         public class Method : MethodCore {
1505                 public readonly string ReturnType;
1506                 public MethodBuilder MethodBuilder;
1507                 public readonly Attributes OptAttributes;
1508
1509                 // <summary>
1510                 //   Modifiers allowed in a class declaration
1511                 // </summary>
1512                 const int AllowedModifiers =
1513                         Modifiers.NEW |
1514                         Modifiers.PUBLIC |
1515                         Modifiers.PROTECTED |
1516                         Modifiers.INTERNAL |
1517                         Modifiers.PRIVATE |
1518                         Modifiers.STATIC |
1519                         Modifiers.VIRTUAL |
1520                         Modifiers.SEALED |
1521                         Modifiers.OVERRIDE |
1522                         Modifiers.ABSTRACT |
1523                         Modifiers.EXTERN;
1524                 
1525                 // return_type can be "null" for VOID values.
1526                 public Method (string return_type, int mod, string name, Parameters parameters,
1527                                Attributes attrs, Location l)
1528                         : base (name, parameters, l)
1529                 {
1530                         ReturnType = return_type;
1531                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1532                         OptAttributes = attrs;
1533                 }
1534
1535                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1536                 {
1537                         MethodInfo mi;
1538                         
1539                         if (! (m is MethodInfo))
1540                                 return false;
1541
1542                         MethodSignature sig = (MethodSignature) filter_criteria;
1543                         
1544                         if (m.Name != sig.Name)
1545                                 return false;
1546                         
1547                         mi = (MethodInfo) m;
1548
1549                         if (mi.ReturnType != sig.RetType)
1550                                 return false;
1551
1552                         Type [] args = TypeManager.GetArgumentTypes (mi);
1553                         Type [] sigp = sig.Parameters;
1554
1555                         //
1556                         // FIXME: remove this assumption if we manage to
1557                         // not enter a null as a the Parameters in TypeManager's 
1558                         // MethodBase to Type argument mapper.
1559                         //
1560                         if (args == null){
1561                                 if (sigp != null)
1562                                         return false;
1563                                 else
1564                                         return true;
1565                         } else if (sigp == null)
1566                                 return false;
1567                         
1568                         if (args.Length != sigp.Length)
1569                                 return false;
1570
1571                         for (int i = args.Length; i > 0; ){
1572                                 i--;
1573                                 if (args [i] != sigp [i])
1574                                         return false;
1575                         }
1576                         return true;
1577                 }
1578                 
1579                 // <summary>
1580                 //    This delegate is used to extract methods which have the
1581                 //    same signature as the argument
1582                 // </summary>
1583                 static MemberFilter method_signature_filter;
1584                 
1585                 static Method ()
1586                 {
1587                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
1588                 }
1589                 
1590                 //
1591                 // Returns the `System.Type' for the ReturnType of this
1592                 // function.  Provides a nice cache.  (used between semantic analysis
1593                 // and actual code generation
1594                 //
1595                 Type type_return_type;
1596                 public Type GetReturnType (TypeContainer parent)
1597                 {
1598                         if (type_return_type == null)
1599                                 type_return_type = parent.LookupType (ReturnType, false);
1600                         
1601                         return type_return_type;
1602                 }
1603
1604                 void WarningNotHiding (TypeContainer parent)
1605                 {
1606                         Report.Warning (
1607                                 109, Location,
1608                                 "The member `" + parent.Name + "." + Name + "' does not hide an " +
1609                                 "inherited member.  The keyword new is not required");
1610                                                            
1611                 }
1612
1613                 string MakeName (TypeContainer parent)
1614                 {
1615                         return "`" + parent.Name + "." + Name + "'";
1616                 }
1617
1618                 string MethodBaseName (MethodBase mb)
1619                 {
1620                         return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
1621                 }
1622                 
1623                 bool CheckMethod (TypeContainer parent, MemberInfo [] mi)
1624                 {
1625                         MethodInfo mb = (MethodInfo) mi [0];
1626
1627                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1628                                 Report.Warning (
1629                                         108, Location, "The keyword new is required on " + 
1630                                         MakeName (parent) + " because it hides `" +
1631                                         mb.ReflectedType.Name + "." +
1632                                         mb.Name + "'");
1633                         }
1634
1635                         if (mb.IsVirtual || mb.IsAbstract){
1636                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1637                                         Report.Warning (
1638                                                 114, Location, MakeName (parent) + 
1639                                                 "hides inherited member " + MethodBaseName (mb) +
1640                                                 ".  To make the current member override that " +
1641                                                 "implementation, add the override keyword, " +
1642                                                 "otherwise use the new keyword");
1643                                 }
1644                                 
1645                         }
1646
1647                         return true;
1648                 }
1649                 
1650                 //
1651                 // Creates the type
1652                 // 
1653                 public MethodBuilder Define (TypeContainer parent)
1654                 {
1655                         Type ret_type = GetReturnType (parent);
1656                         Type [] parameters = ParameterTypes (parent);
1657                         MethodAttributes flags;
1658                         bool error = false;
1659                         
1660                         //
1661                         // Verify if the parent has a type with the same name, and then
1662                         // check whether we have to create a new slot for it or not.
1663                         //
1664                         Type ptype = parent.TypeBuilder.BaseType;
1665
1666                         // ptype is only null for System.Object while compiling corlib.
1667                         if (ptype != null){
1668                                 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1669                                 MemberInfo [] mi;
1670                                 
1671                                 mi = TypeContainer.FindMembers (
1672                                         ptype, MemberTypes.Method,
1673                                         BindingFlags.Public, method_signature_filter,
1674                                         ms);
1675
1676                                 if (mi != null && mi.Length > 0){
1677                                         CheckMethod (parent, mi);
1678                                 } else {
1679                                         if ((ModFlags & Modifiers.NEW) != 0)
1680                                                 WarningNotHiding (parent);
1681                                         
1682                                         if ((ModFlags & Modifiers.OVERRIDE) != 0)
1683                                                 Report.Error (115, Location,
1684                                                               MakeName (parent) +
1685                                                               " no suitable methods found to override");
1686                                 }
1687                         } else if ((ModFlags & Modifiers.NEW) != 0)
1688                                 WarningNotHiding (parent);
1689
1690                         //
1691                         // If we implement an interface, then set the proper flags.
1692                         //
1693                         flags = Modifiers.MethodAttr (ModFlags);
1694
1695                         if (parent.IsInterfaceMethod (Name, ret_type, parameters))
1696                                 flags |= MethodAttributes.Virtual | MethodAttributes.Final |
1697                                          MethodAttributes.NewSlot | MethodAttributes.HideBySig;
1698
1699                         //
1700                         // Catch invalid uses of virtual and abtract modifiers
1701                         //
1702                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1703                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1704                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1705
1706                         if ((ModFlags & va) == va){
1707                                 if ((ModFlags & va) == va){
1708                                         Report.Error (
1709                                                 503, Location, "The abstract method " +
1710                                                 MakeName (parent) + "can not be marked virtual");
1711                                         error = true;
1712                                 }
1713                         }
1714
1715                         if ((ModFlags & Modifiers.ABSTRACT) != 0){
1716                                 if ((parent.ModFlags & Modifiers.ABSTRACT) == 0){
1717                                         Report.Error (
1718                                                 513, Location, MakeName (parent) +
1719                                                 " is abstract but its container class is not");
1720                                         error = true;
1721                                 }
1722                         }
1723
1724                         if ((ModFlags & va) != 0 && ((ModFlags & Modifiers.PRIVATE) != 0)){
1725                                 Report.Error (
1726                                         621, Location, MakeName (parent) +
1727                                         " virtual or abstract members can not be private");
1728                                 error = true;
1729                         }
1730
1731                         if ((ModFlags & Modifiers.STATIC) != 0){
1732                                 if ((ModFlags & vao) != 0){
1733                                         Report.Error (
1734                                                 112, Location, "static method " + MakeName (parent) +
1735                                                 " can not be marked as virtual, abstract or override");
1736
1737                                         error = true;
1738                                 }
1739                         }
1740                         
1741                         if ((ModFlags & Modifiers.OVERRIDE) != 0 && ((ModFlags & nv) != 0)){
1742                                 Report.Error (
1743                                         113, Location, MakeName (parent) +
1744                                         "marked as override cannot be marked as new or virtual");
1745                                 error = true;
1746                         }
1747
1748                         if (error)
1749                                 return null;
1750
1751                         //
1752                         // Finally, define the method
1753                         //
1754                         
1755                         MethodBuilder = parent.TypeBuilder.DefineMethod (
1756                                 Name, flags,
1757                                 GetCallingConvention (parent is Class),
1758                                 ret_type, parameters);
1759
1760                         //
1761                         // HACK because System.Reflection.Emit is lame
1762                         //
1763                         TypeManager.RegisterMethod (MethodBuilder, parameters);
1764                         
1765                         ParameterInfo = new InternalParameters (parameters);
1766
1767                         //
1768                         // This is used to track the Entry Point,
1769                         //
1770                         // FIXME: Allow pluggable entry point, check arguments, etc.
1771                         //
1772                         if (Name == "Main"){
1773                                 if ((ModFlags & Modifiers.STATIC) != 0){
1774                                         parent.RootContext.EntryPoint = MethodBuilder;
1775                                 }
1776                         }
1777                         
1778                         //
1779                         // Define each type attribute (in/out/ref) and
1780                         // the argument names.
1781                         //
1782                         Parameter [] p = Parameters.FixedParameters;
1783                         if (p != null){
1784                                 int i;
1785                                 
1786                                 for (i = 0; i < p.Length; i++)
1787                                         MethodBuilder.DefineParameter (
1788                                                 i + 1, p [i].Attributes, p [i].Name);
1789
1790                                 if (i != parameters.Length)
1791                                         Console.WriteLine ("Implement the type definition for params");
1792                         }
1793
1794                         return MethodBuilder;
1795                 }
1796
1797                 //
1798                 // Emits the code
1799                 // 
1800                 public void Emit (TypeContainer parent)
1801                 {
1802                         ILGenerator ig = MethodBuilder.GetILGenerator ();
1803                         EmitContext ec = new EmitContext (parent, ig, GetReturnType (parent), ModFlags);
1804                         
1805                         ec.EmitTopBlock (Block);
1806                 }
1807         }
1808
1809         public abstract class ConstructorInitializer {
1810                 ArrayList argument_list;
1811                 ConstructorInfo parent_constructor;
1812                 Location location;
1813                 
1814                 public ConstructorInitializer (ArrayList argument_list, Location location)
1815                 {
1816                         this.argument_list = argument_list;
1817                         this.location = location;
1818                 }
1819
1820                 public ArrayList Arguments {
1821                         get {
1822                                 return argument_list;
1823                         }
1824                 }
1825
1826                 public bool Resolve (EmitContext ec)
1827                 {
1828                         Expression parent_constructor_group;
1829                         
1830                         if (argument_list != null){
1831                                 for (int i = argument_list.Count; i > 0; ){
1832                                         --i;
1833
1834                                         Argument a = (Argument) argument_list [i];
1835                                         if (!a.Resolve (ec))
1836                                                 return false;
1837                                 }
1838                         }
1839
1840                         parent_constructor_group = Expression.MemberLookup (
1841                                 ec,
1842                                 ec.TypeContainer.TypeBuilder.BaseType, ".ctor", false,
1843                                 MemberTypes.Constructor,
1844                                 BindingFlags.Public | BindingFlags.Instance, location);
1845                         
1846                         //Console.WriteLine ("Base type : " + ec.TypeContainer.TypeBuilder.BaseType);
1847                         if (parent_constructor_group == null){
1848                                 Console.WriteLine ("Could not find a constructor in our parent");
1849                                 return false;
1850                         }
1851                         
1852                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
1853                                 (MethodGroupExpr) parent_constructor_group, argument_list, location);
1854                         
1855                         if (parent_constructor == null)
1856                                 return false;
1857                         
1858                         return true;
1859                 }
1860
1861                 public void Emit (EmitContext ec)
1862                 {
1863                         ec.ig.Emit (OpCodes.Ldarg_0);
1864                         if (argument_list != null)
1865                                 Invocation.EmitArguments (ec, parent_constructor, argument_list);
1866                         ec.ig.Emit (OpCodes.Call, parent_constructor);
1867                 }
1868         }
1869
1870         public class ConstructorBaseInitializer : ConstructorInitializer {
1871                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1872                 {
1873                 }
1874         }
1875
1876         public class ConstructorThisInitializer : ConstructorInitializer {
1877                 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1878                 {
1879                 }
1880         }
1881         
1882         public class Constructor : MethodCore {
1883                 public ConstructorBuilder ConstructorBuilder;
1884                 public ConstructorInitializer Initializer;
1885
1886                 // <summary>
1887                 //   Modifiers allowed for a constructor.
1888                 // </summary>
1889                 const int AllowedModifiers =
1890                         Modifiers.PUBLIC |
1891                         Modifiers.PROTECTED |
1892                         Modifiers.INTERNAL |
1893                         Modifiers.STATIC |
1894                         Modifiers.PRIVATE;
1895
1896                 //
1897                 // The spec claims that static is not permitted, but
1898                 // my very own code has static constructors.
1899                 //
1900                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
1901                         : base (name, args, l)
1902                 {
1903                         Initializer = init;
1904                 }
1905
1906                 //
1907                 // Returns true if this is a default constructor
1908                 //
1909                 public bool IsDefault ()
1910                 {
1911                         return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
1912                                 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
1913                                 (Initializer is ConstructorBaseInitializer) &&
1914                                 (Initializer.Arguments == null);
1915                 }
1916
1917                 //
1918                 // Creates the ConstructorBuilder
1919                 //
1920                 public ConstructorBuilder Define (TypeContainer parent)
1921                 {
1922                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
1923                                                MethodAttributes.SpecialName);
1924
1925                         Type [] parameters = ParameterTypes (parent);
1926
1927                         if ((ModFlags & Modifiers.STATIC) != 0)
1928                                 ca |= MethodAttributes.Static;
1929                         else {
1930                                 if (parent is Struct && parameters == null){
1931                                         Report.Error (
1932                                                 568, Location, 
1933                                                 "Structs can not contain explicit parameterless " +
1934                                                 "constructors");
1935                                         return null;
1936                                 }
1937                         }
1938
1939                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
1940                                 ca, GetCallingConvention (parent is Class),
1941                                 parameters);
1942                         //
1943                         // HACK because System.Reflection.Emit is lame
1944                         //
1945                         TypeManager.RegisterMethod (ConstructorBuilder, parameters);
1946
1947                         ParameterInfo = new InternalParameters (parameters);
1948
1949                         return ConstructorBuilder;
1950                 }
1951
1952                 //
1953                 // Emits the code
1954                 //
1955                 public void Emit (TypeContainer parent)
1956                 {
1957                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
1958                         EmitContext ec = new EmitContext (parent, ig, null, ModFlags, true);
1959
1960                         if (parent is Class){
1961                                 if (Initializer == null)
1962                                         Initializer = new ConstructorBaseInitializer (null, parent.Location);
1963
1964                                 if (!Initializer.Resolve (ec))
1965                                         return;
1966                         }
1967
1968                         //
1969                         // Classes can have base initializers and instance field initializers.
1970                         //
1971                         if (parent is Class){
1972                                 if ((ModFlags & Modifiers.STATIC) == 0)
1973                                         Initializer.Emit (ec);
1974                                 parent.EmitFieldInitializers (ec, false);
1975                         }
1976                         
1977                         if ((ModFlags & Modifiers.STATIC) != 0)
1978                                 parent.EmitFieldInitializers (ec, true);
1979
1980                         ec.EmitTopBlock (Block);
1981                 }
1982         }
1983         
1984         public class Field {
1985                 public readonly string Type;
1986                 public readonly Object Initializer;
1987                 public readonly string Name;
1988                 public readonly int    ModFlags;
1989                 public readonly Attributes OptAttributes;
1990                 public FieldBuilder  FieldBuilder;
1991                 
1992                 
1993                 // <summary>
1994                 //   Modifiers allowed in a class declaration
1995                 // </summary>
1996                 const int AllowedModifiers =
1997                         Modifiers.NEW |
1998                         Modifiers.PUBLIC |
1999                         Modifiers.PROTECTED |
2000                         Modifiers.INTERNAL |
2001                         Modifiers.PRIVATE |
2002                         Modifiers.STATIC |
2003                         Modifiers.READONLY;
2004
2005                 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
2006                 {
2007                         Type = type;
2008                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
2009                         Name = name;
2010                         Initializer = expr_or_array_init;
2011                         OptAttributes = attrs;
2012                 }
2013
2014                 public void Define (TypeContainer parent)
2015                 {
2016                         Type t = parent.LookupType (Type, false);
2017
2018                         if (t == null)
2019                                 return;
2020                         
2021                         FieldBuilder = parent.TypeBuilder.DefineField (
2022                                 Name, t, Modifiers.FieldAttr (ModFlags));
2023                 }
2024         }
2025
2026         public class Property {
2027                 
2028                 public readonly string Type;
2029                 public readonly string Name;
2030                 public readonly int    ModFlags;
2031                 public Block           Get, Set;
2032                 public PropertyBuilder PropertyBuilder;
2033                 public Attributes OptAttributes;
2034                 MethodBuilder GetBuilder, SetBuilder;
2035
2036                 //
2037                 // The type, once we compute it.
2038                 
2039                 Type PropertyType;
2040
2041                 const int AllowedModifiers =
2042                         Modifiers.NEW |
2043                         Modifiers.PUBLIC |
2044                         Modifiers.PROTECTED |
2045                         Modifiers.INTERNAL |
2046                         Modifiers.PRIVATE |
2047                         Modifiers.STATIC |
2048                         Modifiers.SEALED |
2049                         Modifiers.OVERRIDE |
2050                         Modifiers.ABSTRACT |
2051                         Modifiers.VIRTUAL;
2052                 
2053                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
2054                 {
2055                         Type = type;
2056                         Name = name;
2057                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2058                         Get = get_block;
2059                         Set = set_block;
2060                         OptAttributes = attrs;
2061                 }
2062
2063                 public void Define (TypeContainer parent)
2064                 {
2065
2066                         MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
2067                                         
2068                         // FIXME - PropertyAttributes.HasDefault ?
2069
2070                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2071                                                        PropertyAttributes.SpecialName;
2072                 
2073                 
2074                         PropertyType = parent.LookupType (Type, false);
2075                         Type [] parameters = new Type [1];
2076                         parameters [0] = PropertyType;
2077
2078                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2079                                 Name, prop_attr, PropertyType, null);
2080
2081                         if (Get != null)
2082                         {
2083                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2084                                         "get_" + Name, method_attr, PropertyType, null);
2085                                 PropertyBuilder.SetGetMethod (GetBuilder);
2086                                 //
2087                                 // HACK because System.Reflection.Emit is lame
2088                                 //
2089                                 TypeManager.RegisterMethod (GetBuilder, null);
2090                         }
2091                         
2092                         if (Set != null)
2093                         {
2094                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2095                                         "set_" + Name, method_attr, null, parameters);
2096                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
2097                                 PropertyBuilder.SetSetMethod (SetBuilder);
2098                                 //
2099                                 // HACK because System.Reflection.Emit is lame
2100                                 //
2101                                 TypeManager.RegisterMethod (SetBuilder, parameters);
2102                         }
2103
2104                         //
2105                         // HACK for the reasons exposed above
2106                         //
2107                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2108                 }
2109
2110                 public void Emit (TypeContainer tc)
2111                 {
2112                         ILGenerator ig;
2113                         EmitContext ec;
2114
2115                         if (Get != null){
2116                                 ig = GetBuilder.GetILGenerator ();
2117                                 ec = new EmitContext (tc, ig, PropertyType, ModFlags);
2118                                 
2119                                 ec.EmitTopBlock (Get);
2120                         }
2121
2122                         if (Set != null){
2123                                 ig = SetBuilder.GetILGenerator ();
2124                                 ec = new EmitContext (tc, ig, null, ModFlags);
2125                                 
2126                                 ec.EmitTopBlock (Set);
2127                         }
2128                 }
2129         }
2130
2131         public class Event {
2132                 
2133                 const int AllowedModifiers =
2134                         Modifiers.NEW |
2135                         Modifiers.PUBLIC |
2136                         Modifiers.PROTECTED |
2137                         Modifiers.INTERNAL |
2138                         Modifiers.PRIVATE |
2139                         Modifiers.STATIC |
2140                         Modifiers.VIRTUAL |
2141                         Modifiers.SEALED |
2142                         Modifiers.OVERRIDE |
2143                         Modifiers.ABSTRACT;
2144
2145                 public readonly string    Type;
2146                 public readonly string    Name;
2147                 public readonly Object    Initializer;
2148                 public readonly int       ModFlags;
2149                 public readonly Block     Add;
2150                 public readonly Block     Remove;
2151                 public EventBuilder       EventBuilder;
2152                 public Attributes         OptAttributes;
2153                 
2154                 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
2155                               Attributes attrs)
2156                 {
2157                         Type = type;
2158                         Name = name;
2159                         Initializer = init;
2160                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
2161                         Add = add_block;
2162                         Remove = rem_block;
2163                         OptAttributes = attrs;
2164                 }
2165
2166                 public void Define (TypeContainer parent)
2167                 {
2168                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
2169
2170                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
2171                         
2172                         MethodBuilder mb;
2173
2174                         Type t = parent.LookupType (Type, false);
2175                         Type [] parameters = new Type [1];
2176                         parameters [0] = t;
2177                         
2178                         EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
2179                         
2180                         if (Add != null) {
2181                                 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null,
2182                                                                       parameters);
2183                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2184                                 EventBuilder.SetAddOnMethod (mb);
2185                                 //
2186                                 // HACK because System.Reflection.Emit is lame
2187                                 //
2188                                 TypeManager.RegisterMethod (mb, parameters);
2189                         }
2190
2191                         if (Remove != null) {
2192                                 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null,
2193                                                                       parameters);
2194                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2195                                 EventBuilder.SetRemoveOnMethod (mb);
2196
2197                                 //
2198                                 // HACK because System.Reflection.Emit is lame
2199                                 //
2200                                 TypeManager.RegisterMethod (mb, parameters);
2201                         }
2202                 }
2203                 
2204         }
2205
2206         //
2207         // FIXME: This does not handle:
2208         //
2209         //   int INTERFACENAME [ args ]
2210         //
2211         // Only:
2212         // 
2213         // int this [ args ]
2214  
2215         public class Indexer {
2216
2217                 const int AllowedModifiers =
2218                         Modifiers.NEW |
2219                         Modifiers.PUBLIC |
2220                         Modifiers.PROTECTED |
2221                         Modifiers.INTERNAL |
2222                         Modifiers.PRIVATE |
2223                         Modifiers.VIRTUAL |
2224                         Modifiers.SEALED |
2225                         Modifiers.OVERRIDE |
2226                         Modifiers.ABSTRACT;
2227
2228                 public readonly string     Type;
2229                 public readonly string     InterfaceType;
2230                 public readonly Parameters FormalParameters;
2231                 public readonly int        ModFlags;
2232                 public readonly Block      Get;
2233                 public readonly Block      Set;
2234                 public Attributes          OptAttributes;
2235                 public MethodBuilder       GetBuilder;
2236                 public MethodBuilder       SetBuilder;
2237                 public PropertyBuilder PropertyBuilder;
2238                 public Type IndexerType;
2239                         
2240                 public Indexer (string type, string int_type, int flags, Parameters parms,
2241                                 Block get_block, Block set_block, Attributes attrs)
2242                 {
2243
2244                         Type = type;
2245                         InterfaceType = int_type;
2246                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
2247                         FormalParameters = parms;
2248                         Get = get_block;
2249                         Set = set_block;
2250                         OptAttributes = attrs;
2251                 }
2252
2253                 public void Define (TypeContainer parent)
2254                 {
2255                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
2256                         PropertyAttributes prop_attr =
2257                                 PropertyAttributes.RTSpecialName |
2258                                 PropertyAttributes.SpecialName;
2259                         
2260                         Type IndexerType = parent.LookupType (Type, false);
2261                         Type [] parameters = FormalParameters.GetParameterInfo (parent);
2262
2263                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2264                                 TypeManager.IndexerPropertyName (parent.TypeBuilder),
2265                                 prop_attr, IndexerType, parameters);
2266                                 
2267                         if (Get != null){
2268                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2269                                         "get_Item", attr, IndexerType, parameters);
2270                                 TypeManager.RegisterMethod (GetBuilder, parameters);
2271                                 TypeContainer.RegisterParameterForBuilder (
2272                                         GetBuilder, new InternalParameters (parameters));
2273                         }
2274                         
2275                         if (Set != null){
2276                                 int top = parameters.Length;
2277                                 Type [] set_pars = new Type [top + 1];
2278                                 parameters.CopyTo (set_pars, 0);
2279                                 set_pars [top] = IndexerType;
2280                                 
2281                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2282                                         "set_Item", attr, null, set_pars);
2283                                 TypeManager.RegisterMethod (SetBuilder, set_pars);
2284                                 TypeContainer.RegisterParameterForBuilder (
2285                                         SetBuilder, new InternalParameters (set_pars));
2286                         }
2287
2288                         PropertyBuilder.SetGetMethod (GetBuilder);
2289                         PropertyBuilder.SetSetMethod (SetBuilder);
2290                         
2291                         Parameter [] p = FormalParameters.FixedParameters;
2292
2293                         if (p != null) {
2294                                 int i;
2295                                 
2296                                 for (i = 0; i < p.Length; ++i) {
2297                                         if (Get != null)
2298                                                 GetBuilder.DefineParameter (
2299                                                         i + 1, p [i].Attributes, p [i].Name);
2300
2301                                         if (Set != null)
2302                                                 SetBuilder.DefineParameter (
2303                                                         i + 1, p [i].Attributes, p [i].Name);
2304                                 }
2305
2306                                 if (Set != null)
2307                                         SetBuilder.DefineParameter (
2308                                                 i + 1, ParameterAttributes.None, "value");
2309                                         
2310                                 if (i != parameters.Length)
2311                                         Console.WriteLine ("Implement type definition for params");
2312                         }
2313
2314                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2315                 }
2316
2317                 public void Emit (TypeContainer tc)
2318                 {
2319                         ILGenerator ig;
2320                         EmitContext ec;
2321
2322                         if (Get != null){
2323                                 ig = GetBuilder.GetILGenerator ();
2324                                 ec = new EmitContext (tc, ig, IndexerType, ModFlags);
2325                                 
2326                                 ec.EmitTopBlock (Get);
2327                         }
2328
2329                         if (Set != null){
2330                                 ig = SetBuilder.GetILGenerator ();
2331                                 ec = new EmitContext (tc, ig, null, ModFlags);
2332                                 
2333                                 ec.EmitTopBlock (Set);
2334                         }
2335                 }
2336         }
2337
2338         public class Operator {
2339
2340                 const int AllowedModifiers =
2341                         Modifiers.PUBLIC |
2342                         Modifiers.STATIC;
2343
2344                 const int RequiredModifiers =
2345                         Modifiers.PUBLIC |
2346                         Modifiers.STATIC;
2347
2348                 public enum OpType {
2349
2350                         // Unary operators
2351                         LogicalNot,
2352                         OnesComplement,
2353                         Increment,
2354                         Decrement,
2355                         True,
2356                         False,
2357
2358                         // Unary and Binary operators
2359                         Addition,
2360                         Subtraction,
2361
2362                         UnaryPlus,
2363                         UnaryNegation,
2364                         
2365                         // Binary operators
2366                         Multiply,
2367                         Division,
2368                         Modulus,
2369                         BitwiseAnd,
2370                         BitwiseOr,
2371                         ExclusiveOr,
2372                         LeftShift,
2373                         RightShift,
2374                         Equality,
2375                         Inequality,
2376                         GreaterThan,
2377                         LessThan,
2378                         GreaterThanOrEqual,
2379                         LessThanOrEqual,
2380
2381                         // Implicit and Explicit
2382                         Implicit,
2383                         Explicit
2384                 };
2385
2386                 public readonly OpType OperatorType;
2387                 public readonly string ReturnType;
2388                 public readonly string FirstArgType;
2389                 public readonly string FirstArgName;
2390                 public readonly string SecondArgType;
2391                 public readonly string SecondArgName;
2392                 public readonly int    ModFlags;
2393                 public readonly Block  Block;
2394                 public Attributes      OptAttributes;
2395                 public MethodBuilder   OperatorMethodBuilder;
2396                 public Location        Location;
2397                 
2398                 public string MethodName;
2399                 public Method OperatorMethod;
2400
2401                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
2402                                  string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
2403                 {
2404                         OperatorType = type;
2405                         ReturnType = ret_type;
2406                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
2407                         FirstArgType = arg1type;
2408                         FirstArgName = arg1name;
2409                         SecondArgType = arg2type;
2410                         SecondArgName = arg2name;
2411                         Block = block;
2412                         OptAttributes = attrs;
2413                         Location = loc;
2414                 }
2415
2416                 string Prototype (TypeContainer parent)
2417                 {
2418                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
2419                                 SecondArgType + ")";
2420                 }
2421                 
2422                 public void Define (TypeContainer parent)
2423                 {
2424                         int length = 1;
2425                         MethodName = "op_" + OperatorType;
2426                         
2427                         if (SecondArgType != null)
2428                                 length = 2;
2429                         
2430                         Parameter [] param_list = new Parameter [length];
2431
2432                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2433                                 Report.Error (
2434                                         558, Location, 
2435                                         "User defined operators `" +
2436                                         Prototype (parent) +
2437                                         "' must be declared static and public");
2438                         }
2439
2440                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
2441                                                        Parameter.Modifier.NONE, null);
2442                         if (SecondArgType != null)
2443                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
2444                                                                Parameter.Modifier.NONE, null);
2445                         
2446                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
2447                                                      new Parameters (param_list, null),
2448                                                      OptAttributes, Location.Null);
2449                         
2450                         OperatorMethod.Define (parent);
2451                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
2452
2453                         Type [] param_types = OperatorMethod.ParameterTypes (parent);
2454                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
2455                         Type return_type = OperatorMethod.GetReturnType (parent);
2456                         Type first_arg_type = param_types [0];
2457
2458                         // Rules for conversion operators
2459                         
2460                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2461                                 
2462                                 if (first_arg_type == return_type && first_arg_type == declaring_type)
2463                                         Report.Error (555, Location,
2464                                                "User-defined conversion cannot take an object of the enclosing type " +
2465                                                "and convert to an object of the enclosing type");
2466                                 
2467                                 if (first_arg_type != declaring_type && return_type != declaring_type)
2468                                         Report.Error (556, Location, 
2469                                                "User-defined conversion must convert to or from the enclosing type");
2470                                 
2471                                 if (first_arg_type == TypeManager.object_type || return_type == TypeManager.object_type)
2472                                         Report.Error (-8, Location,
2473                                                "User-defined conversion cannot convert to or from object type");
2474                                 
2475                                 if (first_arg_type.IsInterface || return_type.IsInterface)
2476                                         Report.Error (-9, Location,
2477                                                "User-defined conversion cannot convert to or from an interface type");   
2478                                 
2479                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type))
2480                                         Report.Error (-10, Location,
2481                                                 "User-defined conversion cannot convert between types that " +
2482                                                 "derive from each other"); 
2483                                 
2484                         } else if (SecondArgType == null) {
2485                                 // Checks for Unary operators
2486                                 
2487                                 if (first_arg_type != declaring_type) 
2488                                         Report.Error (562, Location,
2489                                                    "The parameter of a unary operator must be the containing type");
2490                                 
2491                                 
2492                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2493                                         if (return_type != declaring_type)
2494                                                 Report.Error (559, Location,
2495                                                        "The parameter and return type for ++ and -- " +
2496                                                        "must be the containing type");
2497                                         
2498                                 }
2499                                 
2500                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2501                                         if (return_type != TypeManager.bool_type)
2502                                                 Report.Error (215, Location,
2503                                                        "The return type of operator True or False " +
2504                                                        "must be bool");
2505                                 }
2506                                 
2507                         } else {
2508                                 // Checks for Binary operators
2509                                 
2510                                 if (first_arg_type != declaring_type &&
2511                                     param_types [1] != declaring_type)
2512                                         Report.Error (563, Location,
2513                                                "One of the parameters of a binary operator must be the containing type");
2514                         }
2515                         
2516                 
2517                         
2518                 }
2519                 
2520                 public void Emit (TypeContainer parent)
2521                 {
2522                         OperatorMethod.Block = Block;
2523                         OperatorMethod.Emit (parent);
2524                 }
2525                 
2526
2527         }
2528
2529         //
2530         // This is used to compare method signatures
2531         //
2532         struct MethodSignature {
2533                 public string Name;
2534                 public Type RetType;
2535                 public Type [] Parameters;
2536                 
2537                 public MethodSignature (string name, Type ret_type, Type [] parameters)
2538                 {
2539                         Name = name;
2540                         RetType = ret_type;
2541                         Parameters = parameters;
2542
2543                         if (parameters != null){
2544                                 if (parameters.Length == 0)
2545                                         Parameters = null;
2546                         } 
2547                 }
2548                 
2549                 public override int GetHashCode ()
2550                 {
2551                         return Name.GetHashCode ();
2552                 }
2553
2554                 public override bool Equals (Object o)
2555                 {
2556                         MethodSignature other = (MethodSignature) o;
2557
2558                         if (other.Name != Name)
2559                                 return false;
2560
2561                         if (other.RetType != RetType)
2562                                 return false;
2563                         
2564                         if (Parameters == null){
2565                                 if (other.Parameters == null)
2566                                         return true;
2567                                 return false;
2568                         }
2569
2570                         if (other.Parameters == null)
2571                                 return false;
2572                         
2573                         int c = Parameters.Length;
2574                         if (other.Parameters.Length != c)
2575                                 return false;
2576
2577                         for (int i = 0; i < c; i++)
2578                                 if (other.Parameters [i] != Parameters [i])
2579                                         return false;
2580
2581                         return true;
2582                 }
2583         }               
2584 }