f05f3c0a3235859642fd452eaf38bc6387246957
[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                 //
65                 // Pointers to the default constructor and the default static constructor
66                 //
67                 Constructor default_constructor;
68                 Constructor default_static_constructor;
69                 
70                 //
71                 // Whether we have seen a static constructor for this class or not
72                 //
73                 bool have_static_constructor = false;
74                 
75                 //
76                 // This is the namespace in which this typecontainer
77                 // was declared.  We use this to resolve names.
78                 //
79                 Namespace my_namespace;
80                 
81                 //
82                 // This one is computed after we can distinguish interfaces
83                 // from classes from the arraylist `type_bases' 
84                 //
85                 string     base_class_name;
86
87                 TypeContainer parent;
88                 ArrayList type_bases;
89
90                 //
91                 // This behaves like a property ;-)
92                 //
93                 public readonly RootContext RootContext;
94
95                 // Attributes for this type
96                 protected Attributes attributes;
97
98                 public TypeContainer (RootContext rc, TypeContainer parent, string name) : base (name)
99                 {
100                         string n;
101                         types = new ArrayList ();
102                         this.parent = parent;
103                         RootContext = rc;
104
105                         object a = rc.Report;
106                         
107                         if (parent == null)
108                                 n = "";
109                         else
110                                 n = parent.Name;
111
112                         base_class_name = null;
113                         
114                         //Console.WriteLine ("New class " + name + " inside " + n);
115                 }
116
117                 public AdditionResult AddConstant (Constant constant)
118                 {
119                         AdditionResult res;
120                         string name = constant.Name;
121
122                         if ((res = IsValid (name)) != AdditionResult.Success)
123                                 return res;
124                         
125                         if (constants == null)
126                                 constants = new ArrayList ();
127
128                         constants.Add (constant);
129                         DefineName (name, constant);
130
131                         return AdditionResult.Success;
132                 }
133
134                 public AdditionResult AddEnum (CIR.Enum e)
135                 {
136                         AdditionResult res;
137                         string name = e.Name;
138
139                         if ((res = IsValid (name)) != AdditionResult.Success)
140                                 return res;
141
142                         if (enums == null)
143                                 enums = new ArrayList ();
144
145                         enums.Add (e);
146                         DefineName (name, e);
147
148                         return AdditionResult.Success;
149                 }
150                 
151                 public AdditionResult AddClass (Class c)
152                 {
153                         AdditionResult res;
154                         string name = c.Name;
155
156
157                         if ((res = IsValid (name)) != AdditionResult.Success)
158                                 return res;
159
160                         DefineName (name, c);
161                         types.Add (c);
162
163                         return AdditionResult.Success;
164                 }
165
166                 public AdditionResult AddStruct (Struct s)
167                 {
168                         AdditionResult res;
169                         string name = s.Name;
170                         
171                         if ((res = IsValid (name)) != AdditionResult.Success)
172                                 return res;
173
174                         DefineName (name, s);
175                         types.Add (s);
176
177                         return AdditionResult.Success;
178                 }
179
180                 public AdditionResult AddDelegate (Delegate d)
181                 {
182                         AdditionResult res;
183                         string name = d.Name;
184
185                         if ((res = IsValid (name)) != AdditionResult.Success)
186                                 return res;
187
188                         if (delegates == null)
189                                 delegates = new ArrayList ();
190                         
191                         DefineName (name, d);
192                         delegates.Add (d);
193
194                         return AdditionResult.Success;
195                 }
196
197                 public AdditionResult AddMethod (Method method)
198                 {
199                         string name = method.Name;
200                         Object value = defined_names [name];
201                         
202                         if (value != null && (!(value is Method)))
203                                 return AdditionResult.NameExists;
204
205                         if (methods == null)
206                                 methods = new ArrayList ();
207
208                         methods.Add (method);
209                         DefineName (name, method);
210
211                         return AdditionResult.Success;
212                 }
213
214                 public AdditionResult AddConstructor (Constructor c)
215                 {
216                         if (c.Name != Basename)
217                                 return AdditionResult.NotAConstructor;
218                         
219                         if (constructors == null)
220                                 constructors = new ArrayList ();
221
222                         constructors.Add (c);
223
224                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
225                         
226                         if (is_static)
227                                 have_static_constructor = true;
228
229                         if (c.IsDefault ()){
230                                 if (is_static)
231                                         default_static_constructor = c;
232                                 else
233                                         default_constructor = c;
234                         }
235                         
236                         return AdditionResult.Success;
237                 }
238                 
239                 public AdditionResult AddInterface (Interface iface)
240                 {
241                         AdditionResult res;
242                         string name = iface.Name;
243
244                         if ((res = IsValid (name)) != AdditionResult.Success)
245                                 return res;
246                         
247                         if (interfaces == null)
248                                 interfaces = new ArrayList ();
249                         interfaces.Add (iface);
250                         DefineName (name, iface);
251                         
252                         return AdditionResult.Success;
253                 }
254
255                 public AdditionResult AddField (Field field)
256                 {
257                         AdditionResult res;
258                         string name = field.Name;
259                         
260                         if ((res = IsValid (name)) != AdditionResult.Success)
261                                 return res;
262
263                         if (fields == null)
264                                 fields = new ArrayList ();
265
266                         fields.Add (field);
267                         if (field.Initializer != null){
268                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
269                                         if (initialized_static_fields == null)
270                                                 initialized_static_fields = new ArrayList ();
271
272                                         initialized_static_fields.Add (field);
273
274                                         //
275                                         // We have not seen a static constructor,
276                                         // but we will provide static initialization of fields
277                                         //
278                                         have_static_constructor = true;
279                                 } else {
280                                         if (initialized_fields == null)
281                                                 initialized_fields = new ArrayList ();
282                                 
283                                         initialized_fields.Add (field);
284                                 }
285                         }
286                         
287                         DefineName (name, field);
288                         return AdditionResult.Success;
289                 }
290
291                 public AdditionResult AddProperty (Property prop)
292                 {
293                         AdditionResult res;
294                         string name = prop.Name;
295
296                         if ((res = IsValid (name)) != AdditionResult.Success)
297                                 return res;
298
299                         if (properties == null)
300                                 properties = new ArrayList ();
301
302                         properties.Add (prop);
303                         DefineName (name, prop);
304
305                         return AdditionResult.Success;
306                 }
307
308                 public AdditionResult AddEvent (Event e)
309                 {
310                         AdditionResult res;
311                         string name = e.Name;
312
313                         if ((res = IsValid (name)) != AdditionResult.Success)
314                                 return res;
315
316                         if (events == null)
317                                 events = new ArrayList ();
318                         
319                         events.Add (e);
320                         DefineName (name, e);
321
322                         return AdditionResult.Success;
323                 }
324
325                 public AdditionResult AddIndexer (Indexer i)
326                 {
327                         if (indexers == null)
328                                 indexers = new ArrayList ();
329
330                         indexers.Add (i);
331
332                         return AdditionResult.Success;
333                 }
334
335                 public AdditionResult AddOperator (Operator op)
336                 {
337                         if (operators == null)
338                                 operators = new ArrayList ();
339
340                         operators.Add (op);
341
342                         return AdditionResult.Success;
343                 }
344                 
345                 public TypeContainer Parent {
346                         get {
347                                 return parent;
348                         }
349                 }
350
351                 public ArrayList Types {
352                         get {
353                                 return types;
354                         }
355                 }
356
357                 public ArrayList Methods {
358                         get {
359                                 return methods;
360                         }
361                 }
362
363                 public ArrayList Constants {
364                         get {
365                                 return constants;
366                         }
367                 }
368
369                 public ArrayList Interfaces {
370                         get {
371                                 return interfaces;
372                         }
373                 }
374                 
375                 public int ModFlags {
376                         get {
377                                 return mod_flags;
378                         }
379                 }
380
381                 public string Base {
382                         get {
383                                 return base_class_name;
384                         }
385                 }
386                 
387                 public ArrayList Bases {
388                         get {
389                                 return type_bases;
390                         }
391
392                         set {
393                                 type_bases = value;
394                         }
395                 }
396
397                 public ArrayList Fields {
398                         get {
399                                 return fields;
400                         }
401                 }
402
403                 public ArrayList Constructors {
404                         get {
405                                 return constructors;
406                         }
407                 }
408
409                 public ArrayList Properties {
410                         get {
411                                 return properties;
412                         }
413                 }
414
415                 public ArrayList Events {
416                         get {
417                                 return events;
418                         }
419                 }
420                 
421                 public ArrayList Enums {
422                         get {
423                                 return enums;
424                         }
425                 }
426
427                 public ArrayList Indexers {
428                         get {
429                                 return indexers;
430                         }
431                 }
432
433                 public ArrayList Operators {
434                         get {
435                                 return operators;
436                         }
437                 }
438
439                 public ArrayList Delegates {
440                         get {
441                                 return delegates;
442                         }
443                 }
444                 
445                 public Attributes OptAttributes {
446                         get {
447                                 return attributes;
448                         }
449                 }
450                 
451                 public Namespace Namespace {
452                         get {
453                                 return my_namespace;
454                         }
455
456                         set {
457                                 my_namespace = value;
458                         }
459                 }
460
461                 //
462                 // The Toplevel is `root_types' which is a containerfor all
463                 // types defined, hence the non-obviios parent.parent.
464                 //
465                 // If we were not tracking Namespaces we could remove this.
466                 //
467                 bool IsTopLevel {
468                         get {
469                                 if (parent != null){
470                                         if (parent.parent == null)
471                                                 return true;
472                                 }
473
474                                 return false;
475                         }
476                 }
477
478                 // <summary>
479                 //   Returns the TypeAttributes for this TypeContainer
480                 // </summary>
481                 public virtual TypeAttributes TypeAttr {
482                         get {
483                                 TypeAttributes x = 0;
484
485                                 //
486                                 // FIXME: Figure out exactly how private, public and protected
487                                 // map to the TypeAttribute flags.
488                                 //
489                                 // FIXME: Figure out what `new' in the context of a class/struct means.
490                                 //
491                                 // FIXME: figure out what `internal' means in the context of class/structs
492                                 //
493                                 if ((mod_flags & Modifiers.PUBLIC) != 0)
494                                         x |= TypeAttributes.Public;
495
496                                 if ((mod_flags & Modifiers.PRIVATE) != 0)
497                                         x |= TypeAttributes.NotPublic;
498                                 
499                                 if ((mod_flags & Modifiers.ABSTRACT) != 0)
500                                         x |= TypeAttributes.Abstract;
501                                 
502                                 if ((mod_flags & Modifiers.SEALED) != 0)
503                                         x |= TypeAttributes.Sealed;
504
505                                 if (!IsTopLevel){
506                                         if ((mod_flags & Modifiers.PUBLIC) != 0)
507                                                 x |= TypeAttributes.NestedPublic;
508                                         else
509                                                 x |= TypeAttributes.NestedPrivate;
510                                 }
511
512                                 //
513                                 // If we have static constructors, the runtime needs to
514                                 // initialize the class, otherwise we can optimize
515                                 // the case.
516                                 //
517                                 if (!have_static_constructor)
518                                         x |= TypeAttributes.BeforeFieldInit;
519                                 return x;
520                         }
521                 }
522
523                 void EmitField (Field f)
524                 {
525                         Type t = LookupType (f.Type, false);
526
527                         if (t == null)
528                                 return;
529                         
530                         TypeBuilder.DefineField (f.Name, t, Modifiers.FieldAttr (f.ModFlags));
531                 }
532
533                 //
534                 // Emits the class field initializers
535                 //
536                 void EmitStaticFieldInitializers (ConstructorBuilder cb)
537                 {
538                         // FIXME: Implement
539                 }
540
541                 //
542                 // Emits the instance field initializers
543                 //
544                 void EmitFieldInitializers (ConstructorBuilder cb)
545                 {
546                         // FIXME: Implement
547                 }
548
549                 //
550                 // Emits a constructor
551                 //
552                 void EmitConstructor (Constructor c)
553                 {
554                         if ((c.ModFlags & Modifiers.STATIC) != 0){
555                                 if (initialized_static_fields != null)
556                                         EmitStaticFieldInitializers (c.ConstructorBuilder);
557                         } else {
558                                 if (initialized_fields != null)
559                                         EmitFieldInitializers (c.ConstructorBuilder);
560                         }
561
562                 }
563
564                 //
565                 // This function is used to emit instance and static constructors
566                 // when the user did not provide one.
567                 // 
568                 void EmitDefaultConstructor (bool is_static)
569                 {
570                         ConstructorBuilder cb;
571                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
572                                                MethodAttributes.SpecialName);
573
574                         if (is_static)
575                                 ca |= MethodAttributes.Static;
576                         
577                         //
578                         // Default constructors provided by the compiler should be `protected'
579                         // if the class is abstract, otherwise it is public
580                         //
581                         if ((mod_flags & Modifiers.ABSTRACT) != 0)
582                                 ca |= MethodAttributes.Family;
583                         else
584                                 ca |= MethodAttributes.Public;
585                         
586                         cb = TypeBuilder.DefineDefaultConstructor (ca);
587
588                         if (is_static)
589                                 EmitStaticFieldInitializers (cb);
590                         else
591                                 EmitFieldInitializers (cb);
592                 }
593
594                 //
595                 // Populates our TypeBuilder with fields and methods
596                 //
597                 public void Populate ()
598                 {
599                         if (Constants != null){
600                                 foreach (Constant c in Constants)
601                                         c.EmitConstant (RootContext, this);
602                         }
603
604                         if (Fields != null){
605                                 foreach (Field f in Fields)
606                                         EmitField (f);
607                         }
608
609                         if (Constructors != null){
610                                 foreach (Constructor c in Constructors)
611                                         c.Define (this);
612                         }
613
614                         if (Methods != null){
615                                 foreach (Method m in Methods)
616                                         m.Define (this);
617                         }
618
619                         if (Properties != null) {
620                                 foreach (Property p in Properties)
621                                         p.Define (this);
622                         }
623
624                         if (Enums != null) {
625                                 foreach (Enum e in Enums)
626                                         e.Define (this);
627                         }
628
629                         if (Events != null) {
630                                 foreach (Event e in Events)
631                                         e.Define (this);
632                         }
633
634                         if (Indexers != null) {
635                                 foreach (Indexer i in Indexers)
636                                         i.Define (this);
637                         }
638
639                         if (Operators != null) {
640                                 foreach (Operator o in Operators)
641                                         o.Define (this);
642                         }
643
644                         if (Delegates != null) {
645                                 foreach (Delegate d in Delegates)
646                                         d.Define (this);
647                         }
648                         
649                         
650                 }
651
652                 //
653                 // Emits the code, this step is performed after all
654                 // the types, enumerations, constructors
655                 //
656                 public void Emit ()
657                 {
658                         if (default_constructor == null)
659                                 EmitDefaultConstructor (false);
660
661                         if (initialized_static_fields != null && default_static_constructor == null)
662                                 EmitDefaultConstructor (true);
663
664                         if (Constructors != null)
665                                 foreach (Constructor c in Constructors)
666                                         c.Emit ();
667                         
668                         if (Methods != null)
669                                 foreach (Method m in Methods)
670                                         m.Emit (this);
671                 }
672                 
673                 public delegate void ExamineType (TypeContainer container, object cback_data);
674
675                 void WalkTypesAt (TypeContainer root, ExamineType visit, object cback_data)
676                 {
677                         if (root == null)
678                                 return;
679
680                         foreach (TypeContainer type in root.Types){
681                                 visit (type, cback_data);
682                                 WalkTypesAt (type, visit, cback_data);
683                         }
684                 }
685
686                 public void WalkTypes (ExamineType visit, object cback)
687                 {
688                         WalkTypesAt (this, visit, cback);
689                 }
690
691                 public Type LookupType (string name, bool silent)
692                 {
693                         return RootContext.LookupType (this, name, silent);
694                 }
695
696                 // <summary>
697                 // This method returns the members of this type just like Type.FindMembers would
698                 // Only, we need to use this for types which are _being_ defined because MS' brain
699                 // dead implementation can't take care of that ;-)
700                 // </summary>
701                 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
702                 {
703                         // FIXME : Need to actually take care of all the various
704                         // arguments being passed in but for now, we only bother with
705                         // the MemberTypes and criteria arguments.
706
707                         switch (mt) {
708
709                         case MemberTypes.All:
710
711                                 break;
712
713                         case MemberTypes.Constructor:
714
715                                 break;
716                                 
717                         case MemberTypes.Custom:
718
719                                 break;
720
721                         case MemberTypes.Event:
722
723                                 break;
724
725                         case MemberTypes.Field:
726
727                                 break;
728
729                         case MemberTypes.Method:
730
731                                 break;
732                                 
733                         case MemberTypes.NestedType:
734
735                                 break;
736                                 
737                         case MemberTypes.Property:
738
739                                 break;
740                                 
741                         case MemberTypes.TypeInfo:
742
743                                 break;
744
745                         }
746
747                         return null;
748                         
749                 }
750                 
751         }
752
753         public class Class : TypeContainer {
754                 // <summary>
755                 //   Modifiers allowed in a class declaration
756                 // </summary>
757                 public const int AllowedModifiers =
758                         Modifiers.NEW |
759                         Modifiers.PUBLIC |
760                         Modifiers.PROTECTED |
761                         Modifiers.INTERNAL |
762                         Modifiers.PRIVATE |
763                         Modifiers.ABSTRACT |
764                         Modifiers.SEALED;
765
766                 public Class (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
767                         : base (rc, parent, name)
768                 {
769                         int accmods;
770
771                         if (parent.Parent == null)
772                                 accmods = Modifiers.INTERNAL;
773                         else
774                                 accmods = Modifiers.PRIVATE;
775                         
776                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
777                         this.attributes = attrs;
778                 }
779
780                 //
781                 // FIXME: How do we deal with the user specifying a different
782                 // layout?
783                 //
784                 public override TypeAttributes TypeAttr {
785                         get {
786                                 return base.TypeAttr | TypeAttributes.AutoLayout;
787                         }
788                 }
789         }
790
791         public class Struct : TypeContainer {
792                 // <summary>
793                 //   Modifiers allowed in a struct declaration
794                 // </summary>
795                 public const int AllowedModifiers =
796                         Modifiers.NEW |
797                         Modifiers.PUBLIC |
798                         Modifiers.PROTECTED |
799                         Modifiers.INTERNAL |
800                         Modifiers.PRIVATE;
801
802                 public Struct (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
803                         : base (rc, parent, name)
804                 {
805                         int accmods;
806                         
807                         if (parent.Parent == null)
808                                 accmods = Modifiers.INTERNAL;
809                         else
810                                 accmods = Modifiers.PRIVATE;
811                         
812                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
813
814                         this.mod_flags |= Modifiers.SEALED;
815                         this.attributes = attrs;
816                         
817                 }
818
819                 //
820                 // FIXME: Allow the user to specify a different set of attributes
821                 // in some cases (Sealed for example is mandatory for a class,
822                 // but what SequentialLayout can be changed
823                 //
824                 public override TypeAttributes TypeAttr {
825                         get {
826                                 return base.TypeAttr |
827                                         TypeAttributes.SequentialLayout |
828                                         TypeAttributes.Sealed |
829                                         TypeAttributes.BeforeFieldInit;
830                         }
831                 }
832         }
833
834         public class Method {
835                 public readonly Parameters Parameters;
836                 public readonly string     ReturnType;
837                 public readonly string     Name;
838                 public readonly int        ModFlags;
839                 public MethodBuilder MethodBuilder;
840                 public readonly Attributes OptAttributes;
841                 
842                 Block block;
843                 
844                 // return_type can be "null" for VOID values.
845                 public Method (string return_type, int mod, string name, Parameters parameters, Attributes attrs)
846                 {
847                         Name = name;
848                         ReturnType = return_type;
849                         Parameters = parameters;
850                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
851                         OptAttributes = attrs;
852                 }
853
854                 // <summary>
855                 //   Modifiers allowed in a class declaration
856                 // </summary>
857                 const int AllowedModifiers =
858                         Modifiers.NEW |
859                         Modifiers.PUBLIC |
860                         Modifiers.PROTECTED |
861                         Modifiers.INTERNAL |
862                         Modifiers.PRIVATE |
863                         Modifiers.STATIC |
864                         Modifiers.VIRTUAL |
865                         Modifiers.SEALED |
866                         Modifiers.OVERRIDE |
867                         Modifiers.ABSTRACT |
868                         Modifiers.EXTERN;
869
870                 public Block Block {
871                         get {
872                                 return block;
873                         }
874
875                         set {
876                                 block = value;
877                         }
878                 }
879
880                 //
881                 // Returns the `System.Type' for the ReturnType of this
882                 // function.  Provides a nice cache.  (used between semantic analysis
883                 // and actual code generation
884                 //
885                 Type type_return_type;
886                 public Type GetReturnType (TypeContainer parent)
887                 {
888                         if (type_return_type == null)
889                                 type_return_type = parent.LookupType (ReturnType, false);
890                         
891                         return type_return_type;
892                 }
893
894                 //
895                 //  Returns the System.Type array for the parameters of this method
896                 //
897                 Type [] parameter_types;
898                 public Type [] ParameterTypes (TypeContainer parent)
899                 {
900                         if (Parameters == null)
901                                 return null;
902                         
903                         if (parameter_types == null)
904                                 parameter_types = Parameters.GetParameterInfo (parent);
905
906                         return parameter_types;
907                 }
908
909                 public CallingConventions GetCallingConvention (bool is_class)
910                 {
911                         CallingConventions cc = 0;
912                         
913                         cc = Parameters.GetCallingConvention ();
914
915                         if (is_class)
916                                 if ((ModFlags & Modifiers.STATIC) == 0)
917                                         cc |= CallingConventions.HasThis;
918
919                         return cc;
920                 }
921
922                 //
923                 // Creates the type
924                 // 
925                 public void Define (TypeContainer parent)
926                 {
927                         Type ret_type = GetReturnType (parent);
928                         Type [] parameters = ParameterTypes (parent);
929
930                         //
931                         // Create the method
932                         //
933                         MethodBuilder = parent.TypeBuilder.DefineMethod (
934                                 Name, Modifiers.MethodAttr (ModFlags),
935                                 GetCallingConvention (parent is Class),
936                                 ret_type, parameters);
937
938                         //
939                         // This is used to track the Entry Point,
940                         //
941                         // FIXME: Allow pluggable entry point, check arguments, etc.
942                         //
943                         if (Name == "Main"){
944                                 if ((ModFlags & Modifiers.STATIC) != 0){
945                                         parent.RootContext.EntryPoint = MethodBuilder;
946                                 }
947                         }
948                         
949                         //
950                         // Define each type attribute (in/out/ref) and
951                         // the argument names.
952                         //
953                         Parameter [] p = Parameters.FixedParameters;
954                         if (p != null){
955                                 int i;
956                                 
957                                 for (i = 0; i < p.Length; i++)
958                                         MethodBuilder.DefineParameter (
959                                                 i + 1, p [i].Attributes, p [i].Name);
960
961                                 if (i != parameters.Length)
962                                         Console.WriteLine ("Implement the type definition for params");
963                         }
964                 }
965
966                 //
967                 // Emits the code
968                 // 
969                 public void Emit (TypeContainer parent)
970                 {
971                         ILGenerator ig = MethodBuilder.GetILGenerator ();
972                         EmitContext ec = new EmitContext (parent, ig);
973                         
974                         ec.EmitTopBlock (block);
975                 }
976         }
977
978         public class Field {
979                 public readonly string Type;
980                 public readonly Object Initializer;
981                 public readonly string Name;
982                 public readonly int    ModFlags;
983                 public readonly Attributes OptAttributes;
984                 
985                 // <summary>
986                 //   Modifiers allowed in a class declaration
987                 // </summary>
988                 const int AllowedModifiers =
989                         Modifiers.NEW |
990                         Modifiers.PUBLIC |
991                         Modifiers.PROTECTED |
992                         Modifiers.INTERNAL |
993                         Modifiers.PRIVATE |
994                         Modifiers.STATIC |
995                         Modifiers.READONLY;
996
997                 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
998                 {
999                         Type = type;
1000                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
1001                         Name = name;
1002                         Initializer = expr_or_array_init;
1003                         OptAttributes = attrs;
1004                 }
1005         }
1006
1007         public abstract class ConstructorInitializer {
1008                 ArrayList argument_list;
1009
1010                 public ConstructorInitializer (ArrayList argument_list)
1011                 {
1012                         this.argument_list = argument_list;
1013                 }
1014
1015                 public ArrayList Arguments {
1016                         get {
1017                                 return argument_list;
1018                         }
1019                 }
1020         }
1021
1022         public class ConstructorBaseInitializer : ConstructorInitializer {
1023                 public ConstructorBaseInitializer (ArrayList argument_list) : base (argument_list)
1024                 {
1025                 }
1026         }
1027
1028         public class ConstructorThisInitializer : ConstructorInitializer {
1029                 public ConstructorThisInitializer (ArrayList argument_list) : base (argument_list)
1030                 {
1031                 }
1032         }
1033         
1034         public class Constructor {
1035                 public ConstructorBuilder ConstructorBuilder;
1036                 public readonly ConstructorInitializer Initializer;
1037                 public readonly Parameters Parameters;
1038                 public readonly string Name;
1039                 Block block;
1040                 int mod_flags;
1041
1042                 // <summary>
1043                 //   Modifiers allowed for a constructor.
1044                 // </summary>
1045                 const int AllowedModifiers =
1046                         Modifiers.PUBLIC |
1047                         Modifiers.PROTECTED |
1048                         Modifiers.INTERNAL |
1049                         Modifiers.STATIC |
1050                         Modifiers.PRIVATE;
1051
1052                 //
1053                 // The spec claims that static is not permitted, but
1054                 // my very own code has static constructors.
1055                 //
1056                 public Constructor (string name, Parameters args, ConstructorInitializer init)
1057                 {
1058                         Name = name;
1059                         Parameters = args;
1060                         Initializer = init;
1061                 }
1062
1063                 //
1064                 // Returns true if this is a default constructor
1065                 //
1066                 public bool IsDefault ()
1067                 {
1068                         return  (Parameters == null) &&
1069                                 (Initializer is ConstructorBaseInitializer) &&
1070                                 (Initializer.Arguments == null);
1071                 }
1072
1073                 public int ModFlags {
1074                         get {
1075                                 return mod_flags;
1076                         }
1077
1078                         set {
1079                                 mod_flags = value;
1080                         }
1081                 }
1082                 
1083                 public Block Block {
1084                         get {
1085                                 return block;
1086                         }
1087
1088                         set {
1089                                 block = value;
1090                         }
1091                 }
1092
1093                 public CallingConventions GetCallingConvention (bool parent_is_class)
1094                 {
1095                         CallingConventions cc = 0;
1096                         
1097                         if (Parameters.ArrayParameter != null)
1098                                 cc |= CallingConventions.VarArgs;
1099                         else
1100                                 cc |= CallingConventions.Standard;
1101
1102                         if (parent_is_class)
1103                                 if ((ModFlags & Modifiers.STATIC) != 0)
1104                                         cc |= CallingConventions.HasThis;
1105
1106                                 // FIXME: How is `ExplicitThis' used in C#?
1107                                 
1108                         return cc;
1109                 }
1110
1111                 //
1112                 // Cached representation
1113                 ///
1114                 Type [] parameter_types;
1115                 public Type [] ParameterTypes (TypeContainer tc)
1116                 {
1117                         if (Parameters == null)
1118                                 return null;
1119                         
1120                         if (parameter_types == null)
1121                                 parameter_types = Parameters.GetParameterInfo (tc);
1122                         
1123                         return parameter_types;
1124                 }
1125
1126                 //
1127                 // Creates the ConstructorBuilder
1128                 //
1129                 public void Define (TypeContainer parent)
1130                 {
1131                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
1132                                                MethodAttributes.SpecialName);
1133                         
1134                         if ((ModFlags & Modifiers.STATIC) != 0)
1135                                 ca |= MethodAttributes.Static;
1136                         
1137                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
1138                                 ca, GetCallingConvention (parent is Class),
1139                                 ParameterTypes (parent));
1140                 }
1141
1142                 //
1143                 // Emits the code
1144                 //
1145                 public void Emit ()
1146                 {
1147                 }
1148         }
1149
1150         public class Property {
1151                 
1152                 public readonly string Type;
1153                 public readonly string Name;
1154                 public readonly int    ModFlags;
1155                 public Block           Get, Set;
1156                 public PropertyBuilder PropertyBuilder;
1157                 public Attributes OptAttributes;
1158                 
1159                 const int AllowedModifiers =
1160                         Modifiers.NEW |
1161                         Modifiers.PUBLIC |
1162                         Modifiers.PROTECTED |
1163                         Modifiers.INTERNAL |
1164                         Modifiers.PRIVATE |
1165                         Modifiers.STATIC |
1166                         Modifiers.SEALED |
1167                         Modifiers.OVERRIDE |
1168                         Modifiers.ABSTRACT |
1169                         Modifiers.VIRTUAL;
1170                 
1171                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
1172                 {
1173                         Type = type;
1174                         Name = name;
1175                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
1176                         Get = get_block;
1177                         Set = set_block;
1178                         OptAttributes = attrs;
1179                 }
1180
1181                 public void Define (TypeContainer parent)
1182                 {
1183
1184                         MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
1185                                         
1186                         // FIXME - how to handle PropertyAttributes.HasDefault
1187
1188                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
1189                                                        PropertyAttributes.SpecialName;
1190                 
1191                 
1192                         Type tp = parent.LookupType (Type, false);
1193                         Type [] prop_type = new Type [1];
1194                         prop_type [0] = tp;
1195
1196                         MethodBuilder mb;
1197                         
1198                         PropertyBuilder = parent.TypeBuilder.DefineProperty(Name, prop_attr, tp, null);
1199                                         
1200                         if (Get != null)
1201                         {
1202                                 mb = parent.TypeBuilder.DefineMethod("get_" + Name, method_attr, tp, null);
1203                                 PropertyBuilder.SetGetMethod (mb);
1204                         }
1205                         
1206                         if (Set != null)
1207                         {
1208                                 mb = parent.TypeBuilder.DefineMethod("set_" + Name, method_attr, null, prop_type);
1209                                 mb.DefineParameter(1, ParameterAttributes.None, "value"); 
1210                                 PropertyBuilder.SetSetMethod (mb);
1211                         }
1212
1213                 }
1214
1215         }
1216
1217         public class Event {
1218                 
1219                 const int AllowedModifiers =
1220                         Modifiers.NEW |
1221                         Modifiers.PUBLIC |
1222                         Modifiers.PROTECTED |
1223                         Modifiers.INTERNAL |
1224                         Modifiers.PRIVATE |
1225                         Modifiers.STATIC |
1226                         Modifiers.VIRTUAL |
1227                         Modifiers.SEALED |
1228                         Modifiers.OVERRIDE |
1229                         Modifiers.ABSTRACT;
1230
1231                 public readonly string    Type;
1232                 public readonly string    Name;
1233                 public readonly Object    Initializer;
1234                 public readonly int       ModFlags;
1235                 public readonly Block     Add;
1236                 public readonly Block     Remove;
1237                 public EventBuilder       EventBuilder;
1238                 public Attributes         OptAttributes;
1239                 
1240                 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
1241                               Attributes attrs)
1242                 {
1243                         Type = type;
1244                         Name = name;
1245                         Initializer = init;
1246                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
1247                         Add = add_block;
1248                         Remove = rem_block;
1249                         OptAttributes = attrs;
1250                 }
1251
1252                 public void Define (TypeContainer parent)
1253                 {
1254                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
1255
1256                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
1257                         
1258                         MethodBuilder mb;
1259
1260                         Type t = parent.LookupType (Type, false);
1261                         Type [] p_type = new Type [1];
1262                         p_type [0] = t;
1263                         
1264                         EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
1265                         
1266                         if (Add != null) {
1267                                 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null, p_type);
1268                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
1269                                 EventBuilder.SetAddOnMethod (mb);
1270                         }
1271
1272                         if (Remove != null) {
1273                                 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null, p_type);
1274                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
1275                                 EventBuilder.SetRemoveOnMethod (mb);
1276                         }
1277                 }
1278                 
1279         }
1280
1281         public class Indexer {
1282
1283                 const int AllowedModifiers =
1284                         Modifiers.NEW |
1285                         Modifiers.PUBLIC |
1286                         Modifiers.PROTECTED |
1287                         Modifiers.INTERNAL |
1288                         Modifiers.PRIVATE |
1289                         Modifiers.VIRTUAL |
1290                         Modifiers.SEALED |
1291                         Modifiers.OVERRIDE |
1292                         Modifiers.ABSTRACT;
1293
1294                 public readonly string     Type;
1295                 public readonly string     InterfaceType;
1296                 public readonly Parameters FormalParameters;
1297                 public readonly int        ModFlags;
1298                 public readonly Block      Get;
1299                 public readonly Block      Set;
1300                 public Attributes          OptAttributes;
1301                 public MethodBuilder GetMethodBuilder;
1302                 public MethodBuilder SetMethodBuilder;
1303                 
1304
1305                 public Indexer (string type, string int_type, int flags, Parameters parms,
1306                                 Block get_block, Block set_block, Attributes attrs)
1307                 {
1308
1309                         Type = type;
1310                         InterfaceType = int_type;
1311                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
1312                         FormalParameters = parms;
1313                         Get = get_block;
1314                         Set = set_block;
1315                         OptAttributes = attrs;
1316                 }
1317
1318                 public void Define (TypeContainer parent)
1319                 {
1320                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
1321                         
1322                         Type ret_type = parent.LookupType (Type, false);
1323                         Type [] param_types = FormalParameters.GetParameterInfo (parent);
1324
1325                         GetMethodBuilder = parent.TypeBuilder.DefineMethod ("get_Item", attr, ret_type, param_types);
1326                         SetMethodBuilder = parent.TypeBuilder.DefineMethod ("set_Item", attr, ret_type, param_types);
1327                         
1328                         Parameter [] p = FormalParameters.FixedParameters;
1329
1330                         if (p != null) {
1331                                 int i;
1332                                 
1333                                 for (i = 0; i < p.Length; ++i) {
1334                                         GetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
1335                                         SetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
1336                                 }
1337                                 
1338                                 if (i != param_types.Length)
1339                                         Console.WriteLine ("Implement type definition for params");
1340                         }
1341
1342                 }
1343                 
1344         }
1345
1346         public class Operator {
1347
1348                 const int AllowedModifiers =
1349                         Modifiers.PUBLIC |
1350                         Modifiers.STATIC;
1351
1352                 public enum OpType {
1353
1354                         // Unary operators
1355                         Bang,
1356                         Tilde,
1357                         Increment,
1358                         Decrement,
1359                         True,
1360                         False,
1361
1362                         // Unary and Binary operators
1363                         Plus,
1364                         Minus,
1365                         
1366                         // Binary operators
1367                         Star,
1368                         Div,
1369                         Percent,
1370                         BitAnd,
1371                         BitOr,
1372                         Carret,
1373                         ShiftLeft,
1374                         ShiftRight,
1375                         Eq,
1376                         NotEq,
1377                         GreaterThan,
1378                         LesserThan,
1379                         GreaterOrEq,
1380                         LesserOrEq,
1381
1382                         // Implicit and Explicit
1383                         Implicit,
1384                         Explicit
1385                 };
1386
1387                 public readonly OpType OperatorType;
1388                 public readonly string ReturnType;
1389                 public readonly string FirstArgType;
1390                 public readonly string FirstArgName;
1391                 public readonly string SecondArgType;
1392                 public readonly string SecondArgName;
1393                 public readonly int    ModFlags;
1394                 public readonly Block  Block;
1395                 public Attributes      OptAttributes;
1396                 public MethodBuilder   OperatorMethodBuilder;
1397
1398                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
1399                                  string arg2type, string arg2name, Block block, Attributes attrs)
1400                 {
1401                         OperatorType = type;
1402                         ReturnType = ret_type;
1403                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
1404                         FirstArgType = arg1type;
1405                         FirstArgName = arg1name;
1406                         SecondArgType = arg2type;
1407                         SecondArgName = arg2name;
1408                         Block = block;
1409                         OptAttributes = attrs;
1410                 }
1411
1412                 public void Define (TypeContainer parent)
1413                 {
1414                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
1415
1416                         string name = "Operator" + OperatorType;
1417
1418                         Type ret_type = parent.LookupType (ReturnType, false);
1419
1420                         Type [] param_types = new Type [2];
1421
1422                         param_types [0] = parent.LookupType (FirstArgType, false);
1423                         if (SecondArgType != null)
1424                                 param_types [1] = parent.LookupType (SecondArgType, false);
1425                         
1426                         OperatorMethodBuilder = parent.TypeBuilder.DefineMethod (name, attr, ret_type, param_types);
1427
1428                         OperatorMethodBuilder.DefineParameter (1, ParameterAttributes.None, FirstArgName);
1429
1430                         if (SecondArgType != null)
1431                                 OperatorMethodBuilder.DefineParameter (2, ParameterAttributes.None, SecondArgName);
1432
1433                 }
1434                 
1435
1436         }
1437
1438 }
1439