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