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