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