f0e8ae89162dec790a5b1dc3782e1f10d01ad48f
[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
697         public class Class : TypeContainer {
698                 // <summary>
699                 //   Modifiers allowed in a class declaration
700                 // </summary>
701                 public const int AllowedModifiers =
702                         Modifiers.NEW |
703                         Modifiers.PUBLIC |
704                         Modifiers.PROTECTED |
705                         Modifiers.INTERNAL |
706                         Modifiers.PRIVATE |
707                         Modifiers.ABSTRACT |
708                         Modifiers.SEALED;
709
710                 public Class (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
711                         : base (rc, parent, name)
712                 {
713                         int accmods;
714
715                         if (parent.Parent == null)
716                                 accmods = Modifiers.INTERNAL;
717                         else
718                                 accmods = Modifiers.PRIVATE;
719                         
720                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
721                         this.attributes = attrs;
722                 }
723
724                 //
725                 // FIXME: How do we deal with the user specifying a different
726                 // layout?
727                 //
728                 public override TypeAttributes TypeAttr {
729                         get {
730                                 return base.TypeAttr | TypeAttributes.AutoLayout;
731                         }
732                 }
733         }
734
735         public class Struct : TypeContainer {
736                 // <summary>
737                 //   Modifiers allowed in a struct declaration
738                 // </summary>
739                 public const int AllowedModifiers =
740                         Modifiers.NEW |
741                         Modifiers.PUBLIC |
742                         Modifiers.PROTECTED |
743                         Modifiers.INTERNAL |
744                         Modifiers.PRIVATE;
745
746                 public Struct (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
747                         : base (rc, parent, name)
748                 {
749                         int accmods;
750                         
751                         if (parent.Parent == null)
752                                 accmods = Modifiers.INTERNAL;
753                         else
754                                 accmods = Modifiers.PRIVATE;
755                         
756                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
757
758                         this.mod_flags |= Modifiers.SEALED;
759                         this.attributes = attrs;
760                         
761                 }
762
763                 //
764                 // FIXME: Allow the user to specify a different set of attributes
765                 // in some cases (Sealed for example is mandatory for a class,
766                 // but what SequentialLayout can be changed
767                 //
768                 public override TypeAttributes TypeAttr {
769                         get {
770                                 return base.TypeAttr |
771                                         TypeAttributes.SequentialLayout |
772                                         TypeAttributes.Sealed |
773                                         TypeAttributes.BeforeFieldInit;
774                         }
775                 }
776         }
777
778         public class Method {
779                 public readonly Parameters Parameters;
780                 public readonly string     ReturnType;
781                 public readonly string     Name;
782                 public readonly int        ModFlags;
783                 public MethodBuilder MethodBuilder;
784                 public readonly Attributes OptAttributes;
785                 
786                 Block block;
787                 
788                 // return_type can be "null" for VOID values.
789                 public Method (string return_type, int mod, string name, Parameters parameters, Attributes attrs)
790                 {
791                         Name = name;
792                         ReturnType = return_type;
793                         Parameters = parameters;
794                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
795                         OptAttributes = attrs;
796                 }
797
798                 // <summary>
799                 //   Modifiers allowed in a class declaration
800                 // </summary>
801                 const int AllowedModifiers =
802                         Modifiers.NEW |
803                         Modifiers.PUBLIC |
804                         Modifiers.PROTECTED |
805                         Modifiers.INTERNAL |
806                         Modifiers.PRIVATE |
807                         Modifiers.STATIC |
808                         Modifiers.VIRTUAL |
809                         Modifiers.SEALED |
810                         Modifiers.OVERRIDE |
811                         Modifiers.ABSTRACT |
812                         Modifiers.EXTERN;
813
814                 public Block Block {
815                         get {
816                                 return block;
817                         }
818
819                         set {
820                                 block = value;
821                         }
822                 }
823
824                 //
825                 // Returns the `System.Type' for the ReturnType of this
826                 // function.  Provides a nice cache.  (used between semantic analysis
827                 // and actual code generation
828                 //
829                 Type type_return_type;
830                 public Type GetReturnType (TypeContainer parent)
831                 {
832                         if (type_return_type == null)
833                                 type_return_type = parent.LookupType (ReturnType, false);
834                         
835                         return type_return_type;
836                 }
837
838                 //
839                 //  Returns the System.Type array for the parameters of this method
840                 //
841                 Type [] parameter_types;
842                 public Type [] ParameterTypes (TypeContainer parent)
843                 {
844                         if (Parameters == null)
845                                 return null;
846                         
847                         if (parameter_types == null)
848                                 parameter_types = Parameters.GetParameterInfo (parent);
849
850                         return parameter_types;
851                 }
852
853                 public CallingConventions GetCallingConvention (bool is_class)
854                 {
855                         CallingConventions cc = 0;
856                         
857                         cc = Parameters.GetCallingConvention ();
858
859                         if (is_class)
860                                 if ((ModFlags & Modifiers.STATIC) == 0)
861                                         cc |= CallingConventions.HasThis;
862
863                         return cc;
864                 }
865
866                 //
867                 // Creates the type
868                 // 
869                 public void Define (TypeContainer parent)
870                 {
871                         Type ret_type = GetReturnType (parent);
872                         Type [] parameters = ParameterTypes (parent);
873
874                         //
875                         // Create the method
876                         //
877                         MethodBuilder = parent.TypeBuilder.DefineMethod (
878                                 Name, Modifiers.MethodAttr (ModFlags),
879                                 GetCallingConvention (parent is Class),
880                                 ret_type, parameters);
881
882                         //
883                         // This is used to track the Entry Point,
884                         //
885                         // FIXME: Allow pluggable entry point, check arguments, etc.
886                         //
887                         if (Name == "Main"){
888                                 if ((ModFlags & Modifiers.STATIC) != 0){
889                                         parent.RootContext.EntryPoint = MethodBuilder;
890                                 }
891                         }
892                         
893                         //
894                         // Define each type attribute (in/out/ref) and
895                         // the argument names.
896                         //
897                         Parameter [] p = Parameters.FixedParameters;
898                         if (p != null){
899                                 int i;
900                                 
901                                 for (i = 0; i < p.Length; i++)
902                                         MethodBuilder.DefineParameter (
903                                                 i + 1, p [i].Attributes, p [i].Name);
904
905                                 if (i != parameters.Length)
906                                         Console.WriteLine ("Implement the type definition for params");
907                         }
908                 }
909
910                 //
911                 // Emits the code
912                 // 
913                 public void Emit (TypeContainer parent)
914                 {
915                         ILGenerator ig = MethodBuilder.GetILGenerator ();
916                         EmitContext ec = new EmitContext (parent, ig);
917                         
918                         ec.EmitTopBlock (block);
919                 }
920         }
921
922         public class Field {
923                 public readonly string Type;
924                 public readonly Object Initializer;
925                 public readonly string Name;
926                 public readonly int    ModFlags;
927                 public readonly Attributes OptAttributes;
928                 
929                 // <summary>
930                 //   Modifiers allowed in a class declaration
931                 // </summary>
932                 const int AllowedModifiers =
933                         Modifiers.NEW |
934                         Modifiers.PUBLIC |
935                         Modifiers.PROTECTED |
936                         Modifiers.INTERNAL |
937                         Modifiers.PRIVATE |
938                         Modifiers.STATIC |
939                         Modifiers.READONLY;
940
941                 public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
942                 {
943                         Type = type;
944                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
945                         Name = name;
946                         Initializer = expr_or_array_init;
947                         OptAttributes = attrs;
948                 }
949         }
950
951         public abstract class ConstructorInitializer {
952                 ArrayList argument_list;
953
954                 public ConstructorInitializer (ArrayList argument_list)
955                 {
956                         this.argument_list = argument_list;
957                 }
958
959                 public ArrayList Arguments {
960                         get {
961                                 return argument_list;
962                         }
963                 }
964         }
965
966         public class ConstructorBaseInitializer : ConstructorInitializer {
967                 public ConstructorBaseInitializer (ArrayList argument_list) : base (argument_list)
968                 {
969                 }
970         }
971
972         public class ConstructorThisInitializer : ConstructorInitializer {
973                 public ConstructorThisInitializer (ArrayList argument_list) : base (argument_list)
974                 {
975                 }
976         }
977         
978         public class Constructor {
979                 public ConstructorBuilder ConstructorBuilder;
980                 public readonly ConstructorInitializer Initializer;
981                 public readonly Parameters Parameters;
982                 public readonly string Name;
983                 Block block;
984                 int mod_flags;
985
986                 // <summary>
987                 //   Modifiers allowed for a constructor.
988                 // </summary>
989                 const int AllowedModifiers =
990                         Modifiers.PUBLIC |
991                         Modifiers.PROTECTED |
992                         Modifiers.INTERNAL |
993                         Modifiers.STATIC |
994                         Modifiers.PRIVATE;
995
996                 //
997                 // The spec claims that static is not permitted, but
998                 // my very own code has static constructors.
999                 //
1000                 public Constructor (string name, Parameters args, ConstructorInitializer init)
1001                 {
1002                         Name = name;
1003                         Parameters = args;
1004                         Initializer = init;
1005                 }
1006
1007                 //
1008                 // Returns true if this is a default constructor
1009                 //
1010                 public bool IsDefault ()
1011                 {
1012                         return  (Parameters == null) &&
1013                                 (Initializer is ConstructorBaseInitializer) &&
1014                                 (Initializer.Arguments == null);
1015                 }
1016
1017                 public int ModFlags {
1018                         get {
1019                                 return mod_flags;
1020                         }
1021
1022                         set {
1023                                 mod_flags = value;
1024                         }
1025                 }
1026                 
1027                 public Block Block {
1028                         get {
1029                                 return block;
1030                         }
1031
1032                         set {
1033                                 block = value;
1034                         }
1035                 }
1036
1037                 public CallingConventions GetCallingConvention (bool parent_is_class)
1038                 {
1039                         CallingConventions cc = 0;
1040                         
1041                         if (Parameters.ArrayParameter != null)
1042                                 cc |= CallingConventions.VarArgs;
1043                         else
1044                                 cc |= CallingConventions.Standard;
1045
1046                         if (parent_is_class)
1047                                 if ((ModFlags & Modifiers.STATIC) != 0)
1048                                         cc |= CallingConventions.HasThis;
1049
1050                                 // FIXME: How is `ExplicitThis' used in C#?
1051                                 
1052                         return cc;
1053                 }
1054
1055                 //
1056                 // Cached representation
1057                 ///
1058                 Type [] parameter_types;
1059                 public Type [] ParameterTypes (TypeContainer tc)
1060                 {
1061                         if (Parameters == null)
1062                                 return null;
1063                         
1064                         if (parameter_types == null)
1065                                 parameter_types = Parameters.GetParameterInfo (tc);
1066                         
1067                         return parameter_types;
1068                 }
1069
1070                 //
1071                 // Creates the ConstructorBuilder
1072                 //
1073                 public void Define (TypeContainer parent)
1074                 {
1075                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
1076                                                MethodAttributes.SpecialName);
1077                         
1078                         if ((ModFlags & Modifiers.STATIC) != 0)
1079                                 ca |= MethodAttributes.Static;
1080                         
1081                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
1082                                 ca, GetCallingConvention (parent is Class),
1083                                 ParameterTypes (parent));
1084                 }
1085
1086                 //
1087                 // Emits the code
1088                 //
1089                 public void Emit ()
1090                 {
1091                 }
1092         }
1093
1094         public class Property {
1095                 
1096                 public readonly string Type;
1097                 public readonly string Name;
1098                 public readonly int    ModFlags;
1099                 public Block           Get, Set;
1100                 public PropertyBuilder PropertyBuilder;
1101                 public Attributes OptAttributes;
1102                 
1103                 const int AllowedModifiers =
1104                         Modifiers.NEW |
1105                         Modifiers.PUBLIC |
1106                         Modifiers.PROTECTED |
1107                         Modifiers.INTERNAL |
1108                         Modifiers.PRIVATE |
1109                         Modifiers.STATIC |
1110                         Modifiers.SEALED |
1111                         Modifiers.OVERRIDE |
1112                         Modifiers.ABSTRACT |
1113                         Modifiers.VIRTUAL;
1114                 
1115                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
1116                 {
1117                         Type = type;
1118                         Name = name;
1119                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
1120                         Get = get_block;
1121                         Set = set_block;
1122                         OptAttributes = attrs;
1123                 }
1124
1125                 public void Define (TypeContainer parent)
1126                 {
1127
1128                         MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
1129                                         
1130                         // FIXME - how to handle PropertyAttributes.HasDefault
1131
1132                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
1133                                                        PropertyAttributes.SpecialName;
1134                 
1135                 
1136                         Type tp = parent.LookupType (Type, false);
1137                         Type [] prop_type = new Type [1];
1138                         prop_type [0] = tp;
1139
1140                         MethodBuilder mb;
1141                         
1142                         PropertyBuilder = parent.TypeBuilder.DefineProperty(Name, prop_attr, tp, null);
1143                                         
1144                         if (Get != null)
1145                         {
1146                                 mb = parent.TypeBuilder.DefineMethod("get_" + Name, method_attr, tp, null);
1147                                 PropertyBuilder.SetGetMethod (mb);
1148                         }
1149                         
1150                         if (Set != null)
1151                         {
1152                                 mb = parent.TypeBuilder.DefineMethod("set_" + Name, method_attr, null, prop_type);
1153                                 mb.DefineParameter(1, ParameterAttributes.None, "value"); 
1154                                 PropertyBuilder.SetSetMethod (mb);
1155                         }
1156
1157                 }
1158
1159         }
1160
1161         public class Event {
1162                 
1163                 const int AllowedModifiers =
1164                         Modifiers.NEW |
1165                         Modifiers.PUBLIC |
1166                         Modifiers.PROTECTED |
1167                         Modifiers.INTERNAL |
1168                         Modifiers.PRIVATE |
1169                         Modifiers.STATIC |
1170                         Modifiers.VIRTUAL |
1171                         Modifiers.SEALED |
1172                         Modifiers.OVERRIDE |
1173                         Modifiers.ABSTRACT;
1174
1175                 public readonly string    Type;
1176                 public readonly string    Name;
1177                 public readonly Object    Initializer;
1178                 public readonly int       ModFlags;
1179                 public readonly Block     Add;
1180                 public readonly Block     Remove;
1181                 public EventBuilder       EventBuilder;
1182                 public Attributes         OptAttributes;
1183                 
1184                 public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
1185                               Attributes attrs)
1186                 {
1187                         Type = type;
1188                         Name = name;
1189                         Initializer = init;
1190                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
1191                         Add = add_block;
1192                         Remove = rem_block;
1193                         OptAttributes = attrs;
1194                 }
1195
1196                 public void Define (TypeContainer parent)
1197                 {
1198                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
1199
1200                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
1201                         
1202                         MethodBuilder mb;
1203
1204                         Type t = parent.LookupType (Type, false);
1205                         Type [] p_type = new Type [1];
1206                         p_type [0] = t;
1207                         
1208                         EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
1209                         
1210                         if (Add != null) {
1211                                 mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null, p_type);
1212                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
1213                                 EventBuilder.SetAddOnMethod (mb);
1214                         }
1215
1216                         if (Remove != null) {
1217                                 mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null, p_type);
1218                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
1219                                 EventBuilder.SetRemoveOnMethod (mb);
1220                         }
1221                 }
1222                 
1223         }
1224
1225         public class Indexer {
1226
1227                 const int AllowedModifiers =
1228                         Modifiers.NEW |
1229                         Modifiers.PUBLIC |
1230                         Modifiers.PROTECTED |
1231                         Modifiers.INTERNAL |
1232                         Modifiers.PRIVATE |
1233                         Modifiers.VIRTUAL |
1234                         Modifiers.SEALED |
1235                         Modifiers.OVERRIDE |
1236                         Modifiers.ABSTRACT;
1237
1238                 public readonly string     Type;
1239                 public readonly string     InterfaceType;
1240                 public readonly Parameters FormalParameters;
1241                 public readonly int        ModFlags;
1242                 public readonly Block      Get;
1243                 public readonly Block      Set;
1244                 public Attributes          OptAttributes;
1245                 public MethodBuilder GetMethodBuilder;
1246                 public MethodBuilder SetMethodBuilder;
1247                 
1248
1249                 public Indexer (string type, string int_type, int flags, Parameters parms,
1250                                 Block get_block, Block set_block, Attributes attrs)
1251                 {
1252
1253                         Type = type;
1254                         InterfaceType = int_type;
1255                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
1256                         FormalParameters = parms;
1257                         Get = get_block;
1258                         Set = set_block;
1259                         OptAttributes = attrs;
1260                 }
1261
1262                 public void Define (TypeContainer parent)
1263                 {
1264                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
1265                         
1266                         Type ret_type = parent.LookupType (Type, false);
1267                         Type [] param_types = FormalParameters.GetParameterInfo (parent);
1268
1269                         GetMethodBuilder = parent.TypeBuilder.DefineMethod ("get_Item", attr, ret_type, param_types);
1270                         SetMethodBuilder = parent.TypeBuilder.DefineMethod ("set_Item", attr, ret_type, param_types);
1271                         
1272                         Parameter [] p = FormalParameters.FixedParameters;
1273
1274                         if (p != null) {
1275                                 int i;
1276                                 
1277                                 for (i = 0; i < p.Length; ++i) {
1278                                         GetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
1279                                         SetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
1280                                 }
1281                                 
1282                                 if (i != param_types.Length)
1283                                         Console.WriteLine ("Implement type definition for params");
1284                         }
1285
1286                 }
1287                 
1288         }
1289
1290         public class Operator {
1291
1292                 const int AllowedModifiers =
1293                         Modifiers.PUBLIC |
1294                         Modifiers.STATIC;
1295
1296                 public enum OpType {
1297
1298                         // Unary operators
1299                         Bang,
1300                         Tilde,
1301                         Increment,
1302                         Decrement,
1303                         True,
1304                         False,
1305
1306                         // Unary and Binary operators
1307                         Plus,
1308                         Minus,
1309                         
1310                         // Binary operators
1311                         Star,
1312                         Div,
1313                         Percent,
1314                         BitAnd,
1315                         BitOr,
1316                         Carret,
1317                         ShiftLeft,
1318                         ShiftRight,
1319                         Eq,
1320                         NotEq,
1321                         GreaterThan,
1322                         LesserThan,
1323                         GreaterOrEq,
1324                         LesserOrEq,
1325
1326                         // Implicit and Explicit
1327                         Implicit,
1328                         Explicit
1329                 };
1330
1331                 public readonly OpType OperatorType;
1332                 public readonly string ReturnType;
1333                 public readonly string FirstArgType;
1334                 public readonly string FirstArgName;
1335                 public readonly string SecondArgType;
1336                 public readonly string SecondArgName;
1337                 public readonly int    ModFlags;
1338                 public readonly Block  Block;
1339                 public Attributes      OptAttributes;
1340                 public MethodBuilder   OperatorMethodBuilder;
1341
1342                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
1343                                  string arg2type, string arg2name, Block block, Attributes attrs)
1344                 {
1345                         OperatorType = type;
1346                         ReturnType = ret_type;
1347                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
1348                         FirstArgType = arg1type;
1349                         FirstArgName = arg1name;
1350                         SecondArgType = arg2type;
1351                         SecondArgName = arg2name;
1352                         Block = block;
1353                         OptAttributes = attrs;
1354                 }
1355
1356                 public void Define (TypeContainer parent)
1357                 {
1358                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
1359
1360                         string name = "Operator" + OperatorType;
1361
1362                         Type ret_type = parent.LookupType (ReturnType, false);
1363
1364                         Type [] param_types = new Type [2];
1365
1366                         param_types [0] = parent.LookupType (FirstArgType, false);
1367                         if (SecondArgType != null)
1368                                 param_types [1] = parent.LookupType (SecondArgType, false);
1369                         
1370                         OperatorMethodBuilder = parent.TypeBuilder.DefineMethod (name, attr, ret_type, param_types);
1371
1372                         OperatorMethodBuilder.DefineParameter (1, ParameterAttributes.None, FirstArgName);
1373
1374                         if (SecondArgType != null)
1375                                 OperatorMethodBuilder.DefineParameter (2, ParameterAttributes.None, SecondArgName);
1376
1377                 }
1378                 
1379
1380         }
1381
1382 }
1383