2001-10-31 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 (indexers != null)
1319                                 foreach (Indexer ix in indexers)
1320                                         ix.Emit (this);
1321                         
1322                         if (pending_implementations != null)
1323                                 VerifyPendingMethods ();
1324
1325                         if (types != null)
1326                                 foreach (TypeContainer tc in types)
1327                                         tc.Emit ();
1328
1329                 }
1330
1331                 public void CloseType ()
1332                 {
1333                         try {
1334                                 TypeBuilder.CreateType ();
1335                         } catch (InvalidOperationException e){
1336                                 Console.WriteLine ("Exception while creating class: " + TypeBuilder.Name);
1337                                 Console.WriteLine ("Message:" + e.Message);
1338                         }
1339                         
1340                         foreach (TypeContainer tc in Types)
1341                                 tc.CloseType ();
1342
1343                         if (Delegates != null)
1344                                 foreach (Delegate d in Delegates)
1345                                         d.CloseDelegate ();
1346                 }
1347
1348                 string MakeName (string n)
1349                 {
1350                         return "`" + Name + "." + n + "'";
1351                 }
1352                 
1353                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1354                 {
1355                         return 0;
1356                 }
1357         }
1358
1359         public class Class : TypeContainer {
1360                 // <summary>
1361                 //   Modifiers allowed in a class declaration
1362                 // </summary>
1363                 public const int AllowedModifiers =
1364                         Modifiers.NEW |
1365                         Modifiers.PUBLIC |
1366                         Modifiers.PROTECTED |
1367                         Modifiers.INTERNAL |
1368                         Modifiers.PRIVATE |
1369                         Modifiers.ABSTRACT |
1370                         Modifiers.SEALED;
1371
1372                 public Class (RootContext rc, TypeContainer parent, string name, int mod,
1373                               Attributes attrs, Location l)
1374                         : base (rc, parent, name, l)
1375                 {
1376                         int accmods;
1377
1378                         if (parent.Parent == null)
1379                                 accmods = Modifiers.INTERNAL;
1380                         else
1381                                 accmods = Modifiers.PRIVATE;
1382                         
1383                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1384                         this.attributes = attrs;
1385                 }
1386
1387                 //
1388                 // FIXME: How do we deal with the user specifying a different
1389                 // layout?
1390                 //
1391                 public override TypeAttributes TypeAttr {
1392                         get {
1393                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1394                         }
1395                 }
1396         }
1397
1398         public class Struct : TypeContainer {
1399                 // <summary>
1400                 //   Modifiers allowed in a struct declaration
1401                 // </summary>
1402                 public const int AllowedModifiers =
1403                         Modifiers.NEW |
1404                         Modifiers.PUBLIC |
1405                         Modifiers.PROTECTED |
1406                         Modifiers.INTERNAL |
1407                         Modifiers.PRIVATE;
1408
1409                 public Struct (RootContext rc, TypeContainer parent, string name, int mod,
1410                                Attributes attrs, Location l)
1411                         : base (rc, parent, name, l)
1412                 {
1413                         int accmods;
1414                         
1415                         if (parent.Parent == null)
1416                                 accmods = Modifiers.INTERNAL;
1417                         else
1418                                 accmods = Modifiers.PRIVATE;
1419                         
1420                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
1421
1422                         this.mod_flags |= Modifiers.SEALED;
1423                         this.attributes = attrs;
1424                         
1425                 }
1426
1427                 //
1428                 // FIXME: Allow the user to specify a different set of attributes
1429                 // in some cases (Sealed for example is mandatory for a class,
1430                 // but what SequentialLayout can be changed
1431                 //
1432                 public override TypeAttributes TypeAttr {
1433                         get {
1434                                 return base.TypeAttr |
1435                                         TypeAttributes.SequentialLayout |
1436                                         TypeAttributes.Sealed |
1437                                         TypeAttributes.BeforeFieldInit;
1438                         }
1439                 }
1440         }
1441
1442         public class MethodCore {
1443                 public readonly Parameters Parameters;
1444                 public readonly string Name;
1445                 public int ModFlags;
1446                 Block block;
1447                 public readonly Location Location;
1448                 
1449                 //
1450                 // Parameters, cached for semantic analysis.
1451                 //
1452                 InternalParameters parameter_info;
1453                 
1454                 public MethodCore (string name, Parameters parameters, Location l)
1455                 {
1456                         Name = name;
1457                         Parameters = parameters;
1458                         Location = l;
1459                 }
1460                 
1461                 //
1462                 //  Returns the System.Type array for the parameters of this method
1463                 //
1464                 Type [] parameter_types;
1465                 public Type [] ParameterTypes (TypeContainer parent)
1466                 {
1467                         if (Parameters == null)
1468                                 return null;
1469                         
1470                         if (parameter_types == null)
1471                                 parameter_types = Parameters.GetParameterInfo (parent);
1472
1473                         return parameter_types;
1474                 }
1475
1476                 public InternalParameters ParameterInfo
1477                 {
1478                         get {
1479                                 return parameter_info;
1480                         }
1481
1482                         set {
1483                                 parameter_info = value;
1484                         }
1485                 }
1486                 
1487                 public Block Block {
1488                         get {
1489                                 return block;
1490                         }
1491
1492                         set {
1493                                 block = value;
1494                         }
1495                 }
1496
1497                 public CallingConventions GetCallingConvention (bool is_class)
1498                 {
1499                         CallingConventions cc = 0;
1500                         
1501                         cc = Parameters.GetCallingConvention ();
1502
1503                         if (is_class)
1504                                 if ((ModFlags & Modifiers.STATIC) == 0)
1505                                         cc |= CallingConventions.HasThis;
1506
1507                         // FIXME: How is `ExplicitThis' used in C#?
1508                         
1509                         return cc;
1510                 }
1511         }
1512         
1513         public class Method : MethodCore {
1514                 public readonly string ReturnType;
1515                 public MethodBuilder MethodBuilder;
1516                 public readonly Attributes OptAttributes;
1517
1518                 // <summary>
1519                 //   Modifiers allowed in a class declaration
1520                 // </summary>
1521                 const int AllowedModifiers =
1522                         Modifiers.NEW |
1523                         Modifiers.PUBLIC |
1524                         Modifiers.PROTECTED |
1525                         Modifiers.INTERNAL |
1526                         Modifiers.PRIVATE |
1527                         Modifiers.STATIC |
1528                         Modifiers.VIRTUAL |
1529                         Modifiers.SEALED |
1530                         Modifiers.OVERRIDE |
1531                         Modifiers.ABSTRACT |
1532                         Modifiers.EXTERN;
1533                 
1534                 // return_type can be "null" for VOID values.
1535                 public Method (string return_type, int mod, string name, Parameters parameters,
1536                                Attributes attrs, Location l)
1537                         : base (name, parameters, l)
1538                 {
1539                         ReturnType = return_type;
1540                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1541                         OptAttributes = attrs;
1542                 }
1543
1544                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
1545                 {
1546                         MethodInfo mi;
1547                         
1548                         if (! (m is MethodInfo))
1549                                 return false;
1550
1551                         MethodSignature sig = (MethodSignature) filter_criteria;
1552                         
1553                         if (m.Name != sig.Name)
1554                                 return false;
1555                         
1556                         mi = (MethodInfo) m;
1557
1558                         if (mi.ReturnType != sig.RetType)
1559                                 return false;
1560
1561                         Type [] args = TypeManager.GetArgumentTypes (mi);
1562                         Type [] sigp = sig.Parameters;
1563
1564                         //
1565                         // FIXME: remove this assumption if we manage to
1566                         // not enter a null as a the Parameters in TypeManager's 
1567                         // MethodBase to Type argument mapper.
1568                         //
1569                         if (args == null){
1570                                 if (sigp != null)
1571                                         return false;
1572                                 else
1573                                         return true;
1574                         } else if (sigp == null)
1575                                 return false;
1576                         
1577                         if (args.Length != sigp.Length)
1578                                 return false;
1579
1580                         for (int i = args.Length; i > 0; ){
1581                                 i--;
1582                                 if (args [i] != sigp [i])
1583                                         return false;
1584                         }
1585                         return true;
1586                 }
1587                 
1588                 // <summary>
1589                 //    This delegate is used to extract methods which have the
1590                 //    same signature as the argument
1591                 // </summary>
1592                 static MemberFilter method_signature_filter;
1593                 
1594                 static Method ()
1595                 {
1596                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
1597                 }
1598                 
1599                 //
1600                 // Returns the `System.Type' for the ReturnType of this
1601                 // function.  Provides a nice cache.  (used between semantic analysis
1602                 // and actual code generation
1603                 //
1604                 Type type_return_type;
1605                 public Type GetReturnType (TypeContainer parent)
1606                 {
1607                         if (type_return_type == null)
1608                                 type_return_type = parent.LookupType (ReturnType, false);
1609                         
1610                         return type_return_type;
1611                 }
1612
1613                 void WarningNotHiding (TypeContainer parent)
1614                 {
1615                         Report.Warning (
1616                                 109, Location,
1617                                 "The member `" + parent.Name + "." + Name + "' does not hide an " +
1618                                 "inherited member.  The keyword new is not required");
1619                                                            
1620                 }
1621
1622                 string MakeName (TypeContainer parent)
1623                 {
1624                         return "`" + parent.Name + "." + Name + "'";
1625                 }
1626
1627                 string MethodBaseName (MethodBase mb)
1628                 {
1629                         return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
1630                 }
1631                 
1632                 bool CheckMethod (TypeContainer parent, MemberInfo [] mi)
1633                 {
1634                         MethodInfo mb = (MethodInfo) mi [0];
1635
1636                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1637                                 Report.Warning (
1638                                         108, Location, "The keyword new is required on " + 
1639                                         MakeName (parent) + " because it hides `" +
1640                                         mb.ReflectedType.Name + "." +
1641                                         mb.Name + "'");
1642                         }
1643
1644                         if (mb.IsVirtual || mb.IsAbstract){
1645                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
1646                                         Report.Warning (
1647                                                 114, Location, MakeName (parent) + 
1648                                                 "hides inherited member " + MethodBaseName (mb) +
1649                                                 ".  To make the current member override that " +
1650                                                 "implementation, add the override keyword, " +
1651                                                 "otherwise use the new keyword");
1652                                 }
1653                                 
1654                         }
1655
1656                         return true;
1657                 }
1658                 
1659                 //
1660                 // Creates the type
1661                 // 
1662                 public MethodBuilder Define (TypeContainer parent)
1663                 {
1664                         Type ret_type = GetReturnType (parent);
1665                         Type [] parameters = ParameterTypes (parent);
1666                         MethodAttributes flags;
1667                         bool error = false;
1668                         
1669                         //
1670                         // Verify if the parent has a type with the same name, and then
1671                         // check whether we have to create a new slot for it or not.
1672                         //
1673                         Type ptype = parent.TypeBuilder.BaseType;
1674
1675                         // ptype is only null for System.Object while compiling corlib.
1676                         if (ptype != null){
1677                                 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
1678                                 MemberInfo [] mi;
1679                                 
1680                                 mi = TypeContainer.FindMembers (
1681                                         ptype, MemberTypes.Method,
1682                                         BindingFlags.Public, method_signature_filter,
1683                                         ms);
1684
1685                                 if (mi != null && mi.Length > 0){
1686                                         CheckMethod (parent, mi);
1687                                 } else {
1688                                         if ((ModFlags & Modifiers.NEW) != 0)
1689                                                 WarningNotHiding (parent);
1690                                         
1691                                         if ((ModFlags & Modifiers.OVERRIDE) != 0)
1692                                                 Report.Error (115, Location,
1693                                                               MakeName (parent) +
1694                                                               " no suitable methods found to override");
1695                                 }
1696                         } else if ((ModFlags & Modifiers.NEW) != 0)
1697                                 WarningNotHiding (parent);
1698
1699                         //
1700                         // If we implement an interface, then set the proper flags.
1701                         //
1702                         flags = Modifiers.MethodAttr (ModFlags);
1703
1704                         if (parent.IsInterfaceMethod (Name, ret_type, parameters))
1705                                 flags |= MethodAttributes.Virtual | MethodAttributes.Final |
1706                                          MethodAttributes.NewSlot | MethodAttributes.HideBySig;
1707
1708                         //
1709                         // Catch invalid uses of virtual and abtract modifiers
1710                         //
1711                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1712                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1713                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1714
1715                         if ((ModFlags & va) == va){
1716                                 if ((ModFlags & va) == va){
1717                                         Report.Error (
1718                                                 503, Location, "The abstract method " +
1719                                                 MakeName (parent) + "can not be marked virtual");
1720                                         error = true;
1721                                 }
1722                         }
1723
1724                         if ((ModFlags & Modifiers.ABSTRACT) != 0){
1725                                 if ((parent.ModFlags & Modifiers.ABSTRACT) == 0){
1726                                         Report.Error (
1727                                                 513, Location, MakeName (parent) +
1728                                                 " is abstract but its container class is not");
1729                                         error = true;
1730                                 }
1731                         }
1732
1733                         if ((ModFlags & va) != 0 && ((ModFlags & Modifiers.PRIVATE) != 0)){
1734                                 Report.Error (
1735                                         621, Location, MakeName (parent) +
1736                                         " virtual or abstract members can not be private");
1737                                 error = true;
1738                         }
1739
1740                         if ((ModFlags & Modifiers.STATIC) != 0){
1741                                 if ((ModFlags & vao) != 0){
1742                                         Report.Error (
1743                                                 112, Location, "static method " + MakeName (parent) +
1744                                                 " can not be marked as virtual, abstract or override");
1745
1746                                         error = true;
1747                                 }
1748                         }
1749                         
1750                         if ((ModFlags & Modifiers.OVERRIDE) != 0 && ((ModFlags & nv) != 0)){
1751                                 Report.Error (
1752                                         113, Location, MakeName (parent) +
1753                                         "marked as override cannot be marked as new or virtual");
1754                                 error = true;
1755                         }
1756
1757                         if (error)
1758                                 return null;
1759
1760                         //
1761                         // Finally, define the method
1762                         //
1763                         
1764                         MethodBuilder = parent.TypeBuilder.DefineMethod (
1765                                 Name, flags,
1766                                 GetCallingConvention (parent is Class),
1767                                 ret_type, parameters);
1768
1769                         //
1770                         // HACK because System.Reflection.Emit is lame
1771                         //
1772                         TypeManager.RegisterMethod (MethodBuilder, parameters);
1773                         
1774                         ParameterInfo = new InternalParameters (parent, Parameters);
1775
1776                         //
1777                         // This is used to track the Entry Point,
1778                         //
1779                         // FIXME: Allow pluggable entry point, check arguments, etc.
1780                         //
1781                         if (Name == "Main"){
1782                                 if ((ModFlags & Modifiers.STATIC) != 0){
1783                                         parent.RootContext.EntryPoint = MethodBuilder;
1784                                 }
1785                         }
1786                         
1787                         //
1788                         // Define each type attribute (in/out/ref) and
1789                         // the argument names.
1790                         //
1791                         Parameter [] p = Parameters.FixedParameters;
1792                         if (p != null){
1793                                 int i;
1794                                 
1795                                 for (i = 0; i < p.Length; i++) 
1796                                         MethodBuilder.DefineParameter (
1797                                                       i + 1, p [i].Attributes, p [i].Name);
1798                                         
1799                                 if (i != parameters.Length)
1800                                         Console.WriteLine ("Implement the type definition for params");
1801                         }
1802
1803                         return MethodBuilder;
1804                 }
1805
1806                 //
1807                 // Emits the code
1808                 // 
1809                 public void Emit (TypeContainer parent)
1810                 {
1811                         ILGenerator ig = MethodBuilder.GetILGenerator ();
1812                         EmitContext ec = new EmitContext (parent, ig, GetReturnType (parent), ModFlags);
1813                         
1814                         ec.EmitTopBlock (Block);
1815                 }
1816         }
1817
1818         public abstract class ConstructorInitializer {
1819                 ArrayList argument_list;
1820                 ConstructorInfo parent_constructor;
1821                 Location location;
1822                 
1823                 public ConstructorInitializer (ArrayList argument_list, Location location)
1824                 {
1825                         this.argument_list = argument_list;
1826                         this.location = location;
1827                 }
1828
1829                 public ArrayList Arguments {
1830                         get {
1831                                 return argument_list;
1832                         }
1833                 }
1834
1835                 public bool Resolve (EmitContext ec)
1836                 {
1837                         Expression parent_constructor_group;
1838                         
1839                         if (argument_list != null){
1840                                 for (int i = argument_list.Count; i > 0; ){
1841                                         --i;
1842
1843                                         Argument a = (Argument) argument_list [i];
1844                                         if (!a.Resolve (ec))
1845                                                 return false;
1846                                 }
1847                         }
1848
1849                         parent_constructor_group = Expression.MemberLookup (
1850                                 ec,
1851                                 ec.TypeContainer.TypeBuilder.BaseType, ".ctor", false,
1852                                 MemberTypes.Constructor,
1853                                 BindingFlags.Public | BindingFlags.Instance, location);
1854                         
1855                         //Console.WriteLine ("Base type : " + ec.TypeContainer.TypeBuilder.BaseType);
1856                         if (parent_constructor_group == null){
1857                                 Console.WriteLine ("Could not find a constructor in our parent");
1858                                 return false;
1859                         }
1860                         
1861                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
1862                                 (MethodGroupExpr) parent_constructor_group, argument_list, location);
1863                         
1864                         if (parent_constructor == null)
1865                                 return false;
1866                         
1867                         return true;
1868                 }
1869
1870                 public void Emit (EmitContext ec)
1871                 {
1872                         ec.ig.Emit (OpCodes.Ldarg_0);
1873                         if (argument_list != null)
1874                                 Invocation.EmitArguments (ec, argument_list);
1875                         ec.ig.Emit (OpCodes.Call, parent_constructor);
1876                 }
1877         }
1878
1879         public class ConstructorBaseInitializer : ConstructorInitializer {
1880                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1881                 {
1882                 }
1883         }
1884
1885         public class ConstructorThisInitializer : ConstructorInitializer {
1886                 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
1887                 {
1888                 }
1889         }
1890         
1891         public class Constructor : MethodCore {
1892                 public ConstructorBuilder ConstructorBuilder;
1893                 public ConstructorInitializer Initializer;
1894
1895                 // <summary>
1896                 //   Modifiers allowed for a constructor.
1897                 // </summary>
1898                 const int AllowedModifiers =
1899                         Modifiers.PUBLIC |
1900                         Modifiers.PROTECTED |
1901                         Modifiers.INTERNAL |
1902                         Modifiers.STATIC |
1903                         Modifiers.PRIVATE;
1904
1905                 //
1906                 // The spec claims that static is not permitted, but
1907                 // my very own code has static constructors.
1908                 //
1909                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
1910                         : base (name, args, l)
1911                 {
1912                         Initializer = init;
1913                 }
1914
1915                 //
1916                 // Returns true if this is a default constructor
1917                 //
1918                 public bool IsDefault ()
1919                 {
1920                         return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
1921                                 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
1922                                 (Initializer is ConstructorBaseInitializer) &&
1923                                 (Initializer.Arguments == null);
1924                 }
1925
1926                 //
1927                 // Creates the ConstructorBuilder
1928                 //
1929                 public ConstructorBuilder Define (TypeContainer parent)
1930                 {
1931                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
1932                                                MethodAttributes.SpecialName);
1933
1934                         Type [] parameters = ParameterTypes (parent);
1935
1936                         if ((ModFlags & Modifiers.STATIC) != 0)
1937                                 ca |= MethodAttributes.Static;
1938                         else {
1939                                 if (parent is Struct && parameters == null){
1940                                         Report.Error (
1941                                                 568, Location, 
1942                                                 "Structs can not contain explicit parameterless " +
1943                                                 "constructors");
1944                                         return null;
1945                                 }
1946                         }
1947
1948                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
1949                                 ca, GetCallingConvention (parent is Class),
1950                                 parameters);
1951                         //
1952                         // HACK because System.Reflection.Emit is lame
1953                         //
1954                         TypeManager.RegisterMethod (ConstructorBuilder, parameters);
1955
1956                         ParameterInfo = new InternalParameters (parent, Parameters);
1957
1958                         return ConstructorBuilder;
1959                 }
1960
1961                 //
1962                 // Emits the code
1963                 //
1964                 public void Emit (TypeContainer parent)
1965                 {
1966                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
1967                         EmitContext ec = new EmitContext (parent, ig, null, ModFlags, true);
1968
1969                         if (parent is Class){
1970                                 if (Initializer == null)
1971                                         Initializer = new ConstructorBaseInitializer (null, parent.Location);
1972
1973                                 if (!Initializer.Resolve (ec))
1974                                         return;
1975                         }
1976
1977                         //
1978                         // Classes can have base initializers and instance field initializers.
1979                         //
1980                         if (parent is Class){
1981                                 if ((ModFlags & Modifiers.STATIC) == 0)
1982                                         Initializer.Emit (ec);
1983                                 parent.EmitFieldInitializers (ec, false);
1984                         }
1985                         
1986                         if ((ModFlags & Modifiers.STATIC) != 0)
1987                                 parent.EmitFieldInitializers (ec, true);
1988
1989                         ec.EmitTopBlock (Block);
1990                 }
1991         }
1992         
1993         public class Field {
1994                 public readonly string Type;
1995                 public readonly Object Initializer;
1996                 public readonly string Name;
1997                 public readonly int    ModFlags;
1998                 public readonly Attributes OptAttributes;
1999                 public FieldBuilder  FieldBuilder;
2000                 
2001                 
2002                 // <summary>
2003                 //   Modifiers allowed in a class declaration
2004                 // </summary>
2005                 const int AllowedModifiers =
2006                         Modifiers.NEW |
2007                         Modifiers.PUBLIC |
2008                         Modifiers.PROTECTED |
2009                         Modifiers.INTERNAL |
2010                         Modifiers.PRIVATE |
2011                         Modifiers.STATIC |
2012                         Modifiers.READONLY;
2013
2014                 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
2015                 {
2016                         Type = type;
2017                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
2018                         Name = name;
2019                         Initializer = expr_or_array_init;
2020                         OptAttributes = attrs;
2021                 }
2022
2023                 public void Define (TypeContainer parent)
2024                 {
2025                         Type t = parent.LookupType (Type, false);
2026
2027                         if (t == null)
2028                                 return;
2029                         
2030                         FieldBuilder = parent.TypeBuilder.DefineField (
2031                                 Name, t, Modifiers.FieldAttr (ModFlags));
2032                 }
2033         }
2034
2035         public class Property {
2036                 
2037                 public readonly string Type;
2038                 public readonly string Name;
2039                 public readonly int    ModFlags;
2040                 public Block           Get, Set;
2041                 public PropertyBuilder PropertyBuilder;
2042                 public Attributes OptAttributes;
2043                 MethodBuilder GetBuilder, SetBuilder;
2044
2045                 //
2046                 // The type, once we compute it.
2047                 
2048                 Type PropertyType;
2049
2050                 const int AllowedModifiers =
2051                         Modifiers.NEW |
2052                         Modifiers.PUBLIC |
2053                         Modifiers.PROTECTED |
2054                         Modifiers.INTERNAL |
2055                         Modifiers.PRIVATE |
2056                         Modifiers.STATIC |
2057                         Modifiers.SEALED |
2058                         Modifiers.OVERRIDE |
2059                         Modifiers.ABSTRACT |
2060                         Modifiers.VIRTUAL;
2061                 
2062                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
2063                 {
2064                         Type = type;
2065                         Name = name;
2066                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2067                         Get = get_block;
2068                         Set = set_block;
2069                         OptAttributes = attrs;
2070                 }
2071
2072                 public void Define (TypeContainer parent)
2073                 {
2074
2075                         MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
2076                                         
2077                         // FIXME - PropertyAttributes.HasDefault ?
2078
2079                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2080                                                        PropertyAttributes.SpecialName;
2081                 
2082                 
2083                         PropertyType = parent.LookupType (Type, false);
2084                         Type [] parameters = new Type [1];
2085                         parameters [0] = PropertyType;
2086
2087                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2088                                 Name, prop_attr, PropertyType, null);
2089
2090                         if (Get != null)
2091                         {
2092                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2093                                         "get_" + Name, method_attr, PropertyType, null);
2094                                 PropertyBuilder.SetGetMethod (GetBuilder);
2095                                 //
2096                                 // HACK because System.Reflection.Emit is lame
2097                                 //
2098                                 TypeManager.RegisterMethod (GetBuilder, null);
2099                         }
2100                         
2101                         if (Set != null)
2102                         {
2103                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2104                                         "set_" + Name, method_attr, null, parameters);
2105                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
2106                                 PropertyBuilder.SetSetMethod (SetBuilder);
2107                                 //
2108                                 // HACK because System.Reflection.Emit is lame
2109                                 //
2110                                 TypeManager.RegisterMethod (SetBuilder, parameters);
2111                         }
2112
2113                         //
2114                         // HACK for the reasons exposed above
2115                         //
2116                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2117                 }
2118
2119                 public void Emit (TypeContainer tc)
2120                 {
2121                         ILGenerator ig;
2122                         EmitContext ec;
2123
2124                         if (Get != null){
2125                                 ig = GetBuilder.GetILGenerator ();
2126                                 ec = new EmitContext (tc, ig, PropertyType, ModFlags);
2127                                 
2128                                 ec.EmitTopBlock (Get);
2129                         }
2130
2131                         if (Set != null){
2132                                 ig = SetBuilder.GetILGenerator ();
2133                                 ec = new EmitContext (tc, ig, null, ModFlags);
2134                                 
2135                                 ec.EmitTopBlock (Set);
2136                         }
2137                 }
2138         }
2139
2140         public class Event {
2141                 
2142                 const int AllowedModifiers =
2143                         Modifiers.NEW |
2144                         Modifiers.PUBLIC |
2145                         Modifiers.PROTECTED |
2146                         Modifiers.INTERNAL |
2147                         Modifiers.PRIVATE |
2148                         Modifiers.STATIC |
2149                         Modifiers.VIRTUAL |
2150                         Modifiers.SEALED |
2151                         Modifiers.OVERRIDE |
2152                         Modifiers.ABSTRACT;
2153
2154                 public readonly string    Type;
2155                 public readonly string    Name;
2156                 public readonly Object    Initializer;
2157                 public readonly int       ModFlags;
2158                 public readonly Block     Add;
2159                 public readonly Block     Remove;
2160                 public EventBuilder       EventBuilder;
2161                 public Attributes         OptAttributes;
2162                 
2163                 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
2164                               Attributes attrs)
2165                 {
2166                         Type = type;
2167                         Name = name;
2168                         Initializer = init;
2169                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
2170                         Add = add_block;
2171                         Remove = rem_block;
2172                         OptAttributes = attrs;
2173                 }
2174
2175                 public void Define (TypeContainer parent)
2176                 {
2177                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
2178
2179                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
2180                         
2181                         MethodBuilder mb;
2182
2183                         Type t = parent.LookupType (Type, false);
2184                         Type [] parameters = new Type [1];
2185                         parameters [0] = t;
2186                         
2187                         EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
2188                         
2189                         if (Add != null) {
2190                                 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null,
2191                                                                       parameters);
2192                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2193                                 EventBuilder.SetAddOnMethod (mb);
2194                                 //
2195                                 // HACK because System.Reflection.Emit is lame
2196                                 //
2197                                 TypeManager.RegisterMethod (mb, parameters);
2198                         }
2199
2200                         if (Remove != null) {
2201                                 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null,
2202                                                                       parameters);
2203                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2204                                 EventBuilder.SetRemoveOnMethod (mb);
2205
2206                                 //
2207                                 // HACK because System.Reflection.Emit is lame
2208                                 //
2209                                 TypeManager.RegisterMethod (mb, parameters);
2210                         }
2211                 }
2212                 
2213         }
2214
2215         //
2216         // FIXME: This does not handle:
2217         //
2218         //   int INTERFACENAME [ args ]
2219         //
2220         // Only:
2221         // 
2222         // int this [ args ]
2223  
2224         public class Indexer {
2225
2226                 const int AllowedModifiers =
2227                         Modifiers.NEW |
2228                         Modifiers.PUBLIC |
2229                         Modifiers.PROTECTED |
2230                         Modifiers.INTERNAL |
2231                         Modifiers.PRIVATE |
2232                         Modifiers.VIRTUAL |
2233                         Modifiers.SEALED |
2234                         Modifiers.OVERRIDE |
2235                         Modifiers.ABSTRACT;
2236
2237                 public readonly string     Type;
2238                 public readonly string     InterfaceType;
2239                 public readonly Parameters FormalParameters;
2240                 public readonly int        ModFlags;
2241                 public readonly Block      Get;
2242                 public readonly Block      Set;
2243                 public Attributes          OptAttributes;
2244                 public MethodBuilder       GetBuilder;
2245                 public MethodBuilder       SetBuilder;
2246                 public PropertyBuilder PropertyBuilder;
2247                 public Type IndexerType;
2248                         
2249                 public Indexer (string type, string int_type, int flags, Parameters parms,
2250                                 Block get_block, Block set_block, Attributes attrs)
2251                 {
2252
2253                         Type = type;
2254                         InterfaceType = int_type;
2255                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
2256                         FormalParameters = parms;
2257                         Get = get_block;
2258                         Set = set_block;
2259                         OptAttributes = attrs;
2260                 }
2261
2262                 public void Define (TypeContainer parent)
2263                 {
2264                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
2265                         PropertyAttributes prop_attr =
2266                                 PropertyAttributes.RTSpecialName |
2267                                 PropertyAttributes.SpecialName;
2268                         
2269                         IndexerType = parent.LookupType (Type, false);
2270                         Type [] parameters = FormalParameters.GetParameterInfo (parent);
2271
2272                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2273                                 TypeManager.IndexerPropertyName (parent.TypeBuilder),
2274                                 prop_attr, IndexerType, parameters);
2275                                 
2276                         if (Get != null){
2277                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2278                                         "get_Item", attr, IndexerType, parameters);
2279                                 TypeManager.RegisterMethod (GetBuilder, parameters);
2280                                 TypeContainer.RegisterParameterForBuilder (
2281                                         GetBuilder, new InternalParameters (parent, FormalParameters));
2282                         }
2283                         
2284                         if (Set != null){
2285                                 int top = parameters.Length;
2286                                 Type [] set_pars = new Type [top + 1];
2287                                 parameters.CopyTo (set_pars, 0);
2288                                 set_pars [top] = IndexerType;
2289
2290                                 Parameter [] fixed_parms = FormalParameters.FixedParameters;
2291
2292                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
2293
2294                                 fixed_parms.CopyTo (tmp, 0);
2295                                 tmp [fixed_parms.Length] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2296
2297                                 Parameters set_formal_params = new Parameters (tmp, null);
2298                                 
2299                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2300                                         "set_Item", attr, null, set_pars);
2301                                 TypeManager.RegisterMethod (SetBuilder, set_pars);
2302                                 TypeContainer.RegisterParameterForBuilder (
2303                                         SetBuilder, new InternalParameters (parent, set_formal_params));
2304                         }
2305
2306                         PropertyBuilder.SetGetMethod (GetBuilder);
2307                         PropertyBuilder.SetSetMethod (SetBuilder);
2308                         
2309                         Parameter [] p = FormalParameters.FixedParameters;
2310
2311                         if (p != null) {
2312                                 int i;
2313                                 
2314                                 for (i = 0; i < p.Length; ++i) {
2315                                         if (Get != null)
2316                                                 GetBuilder.DefineParameter (
2317                                                         i + 1, p [i].Attributes, p [i].Name);
2318
2319                                         if (Set != null)
2320                                                 SetBuilder.DefineParameter (
2321                                                         i + 1, p [i].Attributes, p [i].Name);
2322                                 }
2323
2324                                 if (Set != null)
2325                                         SetBuilder.DefineParameter (
2326                                                 i + 1, ParameterAttributes.None, "value");
2327                                         
2328                                 if (i != parameters.Length)
2329                                         Console.WriteLine ("Implement type definition for params");
2330                         }
2331
2332                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2333                 }
2334
2335                 public void Emit (TypeContainer tc)
2336                 {
2337                         ILGenerator ig;
2338                         EmitContext ec;
2339
2340                         if (Get != null){
2341                                 ig = GetBuilder.GetILGenerator ();
2342                                 ec = new EmitContext (tc, ig, IndexerType, ModFlags);
2343                                 
2344                                 ec.EmitTopBlock (Get);
2345                         }
2346
2347                         if (Set != null){
2348                                 ig = SetBuilder.GetILGenerator ();
2349                                 ec = new EmitContext (tc, ig, null, ModFlags);
2350                                 
2351                                 ec.EmitTopBlock (Set);
2352                         }
2353                 }
2354         }
2355
2356         public class Operator {
2357
2358                 const int AllowedModifiers =
2359                         Modifiers.PUBLIC |
2360                         Modifiers.STATIC;
2361
2362                 const int RequiredModifiers =
2363                         Modifiers.PUBLIC |
2364                         Modifiers.STATIC;
2365
2366                 public enum OpType {
2367
2368                         // Unary operators
2369                         LogicalNot,
2370                         OnesComplement,
2371                         Increment,
2372                         Decrement,
2373                         True,
2374                         False,
2375
2376                         // Unary and Binary operators
2377                         Addition,
2378                         Subtraction,
2379
2380                         UnaryPlus,
2381                         UnaryNegation,
2382                         
2383                         // Binary operators
2384                         Multiply,
2385                         Division,
2386                         Modulus,
2387                         BitwiseAnd,
2388                         BitwiseOr,
2389                         ExclusiveOr,
2390                         LeftShift,
2391                         RightShift,
2392                         Equality,
2393                         Inequality,
2394                         GreaterThan,
2395                         LessThan,
2396                         GreaterThanOrEqual,
2397                         LessThanOrEqual,
2398
2399                         // Implicit and Explicit
2400                         Implicit,
2401                         Explicit
2402                 };
2403
2404                 public readonly OpType OperatorType;
2405                 public readonly string ReturnType;
2406                 public readonly string FirstArgType;
2407                 public readonly string FirstArgName;
2408                 public readonly string SecondArgType;
2409                 public readonly string SecondArgName;
2410                 public readonly int    ModFlags;
2411                 public readonly Block  Block;
2412                 public Attributes      OptAttributes;
2413                 public MethodBuilder   OperatorMethodBuilder;
2414                 public Location        Location;
2415                 
2416                 public string MethodName;
2417                 public Method OperatorMethod;
2418
2419                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
2420                                  string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
2421                 {
2422                         OperatorType = type;
2423                         ReturnType = ret_type;
2424                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
2425                         FirstArgType = arg1type;
2426                         FirstArgName = arg1name;
2427                         SecondArgType = arg2type;
2428                         SecondArgName = arg2name;
2429                         Block = block;
2430                         OptAttributes = attrs;
2431                         Location = loc;
2432                 }
2433
2434                 string Prototype (TypeContainer parent)
2435                 {
2436                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
2437                                 SecondArgType + ")";
2438                 }
2439                 
2440                 public void Define (TypeContainer parent)
2441                 {
2442                         int length = 1;
2443                         MethodName = "op_" + OperatorType;
2444                         
2445                         if (SecondArgType != null)
2446                                 length = 2;
2447                         
2448                         Parameter [] param_list = new Parameter [length];
2449
2450                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2451                                 Report.Error (
2452                                         558, Location, 
2453                                         "User defined operators `" +
2454                                         Prototype (parent) +
2455                                         "' must be declared static and public");
2456                         }
2457
2458                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
2459                                                        Parameter.Modifier.NONE, null);
2460                         if (SecondArgType != null)
2461                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
2462                                                                Parameter.Modifier.NONE, null);
2463                         
2464                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
2465                                                      new Parameters (param_list, null),
2466                                                      OptAttributes, Location.Null);
2467                         
2468                         OperatorMethod.Define (parent);
2469                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
2470
2471                         Type [] param_types = OperatorMethod.ParameterTypes (parent);
2472                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
2473                         Type return_type = OperatorMethod.GetReturnType (parent);
2474                         Type first_arg_type = param_types [0];
2475
2476                         // Rules for conversion operators
2477                         
2478                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2479                                 
2480                                 if (first_arg_type == return_type && first_arg_type == declaring_type)
2481                                         Report.Error (555, Location,
2482                                                "User-defined conversion cannot take an object of the enclosing type " +
2483                                                "and convert to an object of the enclosing type");
2484                                 
2485                                 if (first_arg_type != declaring_type && return_type != declaring_type)
2486                                         Report.Error (556, Location, 
2487                                                "User-defined conversion must convert to or from the enclosing type");
2488                                 
2489                                 if (first_arg_type == TypeManager.object_type || return_type == TypeManager.object_type)
2490                                         Report.Error (-8, Location,
2491                                                "User-defined conversion cannot convert to or from object type");
2492                                 
2493                                 if (first_arg_type.IsInterface || return_type.IsInterface)
2494                                         Report.Error (-9, Location,
2495                                                "User-defined conversion cannot convert to or from an interface type");   
2496                                 
2497                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type))
2498                                         Report.Error (-10, Location,
2499                                                 "User-defined conversion cannot convert between types that " +
2500                                                 "derive from each other"); 
2501                                 
2502                         } else if (SecondArgType == null) {
2503                                 // Checks for Unary operators
2504                                 
2505                                 if (first_arg_type != declaring_type) 
2506                                         Report.Error (562, Location,
2507                                                    "The parameter of a unary operator must be the containing type");
2508                                 
2509                                 
2510                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2511                                         if (return_type != declaring_type)
2512                                                 Report.Error (559, Location,
2513                                                        "The parameter and return type for ++ and -- " +
2514                                                        "must be the containing type");
2515                                         
2516                                 }
2517                                 
2518                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2519                                         if (return_type != TypeManager.bool_type)
2520                                                 Report.Error (215, Location,
2521                                                        "The return type of operator True or False " +
2522                                                        "must be bool");
2523                                 }
2524                                 
2525                         } else {
2526                                 // Checks for Binary operators
2527                                 
2528                                 if (first_arg_type != declaring_type &&
2529                                     param_types [1] != declaring_type)
2530                                         Report.Error (563, Location,
2531                                                "One of the parameters of a binary operator must be the containing type");
2532                         }
2533                         
2534                 
2535                         
2536                 }
2537                 
2538                 public void Emit (TypeContainer parent)
2539                 {
2540                         OperatorMethod.Block = Block;
2541                         OperatorMethod.Emit (parent);
2542                 }
2543                 
2544
2545         }
2546
2547         //
2548         // This is used to compare method signatures
2549         //
2550         struct MethodSignature {
2551                 public string Name;
2552                 public Type RetType;
2553                 public Type [] Parameters;
2554                 
2555                 public MethodSignature (string name, Type ret_type, Type [] parameters)
2556                 {
2557                         Name = name;
2558                         RetType = ret_type;
2559                         Parameters = parameters;
2560
2561                         if (parameters != null){
2562                                 if (parameters.Length == 0)
2563                                         Parameters = null;
2564                         } 
2565                 }
2566                 
2567                 public override int GetHashCode ()
2568                 {
2569                         return Name.GetHashCode ();
2570                 }
2571
2572                 public override bool Equals (Object o)
2573                 {
2574                         MethodSignature other = (MethodSignature) o;
2575
2576                         if (other.Name != Name)
2577                                 return false;
2578
2579                         if (other.RetType != RetType)
2580                                 return false;
2581                         
2582                         if (Parameters == null){
2583                                 if (other.Parameters == null)
2584                                         return true;
2585                                 return false;
2586                         }
2587
2588                         if (other.Parameters == null)
2589                                 return false;
2590                         
2591                         int c = Parameters.Length;
2592                         if (other.Parameters.Length != c)
2593                                 return false;
2594
2595                         for (int i = 0; i < c; i++)
2596                                 if (other.Parameters [i] != Parameters [i])
2597                                         return false;
2598
2599                         return true;
2600                 }
2601         }               
2602 }