2001-11-08 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 (Delegates != null) {
1014                                 foreach (Delegate d in Delegates) 
1015                                         d.Populate (this);
1016                         }
1017                         
1018                         if (Types != null) {
1019                                 foreach (TypeContainer tc in Types)
1020                                         tc.Populate ();
1021                         }
1022
1023                 
1024                 }
1025
1026                 // <summary>
1027                 //   Since System.Reflection.Emit can not retrieve parameter information
1028                 //   from methods that are dynamically defined, we have to look those
1029                 //   up ourselves using this
1030                 // </summary>
1031                 static public ParameterData LookupParametersByBuilder (MethodBase mb)
1032                 {
1033                         return (ParameterData) method_builders_to_parameters [MakeKey (mb)];
1034                 }
1035
1036                 // <summary>
1037                 //   Indexers and properties can register more than one method at once,
1038                 //   so we need to provide a mechanism for those to register their
1039                 //   various methods to parameter info mappers.
1040                 // </summary>
1041                 static public void RegisterParameterForBuilder (MethodBase mb, InternalParameters pi)
1042                 {
1043                         method_builders_to_parameters.Add (MakeKey (mb), pi);
1044                 }
1045                 
1046                 public Type LookupType (string name, bool silent)
1047                 {
1048                         return RootContext.LookupType (this, name, silent);
1049                 }
1050
1051                 public string LookupAlias (string Name)
1052                 {
1053                         //
1054                         // Read the comments on `mcs/mcs/TODO' for details
1055                         // 
1056                         return null;
1057                 }
1058                 
1059                 //
1060                 // This function is based by a delegate to the FindMembers routine
1061                 //
1062                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1063                 {
1064                         return true;
1065                 }
1066                 
1067                 //
1068                 static bool IsAbstractMethod (MemberInfo m, object filter_criteria)
1069                 {
1070                         MethodInfo mi = (MethodInfo) m;
1071
1072                         return mi.IsAbstract;
1073                 }
1074
1075                 // This filter is used by FindMembers, and we just keep
1076                 // a global for the filter to `AlwaysAccept'
1077                 //
1078                 static MemberFilter accepting_filter;
1079                 
1080                 // <summary>
1081                 //    This delegate is a MemberFilter used to extract the 
1082                 //    abstact methods from a type.  
1083                 // </summary>
1084                 static MemberFilter abstract_method_filter;
1085
1086                 static TypeContainer ()
1087                 {
1088                         abstract_method_filter = new MemberFilter (IsAbstractMethod);
1089                         accepting_filter = new MemberFilter (AlwaysAccept);
1090                 }
1091                 
1092                 // <summary>
1093                 //   This method returns the members of this type just like Type.FindMembers would
1094                 //   Only, we need to use this for types which are _being_ defined because MS' 
1095                 //   implementation can't take care of that.
1096                 // </summary>
1097                 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1098                                                   MemberFilter filter, object criteria)
1099                 {
1100                         ArrayList members = new ArrayList ();
1101
1102                         if (filter == null)
1103                                 filter = accepting_filter; 
1104                         
1105                         if ((mt & MemberTypes.Field) != 0 && Fields != null) {
1106                                 foreach (Field f in Fields) {
1107                                         if (filter (f.FieldBuilder, criteria) == true)
1108                                                 members.Add (f.FieldBuilder);
1109                                 }
1110                         }
1111
1112                         if ((mt & MemberTypes.Method) != 0) {
1113                                 if (Methods != null){
1114                                         foreach (Method m in Methods) {
1115                                                 MethodBuilder mb = m.MethodBuilder;
1116
1117                                                 if (filter (mb, criteria) == true)
1118                                                         members.Add (mb);
1119                                         }
1120                                 }
1121
1122                                 if (Operators != null){
1123                                         foreach (Operator o in Operators) {
1124                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1125
1126                                                 if (filter (ob, criteria) == true)
1127                                                         members.Add (ob);
1128                                         }
1129                                 }
1130                         }
1131
1132                         // FIXME : This ain't right because EventBuilder is not a
1133                         // MemberInfo. What do we do ?
1134                         
1135                         if ((mt & MemberTypes.Event) != 0 && Events != null) {
1136                                 //foreach (Event e in Events) {
1137                                 //      if (filter (e.EventBuilder, criteria) == true)
1138                                 //              mi [i++] = e.EventBuilder;
1139                                 //}
1140                         }
1141
1142                         if ((mt & MemberTypes.Property) != 0){
1143                                 if (Properties != null)
1144                                         foreach (Property p in Properties) {
1145                                                 if (filter (p.PropertyBuilder, criteria) == true)
1146                                                         members.Add (p.PropertyBuilder);
1147                                         }
1148
1149                                 if (Indexers != null)
1150                                         foreach (Indexer ix in Indexers){
1151                                                 if (filter (ix.PropertyBuilder, criteria) == true)
1152                                                         members.Add (ix.PropertyBuilder);
1153                                         }
1154                         }
1155                         
1156                         if ((mt & MemberTypes.NestedType) != 0 && Types != null) {
1157                                 foreach (TypeContainer t in Types) { 
1158                                         if (filter (t.TypeBuilder, criteria) == true)
1159                                                 members.Add (t.TypeBuilder);
1160                                 }
1161                         }
1162
1163                         if ((mt & MemberTypes.Constructor) != 0){
1164                                 if (Constructors != null){
1165                                         foreach (Constructor c in Constructors){
1166                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1167
1168                                                 if (filter (cb, criteria) == true)
1169                                                         members.Add (cb);
1170                                         }
1171                                 }
1172                         }
1173
1174                         //
1175                         // Lookup members in parent if requested.
1176                         //
1177                         if ((bf & BindingFlags.DeclaredOnly) == 0){
1178                                 MemberInfo [] mi;
1179
1180                                 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1181                                 if (mi != null)
1182                                         members.AddRange (mi);
1183                         }
1184                         
1185                         int count = members.Count;
1186                         if (count > 0){
1187                                 MemberInfo [] mi = new MemberInfo [count];
1188                                 members.CopyTo (mi);
1189                                 return mi;
1190                         }
1191
1192                         return null;
1193                 }
1194
1195                 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1196                                                          MemberFilter filter, object criteria)
1197                 {
1198                         TypeContainer tc = TypeManager.LookupTypeContainer (t);
1199
1200                         if (tc != null)
1201                                 return tc.FindMembers (mt, bf, filter, criteria);
1202                         else
1203                                 return t.FindMembers (mt, bf, filter, criteria);
1204                 }
1205                 
1206
1207                 Hashtable pending_implementations;
1208                 
1209                 // <summary>
1210                 //   Requires that the methods in `mi' be implemented for this
1211                 //   class
1212                 // </summary>
1213                 public void RequireMethods (MethodInfo [] mi, object data)
1214                 {
1215                         if (pending_implementations == null)
1216                                 pending_implementations = new Hashtable ();
1217
1218                         foreach (MethodInfo m in mi){
1219                                 Type [] types = TypeManager.GetArgumentTypes (m);
1220
1221                                 pending_implementations.Add (
1222                                         new MethodSignature 
1223                                                 (m.Name, m.ReturnType, types), data);
1224                         }
1225                 }
1226
1227                 // <summary>
1228                 //   Used to set the list of interfaces that this typecontainer
1229                 //   must implement.
1230                 // </summary>
1231                 //
1232                 // <remarks>
1233                 //   For each element exposed by the type, we create a MethodSignature
1234                 //   struct that we will label as `implemented' as we define the various
1235                 //   methods.
1236                 // </remarks>
1237                 public void SetRequiredInterfaces (Type [] ifaces)
1238                 {
1239                         foreach (Type t in ifaces){
1240                                 MethodInfo [] mi;
1241
1242                                 if (t is TypeBuilder){
1243                                         Interface iface = RootContext.TypeManager.LookupInterface (t);
1244
1245                                         mi = iface.GetMethods ();
1246                                 } else
1247                                         mi = t.GetMethods ();
1248
1249                                 RequireMethods (mi, t);
1250                         }
1251                 }
1252
1253                 // <summary>
1254                 //   If a method with name `Name', return type `ret_type' and
1255                 //   arguments `args' implements an interface, this method will
1256                 //   return true.
1257                 //
1258                 //   This will remove the method from the list of "pending" methods
1259                 //   that are required to be implemented for this class as a side effect.
1260                 // 
1261                 // </summary>
1262                 public bool IsInterfaceMethod (string Name, Type ret_type, Type [] args)
1263                 {
1264                         MethodSignature query;
1265
1266                         if (pending_implementations == null)
1267                                 return false;
1268
1269                         query = new MethodSignature (Name, ret_type, args);
1270
1271                         if (pending_implementations.Contains (query)){
1272                                 pending_implementations.Remove (query);
1273                                 return true;
1274                         }
1275
1276                         return false;
1277                 }
1278
1279                 // <summary>
1280                 //   Verifies that any pending abstract methods or interface methods
1281                 //   were implemented.
1282                 // </summary>
1283                 void VerifyPendingMethods ()
1284                 {
1285                         int pending = 0;
1286                         
1287                         foreach (object m in pending_implementations){
1288                                 DictionaryEntry de = (DictionaryEntry) m;
1289                                 Type t = (Type) de.Value;
1290                                 pending++;
1291
1292                                 MethodSignature method = (MethodSignature) de.Key;
1293
1294                                 if (t.IsInterface)
1295                                         Report.Error (
1296                                                 536, Location,
1297                                                 "`" + Name + "' does not implement interface member `" +
1298                                                 t.FullName + "." + method.Name + "'");
1299                                 else
1300                                         Report.Error (
1301                                                 534, Location,
1302                                                 "`" + Name + "' does not implement inherited abstract " +
1303                                                 "member `" + t.FullName + "." + method.Name + "'");
1304                         }
1305                 }
1306                 
1307                 // <summary>
1308                 //   Emits the code, this step is performed after all
1309                 //   the types, enumerations, constructors
1310                 // </summary>
1311                 public void Emit ()
1312                 {
1313                         if (Constructors != null)
1314                                 foreach (Constructor c in Constructors)
1315                                         c.Emit (this);
1316                         
1317                         if (methods != null)
1318                                 foreach (Method m in methods)
1319                                         m.Emit (this);
1320
1321                         if (operators != null)
1322                                 foreach (Operator o in operators)
1323                                         o.Emit (this);
1324
1325                         if (properties != null)
1326                                 foreach (Property p in properties)
1327                                         p.Emit (this);
1328
1329                         if (indexers != null)
1330                                 foreach (Indexer ix in indexers)
1331                                         ix.Emit (this);
1332
1333                         if (fields != null)
1334                                 foreach (Field f in fields)
1335                                         f.Emit (this);
1336
1337                         if (events != null)
1338                                 foreach (Event e in Events)
1339                                         e.Emit (this);
1340
1341                         if (enums != null)
1342                                 foreach (Enum en in enums)
1343                                         en.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                                 if (OptAttributes.AttributeSections != null) {
2125                                         foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2126                                                 if (asec.Attributes != null) {
2127                                                         foreach (Attribute a in asec.Attributes) {
2128                                                                 CustomAttributeBuilder cb = a.Resolve (ec);
2129                                                                 if (cb != null)
2130                                                                         FieldBuilder.SetCustomAttribute (cb);
2131                                                         }
2132                                                 }
2133                                         }
2134                                 }
2135                         }
2136                 }
2137         }
2138
2139         public class Property {
2140                 
2141                 public readonly string Type;
2142                 public readonly string Name;
2143                 public readonly int    ModFlags;
2144                 public Block           Get, Set;
2145                 public PropertyBuilder PropertyBuilder;
2146                 public Attributes OptAttributes;
2147                 MethodBuilder GetBuilder, SetBuilder;
2148
2149                 Location Location;
2150
2151                 //
2152                 // The type, once we compute it.
2153                 
2154                 Type PropertyType;
2155
2156                 const int AllowedModifiers =
2157                         Modifiers.NEW |
2158                         Modifiers.PUBLIC |
2159                         Modifiers.PROTECTED |
2160                         Modifiers.INTERNAL |
2161                         Modifiers.PRIVATE |
2162                         Modifiers.STATIC |
2163                         Modifiers.SEALED |
2164                         Modifiers.OVERRIDE |
2165                         Modifiers.ABSTRACT |
2166                         Modifiers.VIRTUAL;
2167                 
2168                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2169                                  Attributes attrs, Location loc)
2170                 {
2171                         Type = type;
2172                         Name = name;
2173                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
2174                         Get = get_block;
2175                         Set = set_block;
2176                         OptAttributes = attrs;
2177                         Location = loc;
2178                 }
2179
2180                 public void Define (TypeContainer parent)
2181                 {
2182
2183                         MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
2184                                         
2185                         // FIXME - PropertyAttributes.HasDefault ?
2186
2187                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2188                                                        PropertyAttributes.SpecialName;
2189                 
2190                 
2191                         PropertyType = parent.LookupType (Type, false);
2192                         Type [] parameters = new Type [1];
2193                         parameters [0] = PropertyType;
2194
2195                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2196                                 Name, prop_attr, PropertyType, null);
2197
2198                         if (Get != null)
2199                         {
2200                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2201                                         "get_" + Name, method_attr, PropertyType, null);
2202                                 PropertyBuilder.SetGetMethod (GetBuilder);
2203                                 //
2204                                 // HACK because System.Reflection.Emit is lame
2205                                 //
2206                                 if (!TypeManager.RegisterMethod (GetBuilder, null)) {
2207                                         Report.Error (111, Location,
2208                                                "Class `" + parent.Name + "' already contains a definition with the " +
2209                                                "same return value and parameter types as the " +
2210                                                "'get' method of property `" + Name + "'");
2211                                         return;
2212                                 }
2213                                 
2214                                 
2215                         }
2216                         
2217                         if (Set != null)
2218                         {
2219                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2220                                         "set_" + Name, method_attr, null, parameters);
2221                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
2222                                 PropertyBuilder.SetSetMethod (SetBuilder);
2223                                 //
2224                                 // HACK because System.Reflection.Emit is lame
2225                                 //
2226                                 if (!TypeManager.RegisterMethod (SetBuilder, parameters)) {
2227                                         Report.Error (111, Location,
2228                                                "Class `" + parent.Name + "' already contains a definition with the " +
2229                                                "same return value and parameter types as the " +
2230                                                "'set' method of property `" + Name + "'");
2231                                         return;
2232                                 }
2233                                 
2234                                 //
2235                                 // HACK for the reasons exposed above
2236                                 //
2237                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2238                                         Report.Error (111, Location,
2239                                                "Class `" + parent.Name + "' already contains a definition for the " +
2240                                                " property `" + Name + "'");
2241                                         return;
2242                                 }
2243                                         
2244                         }
2245
2246                 }
2247                 
2248                 public void Emit (TypeContainer tc)
2249                 {
2250                         ILGenerator ig;
2251                         EmitContext ec;
2252
2253                         if (OptAttributes != null) {
2254                                 ec = new EmitContext (tc, null, PropertyType, ModFlags);
2255                                 if (OptAttributes.AttributeSections != null) {
2256                                         foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2257                                                 if (asec.Attributes != null) {
2258                                                         foreach (Attribute a in asec.Attributes) {
2259                                                                 CustomAttributeBuilder cb = a.Resolve (ec);
2260                                                                 if (cb != null)
2261                                                                         PropertyBuilder.SetCustomAttribute (cb);
2262                                                         }
2263                                                 }
2264                                         }
2265                                 }
2266                         }
2267                         
2268                         if (Get != null){
2269                                 ig = GetBuilder.GetILGenerator ();
2270                                 ec = new EmitContext (tc, ig, PropertyType, ModFlags);
2271                                 
2272                                 ec.EmitTopBlock (Get);
2273                         }
2274
2275                         if (Set != null){
2276                                 ig = SetBuilder.GetILGenerator ();
2277                                 ec = new EmitContext (tc, ig, null, ModFlags);
2278                                 
2279                                 ec.EmitTopBlock (Set);
2280                         }
2281                 }
2282         }
2283
2284         public class Event {
2285                 
2286                 const int AllowedModifiers =
2287                         Modifiers.NEW |
2288                         Modifiers.PUBLIC |
2289                         Modifiers.PROTECTED |
2290                         Modifiers.INTERNAL |
2291                         Modifiers.PRIVATE |
2292                         Modifiers.STATIC |
2293                         Modifiers.VIRTUAL |
2294                         Modifiers.SEALED |
2295                         Modifiers.OVERRIDE |
2296                         Modifiers.ABSTRACT;
2297
2298                 public readonly string    Type;
2299                 public readonly string    Name;
2300                 public readonly Object    Initializer;
2301                 public readonly int       ModFlags;
2302                 public readonly Block     Add;
2303                 public readonly Block     Remove;
2304                 public EventBuilder       EventBuilder;
2305                 public Attributes         OptAttributes;
2306
2307                 Type EventType;
2308
2309                 Location Location;
2310                 
2311                 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
2312                               Attributes attrs, Location loc)
2313                 {
2314                         Type = type;
2315                         Name = name;
2316                         Initializer = init;
2317                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
2318                         Add = add_block;
2319                         Remove = rem_block;
2320                         OptAttributes = attrs;
2321                         Location = loc;
2322                 }
2323
2324                 public void Define (TypeContainer parent)
2325                 {
2326                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
2327
2328                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
2329                         
2330                         MethodBuilder mb;
2331
2332                         EventType = parent.LookupType (Type, false);
2333                         Type [] parameters = new Type [1];
2334                         parameters [0] = EventType;
2335                         
2336                         EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, EventType);
2337                         
2338                         if (Add != null) {
2339                                 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null,
2340                                                                       parameters);
2341                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2342                                 EventBuilder.SetAddOnMethod (mb);
2343                                 //
2344                                 // HACK because System.Reflection.Emit is lame
2345                                 //
2346                                 if (!TypeManager.RegisterMethod (mb, parameters)) {
2347                                         Report.Error (111, Location,
2348                                                "Class `" + parent.Name + "' already contains a definition with the " +
2349                                                "same return value and parameter types for the " +
2350                                                "'add' method of event `" + Name + "'");
2351                                         return;
2352                                 }
2353                         }
2354
2355                         if (Remove != null) {
2356                                 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null,
2357                                                                       parameters);
2358                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
2359                                 EventBuilder.SetRemoveOnMethod (mb);
2360
2361                                 //
2362                                 // HACK because System.Reflection.Emit is lame
2363                                 //
2364                                 if (!TypeManager.RegisterMethod (mb, parameters)) {
2365                                         Report.Error (111, Location,    
2366                                        "Class `" + parent.Name + "' already contains a definition with the " +
2367                                                "same return value and parameter types for the " +
2368                                                "'remove' method of event `" + Name + "'");
2369                                         return;
2370                                 }
2371                         }
2372
2373                 
2374                 }
2375
2376                 public void Emit (TypeContainer tc)
2377                 {
2378                         EmitContext ec = new EmitContext (tc, null, EventType, ModFlags);
2379
2380                         if (OptAttributes != null) {
2381                                 if (OptAttributes.AttributeSections != null) {
2382                                         foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2383                                                 if (asec.Attributes != null) {
2384                                                         foreach (Attribute a in asec.Attributes) {
2385                                                                 CustomAttributeBuilder cb = a.Resolve (ec);
2386                                                                 if (cb != null)
2387                                                                         EventBuilder.SetCustomAttribute (cb);
2388                                                         }
2389                                                 }
2390                                         }
2391                                 }
2392                         }
2393                 }
2394                 
2395         }
2396
2397         //
2398         // FIXME: This does not handle:
2399         //
2400         //   int INTERFACENAME [ args ]
2401         //
2402         // Only:
2403         // 
2404         // int this [ args ]
2405  
2406         public class Indexer {
2407
2408                 const int AllowedModifiers =
2409                         Modifiers.NEW |
2410                         Modifiers.PUBLIC |
2411                         Modifiers.PROTECTED |
2412                         Modifiers.INTERNAL |
2413                         Modifiers.PRIVATE |
2414                         Modifiers.VIRTUAL |
2415                         Modifiers.SEALED |
2416                         Modifiers.OVERRIDE |
2417                         Modifiers.ABSTRACT;
2418
2419                 public readonly string     Type;
2420                 public readonly string     InterfaceType;
2421                 public readonly Parameters FormalParameters;
2422                 public readonly int        ModFlags;
2423                 public readonly Block      Get;
2424                 public readonly Block      Set;
2425                 public Attributes          OptAttributes;
2426                 public MethodBuilder       GetBuilder;
2427                 public MethodBuilder       SetBuilder;
2428                 public PropertyBuilder PropertyBuilder;
2429                 public Type IndexerType;
2430
2431                 Location Location;
2432                         
2433                 public Indexer (string type, string int_type, int flags, Parameters parms,
2434                                 Block get_block, Block set_block, Attributes attrs, Location loc)
2435                 {
2436
2437                         Type = type;
2438                         InterfaceType = int_type;
2439                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
2440                         FormalParameters = parms;
2441                         Get = get_block;
2442                         Set = set_block;
2443                         OptAttributes = attrs;
2444                         Location = loc;
2445                 }
2446
2447                 public void Define (TypeContainer parent)
2448                 {
2449                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
2450                         PropertyAttributes prop_attr =
2451                                 PropertyAttributes.RTSpecialName |
2452                                 PropertyAttributes.SpecialName;
2453                         
2454                         IndexerType = parent.LookupType (Type, false);
2455                         Type [] parameters = FormalParameters.GetParameterInfo (parent);
2456
2457                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
2458                                 TypeManager.IndexerPropertyName (parent.TypeBuilder),
2459                                 prop_attr, IndexerType, parameters);
2460                                 
2461                         if (Get != null){
2462                                 GetBuilder = parent.TypeBuilder.DefineMethod (
2463                                         "get_Item", attr, IndexerType, parameters);
2464
2465                                 if (!TypeManager.RegisterMethod (GetBuilder, parameters)) {
2466                                         Report.Error (111, Location,
2467                                                "Class `" + parent.Name + "' already contains a definition with the " +
2468                                                "same return value and parameter types for the " +
2469                                                "'get' indexer");
2470                                         return;
2471                                 }
2472                                         
2473                                 TypeContainer.RegisterParameterForBuilder (
2474                                               GetBuilder, new InternalParameters (parent, FormalParameters));
2475                         }
2476                         
2477                         if (Set != null){
2478                                 int top = parameters.Length;
2479                                 Type [] set_pars = new Type [top + 1];
2480                                 parameters.CopyTo (set_pars, 0);
2481                                 set_pars [top] = IndexerType;
2482
2483                                 Parameter [] fixed_parms = FormalParameters.FixedParameters;
2484
2485                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
2486
2487                                 fixed_parms.CopyTo (tmp, 0);
2488                                 tmp [fixed_parms.Length] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2489
2490                                 Parameters set_formal_params = new Parameters (tmp, null);
2491                                 
2492                                 SetBuilder = parent.TypeBuilder.DefineMethod (
2493                                         "set_Item", attr, null, set_pars);
2494
2495                                 if (!TypeManager.RegisterMethod (SetBuilder, set_pars)) {
2496                                         Report.Error (111, Location,
2497                                                "Class `" + parent.Name + "' already contains a definition with the " +
2498                                                "same return value and parameter types for the " +
2499                                                "'set' indexer");
2500                                         return;
2501                                 }
2502
2503                                 TypeContainer.RegisterParameterForBuilder (
2504                                         SetBuilder, new InternalParameters (parent, set_formal_params));
2505                         }
2506
2507                         PropertyBuilder.SetGetMethod (GetBuilder);
2508                         PropertyBuilder.SetSetMethod (SetBuilder);
2509                         
2510                         Parameter [] p = FormalParameters.FixedParameters;
2511
2512                         if (p != null) {
2513                                 int i;
2514                                 
2515                                 for (i = 0; i < p.Length; ++i) {
2516                                         if (Get != null)
2517                                                 GetBuilder.DefineParameter (
2518                                                         i + 1, p [i].Attributes, p [i].Name);
2519
2520                                         if (Set != null)
2521                                                 SetBuilder.DefineParameter (
2522                                                         i + 1, p [i].Attributes, p [i].Name);
2523                                 }
2524
2525                                 if (Set != null)
2526                                         SetBuilder.DefineParameter (
2527                                                 i + 1, ParameterAttributes.None, "value");
2528                                         
2529                                 if (i != parameters.Length) {
2530                                         Parameter array_param = FormalParameters.ArrayParameter;
2531                                         SetBuilder.DefineParameter (i + 1, array_param.Attributes,
2532                                                                     array_param.Name);
2533                                 }
2534                         }
2535
2536                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
2537                 }
2538
2539                 public void Emit (TypeContainer tc)
2540                 {
2541                         ILGenerator ig;
2542                         EmitContext ec;
2543
2544                         if (OptAttributes != null) {
2545                                 ec = new EmitContext (tc, null, IndexerType, ModFlags);
2546                                 if (OptAttributes.AttributeSections != null) {
2547                                         foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2548                                                 if (asec.Attributes != null) {
2549                                                         foreach (Attribute a in asec.Attributes) {
2550                                                                 CustomAttributeBuilder cb = a.Resolve (ec);
2551                                                                 if (cb != null)
2552                                                                         PropertyBuilder.SetCustomAttribute (cb);
2553                                                         }
2554                                                 }
2555                                         }
2556                                 }
2557                         }
2558
2559                         if (Get != null){
2560                                 ig = GetBuilder.GetILGenerator ();
2561                                 ec = new EmitContext (tc, ig, IndexerType, ModFlags);
2562                                 
2563                                 ec.EmitTopBlock (Get);
2564                         }
2565
2566                         if (Set != null){
2567                                 ig = SetBuilder.GetILGenerator ();
2568                                 ec = new EmitContext (tc, ig, null, ModFlags);
2569                                 
2570                                 ec.EmitTopBlock (Set);
2571                         }
2572                 }
2573         }
2574
2575         public class Operator {
2576
2577                 const int AllowedModifiers =
2578                         Modifiers.PUBLIC |
2579                         Modifiers.STATIC;
2580
2581                 const int RequiredModifiers =
2582                         Modifiers.PUBLIC |
2583                         Modifiers.STATIC;
2584
2585                 public enum OpType {
2586
2587                         // Unary operators
2588                         LogicalNot,
2589                         OnesComplement,
2590                         Increment,
2591                         Decrement,
2592                         True,
2593                         False,
2594
2595                         // Unary and Binary operators
2596                         Addition,
2597                         Subtraction,
2598
2599                         UnaryPlus,
2600                         UnaryNegation,
2601                         
2602                         // Binary operators
2603                         Multiply,
2604                         Division,
2605                         Modulus,
2606                         BitwiseAnd,
2607                         BitwiseOr,
2608                         ExclusiveOr,
2609                         LeftShift,
2610                         RightShift,
2611                         Equality,
2612                         Inequality,
2613                         GreaterThan,
2614                         LessThan,
2615                         GreaterThanOrEqual,
2616                         LessThanOrEqual,
2617
2618                         // Implicit and Explicit
2619                         Implicit,
2620                         Explicit
2621                 };
2622
2623                 public readonly OpType OperatorType;
2624                 public readonly string ReturnType;
2625                 public readonly string FirstArgType;
2626                 public readonly string FirstArgName;
2627                 public readonly string SecondArgType;
2628                 public readonly string SecondArgName;
2629                 public readonly int    ModFlags;
2630                 public readonly Block  Block;
2631                 public Attributes      OptAttributes;
2632                 public MethodBuilder   OperatorMethodBuilder;
2633                 public Location        Location;
2634                 
2635                 public string MethodName;
2636                 public Method OperatorMethod;
2637
2638                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
2639                                  string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
2640                 {
2641                         OperatorType = type;
2642                         ReturnType = ret_type;
2643                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
2644                         FirstArgType = arg1type;
2645                         FirstArgName = arg1name;
2646                         SecondArgType = arg2type;
2647                         SecondArgName = arg2name;
2648                         Block = block;
2649                         OptAttributes = attrs;
2650                         Location = loc;
2651                 }
2652
2653                 string Prototype (TypeContainer parent)
2654                 {
2655                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
2656                                 SecondArgType + ")";
2657                 }
2658                 
2659                 public void Define (TypeContainer parent)
2660                 {
2661                         int length = 1;
2662                         MethodName = "op_" + OperatorType;
2663                         
2664                         if (SecondArgType != null)
2665                                 length = 2;
2666                         
2667                         Parameter [] param_list = new Parameter [length];
2668
2669                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2670                                 Report.Error (
2671                                         558, Location, 
2672                                         "User defined operators `" +
2673                                         Prototype (parent) +
2674                                         "' must be declared static and public");
2675                         }
2676
2677                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
2678                                                        Parameter.Modifier.NONE, null);
2679                         if (SecondArgType != null)
2680                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
2681                                                                Parameter.Modifier.NONE, null);
2682                         
2683                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
2684                                                      new Parameters (param_list, null),
2685                                                      OptAttributes, Location.Null);
2686                         
2687                         OperatorMethod.Define (parent);
2688                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
2689
2690                         Type [] param_types = OperatorMethod.ParameterTypes (parent);
2691                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
2692                         Type return_type = OperatorMethod.GetReturnType (parent);
2693                         Type first_arg_type = param_types [0];
2694
2695                         // Rules for conversion operators
2696                         
2697                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2698                                 
2699                                 if (first_arg_type == return_type && first_arg_type == declaring_type)
2700                                         Report.Error (555, Location,
2701                                                "User-defined conversion cannot take an object of the enclosing type " +
2702                                                "and convert to an object of the enclosing type");
2703                                 
2704                                 if (first_arg_type != declaring_type && return_type != declaring_type)
2705                                         Report.Error (556, Location, 
2706                                                "User-defined conversion must convert to or from the enclosing type");
2707                                 
2708                                 if (first_arg_type == TypeManager.object_type || return_type == TypeManager.object_type)
2709                                         Report.Error (-8, Location,
2710                                                "User-defined conversion cannot convert to or from object type");
2711                                 
2712                                 if (first_arg_type.IsInterface || return_type.IsInterface)
2713                                         Report.Error (-9, Location,
2714                                                "User-defined conversion cannot convert to or from an interface type");   
2715                                 
2716                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type))
2717                                         Report.Error (-10, Location,
2718                                                 "User-defined conversion cannot convert between types that " +
2719                                                 "derive from each other"); 
2720                                 
2721                         } else if (SecondArgType == null) {
2722                                 // Checks for Unary operators
2723                                 
2724                                 if (first_arg_type != declaring_type) 
2725                                         Report.Error (562, Location,
2726                                                    "The parameter of a unary operator must be the containing type");
2727                                 
2728                                 
2729                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2730                                         if (return_type != declaring_type)
2731                                                 Report.Error (559, Location,
2732                                                        "The parameter and return type for ++ and -- " +
2733                                                        "must be the containing type");
2734                                         
2735                                 }
2736                                 
2737                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2738                                         if (return_type != TypeManager.bool_type)
2739                                                 Report.Error (215, Location,
2740                                                        "The return type of operator True or False " +
2741                                                        "must be bool");
2742                                 }
2743                                 
2744                         } else {
2745                                 // Checks for Binary operators
2746                                 
2747                                 if (first_arg_type != declaring_type &&
2748                                     param_types [1] != declaring_type)
2749                                         Report.Error (563, Location,
2750                                                "One of the parameters of a binary operator must be the containing type");
2751                         }
2752                         
2753                 
2754                         
2755                 }
2756                 
2757                 public void Emit (TypeContainer parent)
2758                 {
2759                         if (OptAttributes != null) {
2760                                 EmitContext ec = new EmitContext (parent, null, null, ModFlags);
2761                                 if (OptAttributes.AttributeSections != null) {
2762                                         foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2763                                                 if (asec.Attributes != null) {
2764                                                         foreach (Attribute a in asec.Attributes) {
2765                                                                 CustomAttributeBuilder cb = a.Resolve (ec);
2766                                                                 if (cb != null)
2767                                                                         OperatorMethodBuilder.SetCustomAttribute (cb);
2768                                                         }
2769                                                 }
2770                                         }
2771                                 }
2772                         }
2773                         
2774                         OperatorMethod.Block = Block;
2775                         OperatorMethod.Emit (parent);
2776                 }
2777                 
2778
2779         }
2780
2781         //
2782         // This is used to compare method signatures
2783         //
2784         struct MethodSignature {
2785                 public string Name;
2786                 public Type RetType;
2787                 public Type [] Parameters;
2788                 
2789                 public MethodSignature (string name, Type ret_type, Type [] parameters)
2790                 {
2791                         Name = name;
2792                         RetType = ret_type;
2793                         Parameters = parameters;
2794
2795                         if (parameters != null){
2796                                 if (parameters.Length == 0)
2797                                         Parameters = null;
2798                         } 
2799                 }
2800                 
2801                 public override int GetHashCode ()
2802                 {
2803                         return Name.GetHashCode ();
2804                 }
2805
2806                 public override bool Equals (Object o)
2807                 {
2808                         MethodSignature other = (MethodSignature) o;
2809
2810                         if (other.Name != Name)
2811                                 return false;
2812
2813                         if (other.RetType != RetType)
2814                                 return false;
2815                         
2816                         if (Parameters == null){
2817                                 if (other.Parameters == null)
2818                                         return true;
2819                                 return false;
2820                         }
2821
2822                         if (other.Parameters == null)
2823                                 return false;
2824                         
2825                         int c = Parameters.Length;
2826                         if (other.Parameters.Length != c)
2827                                 return false;
2828
2829                         for (int i = 0; i < c; i++)
2830                                 if (other.Parameters [i] != Parameters [i])
2831                                         return false;
2832
2833                         return true;
2834                 }
2835         }               
2836 }