131f29a43b7a6dfcba100ad3c4ed41aa6804fa46
[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 // TODO:
11 //
12 //    a. Maybe keep a list of defined names in the order they
13 //       appeared, so we can walk things in this way to present
14 //       the users with errors in that order?
15 //
16
17 using System.Collections;
18 using System;
19
20 namespace CIR {
21         
22         public class TypeContainer : DeclSpace {
23                 protected int mod_flags;
24                 Hashtable types, fields, properties;
25                 Hashtable enums, constants, interfaces, method_groups;
26
27                 ArrayList constructor_list;
28
29                 //
30                 // This is the namespace in which this typecontainer
31                 // was declared.  We use this to resolve names.
32                 //
33                 CSC.Namespace my_namespace;
34                 
35                 //
36                 // This one is computed after we can distinguish interfaces
37                 // from classes from the arraylist `type_bases' 
38                 //
39                 string     base_class_name;
40
41                 TypeContainer parent;
42                 ArrayList type_bases;
43
44                 public TypeContainer (TypeContainer parent, string name) : base (name)
45                 {
46                         types = new Hashtable ();
47                         this.parent = parent;
48
49                         string n;
50                         if (parent == null)
51                                 n = "";
52                         else
53                                 n = parent.Name;
54
55                         base_class_name = null;
56                         
57                         //Console.WriteLine ("New class " + name + " inside " + n);
58                 }
59
60                 public AdditionResult AddConstant (Constant constant)
61                 {
62                         AdditionResult res;
63                         string name = constant.Name;
64
65                         if ((res = IsValid (name)) != AdditionResult.Success)
66                                 return res;
67                         
68                         if (constants == null)
69                                 constants = new Hashtable ();
70
71                         constants.Add (name, constant);
72                         DefineName (name, constant);
73
74                         return AdditionResult.Success;
75                 }
76
77                 public AdditionResult AddEnum (CIR.Enum e)
78                 {
79                         AdditionResult res;
80                         string name = e.Name;
81
82                         if ((res = IsValid (name)) != AdditionResult.Success)
83                                 return res;
84
85                         if (enums == null)
86                                 enums = new Hashtable ();
87
88                         enums.Add (name, e);
89                         DefineName (name, e);
90
91                         return AdditionResult.Success;
92                 }
93                 
94                 public AdditionResult AddClass (Class c)
95                 {
96                         AdditionResult res;
97                         string name = c.Name;
98
99
100                         if ((res = IsValid (name)) != AdditionResult.Success)
101                                 return res;
102
103                         DefineName (name, c);
104                         types.Add (name, c);
105
106                         return AdditionResult.Success;
107                 }
108
109                 public AdditionResult AddStruct (Struct s)
110                 {
111                         AdditionResult res;
112                         string name = s.Name;
113                         
114                         if ((res = IsValid (name)) != AdditionResult.Success)
115                                 return res;
116
117                         DefineName (name, s);
118                         types.Add (name, s);
119
120                         return AdditionResult.Success;
121                 }
122
123                 public AdditionResult AddMethod (Method method)
124                 {
125                         string name = method.Name;
126                         Object value = defined_names [name];
127                         
128                         if (value != null && (!(value is MethodGroup)))
129                                 return AdditionResult.NameExists;
130
131                         if (method_groups == null)
132                                 method_groups = new Hashtable ();
133
134                         MethodGroup mg = (MethodGroup) method_groups [name];
135                         if (mg == null){
136                                 mg = new MethodGroup (name);
137
138                                 mg.Add (method);
139                                 method_groups.Add (name, mg);
140
141                                 return AdditionResult.Success;
142                         }
143                         mg.Add (method);
144
145                         if (value == null)
146                                 DefineName (name, mg);
147                         
148                         return AdditionResult.Success;
149                 }
150
151                 public AdditionResult AddConstructor (Constructor c)
152                 {
153                         if (c.Name != Basename)
154                                 return AdditionResult.NotAConstructor;
155                         
156                         if (constructor_list == null)
157                                 constructor_list = new ArrayList ();
158
159                         constructor_list.Add (c);
160                         
161                         return AdditionResult.Success;
162                 }
163                 
164                 public AdditionResult AddInterface (Interface iface)
165                 {
166                         AdditionResult res;
167                         string name = iface.Name;
168
169                         if ((res = IsValid (name)) != AdditionResult.Success)
170                                 return res;
171                         
172                         if (interfaces == null)
173                                 interfaces = new Hashtable ();
174                         interfaces.Add (name, iface);
175                         DefineName (name, iface);
176                         
177                         return AdditionResult.Success;
178                 }
179
180                 public AdditionResult AddField (Field field)
181                 {
182                         AdditionResult res;
183                         string name = field.Name;
184                         
185                         if ((res = IsValid (name)) != AdditionResult.Success)
186                                 return res;
187
188                         if (fields == null)
189                                 fields = new Hashtable ();
190
191                         fields.Add (name, field);
192                         DefineName (name, field);
193                         return AdditionResult.Success;
194                 }
195
196                 public AdditionResult AddProperty (Property prop)
197                 {
198                         AdditionResult res;
199                         string name = prop.Name;
200
201                         if ((res = IsValid (name)) != AdditionResult.Success)
202                                 return res;
203
204                         if (properties == null)
205                                 properties = new Hashtable ();
206
207                         properties.Add (name, prop);
208                         DefineName (name, prop);
209
210                         return AdditionResult.Success;
211                 }
212                 
213                 public Constant GetConstant (string name) {
214                         return (Constant) constants [name];
215                 }
216                 
217                 public TypeContainer Parent {
218                         get {
219                                 return parent;
220                         }
221                 }
222
223                 public Hashtable Types {
224                         get {
225                                 return types;
226                         }
227                 }
228
229                 public Hashtable MethodGroups {
230                         get {
231                                 return method_groups;
232                         }
233                 }
234
235                 public Hashtable Constants {
236                         get {
237                                 return constants;
238                         }
239                 }
240
241                 public Hashtable Interfaces {
242                         get {
243                                 return interfaces;
244                         }
245                 }
246                 
247                 public int ModFlags {
248                         get {
249                                 return mod_flags;
250                         }
251                 }
252
253                 public string Base {
254                         get {
255                                 return base_class_name;
256                         }
257                 }
258                 
259                 public ArrayList Bases {
260                         get {
261                                 return type_bases;
262                         }
263
264                         set {
265                                 type_bases = value;
266                         }
267                 }
268
269                 public Hashtable Fields {
270                         get {
271                                 return fields;
272                         }
273                 }
274
275                 public Hashtable Constructors {
276                         get {
277                                 return null; // constructors;
278                         }
279                 }
280
281                 public Hashtable Properties {
282                         get {
283                                 return properties;
284                         }
285                 }
286
287                 public Hashtable Enums {
288                         get {
289                                 return enums;
290                         }
291                 }
292
293                 public CSC.Namespace Namespace {
294                         get {
295                                 return my_namespace;
296                         }
297
298                         set {
299                                 my_namespace = value;
300                         }
301                 }
302                 
303                 public int ResolveParents (Tree root)
304                 {
305                         if (Bases == null){
306                                 base_class_name = "System.Object";
307                                 return 0;
308                         }
309                         
310                         if (type_bases.Count == 0){
311                                 base_class_name = "System.Object";
312                                 return 0;
313                         }
314                         
315                         return 0;
316                 }
317
318                 override public Type Define (Tree tree)
319                 {
320                         return null;
321                 }
322                 
323                 public delegate void VisitContainer (TypeContainer container, object cback_data);
324
325                 void VisitTypesAt (TypeContainer root, VisitContainer visit, object cback)
326                 {
327                         if (root == null)
328                                 return;
329                         
330                         foreach (DictionaryEntry de in root.Types){
331                                 TypeContainer type = (TypeContainer) de.Value;
332
333                                 visit (type, cback);
334                                 VisitTypesAt (type, visit, cback);
335                         }
336                 }
337
338                 // <summary>
339                 //   Use this method to visit all the types in a type container.
340                 //   You can use cback to pass arbitrary data to your callback.
341                 // </summary>
342                 public void VisitTypes (VisitContainer visit, object cback)
343                 {
344                         foreach (DictionaryEntry de in types){
345                                 TypeContainer type = (TypeContainer) de.Value;
346
347                                 VisitTypesAt (type, visit, cback);
348                         }
349                         
350                 }
351
352                 internal class VisitExpressions_Lambda {
353                         VisitExpressionRoot vb;
354                         object user_data;
355
356                         void walk_arguments (ArrayList args)
357                         {
358                                 if (args == null)
359                                         return;
360                                 
361                                 int top = args.Count;
362
363                                 for (int i = 0; i < top; i++){
364                                         Argument arg = (Argument) args [i];
365
366                                         vb (arg.Expr, user_data);
367                                 }
368                         }
369
370                         void walk_block (Block b)
371                         {
372                         }
373                         
374                         void walk_constructor (Constructor c)
375                         {
376                                 ConstructorInitializer init = c.Initializer;
377                                 
378                                 if (init != null && init.Arguments != null)
379                                         walk_arguments (init.Arguments);
380
381                                 walk_block (c.Block);
382                         }
383
384                         void walk_properties (Property p)
385                         {
386                         }
387
388                         void walk_method (Method m)
389                         {
390                         }
391                                 
392                         void type_walker_1 (TypeContainer type, object cback)
393                         {
394                                 if (type.Fields != null){
395                                         foreach (DictionaryEntry de in type.Fields){
396                                                 Field f = (Field) de.Value;
397                                                 
398                                                 if (f.Initializer != null){
399                                                         if (f.Initializer is Expression)
400                                                                 vb ((Expression) f.Initializer, user_data);
401                                                 }
402                                         }
403                                 }
404
405                                 if (type.Constructors != null){
406                                         foreach (DictionaryEntry de in type.Constructors)
407                                                 walk_constructor ((Constructor) de.Value);
408                                 }
409
410                                 if (type.Properties != null){
411                                         foreach (DictionaryEntry de in type.Properties)
412                                                 walk_properties ((Property) de.Value);
413                                 }
414
415                                 if (type.MethodGroups != null){
416                                         foreach (DictionaryEntry de in type.MethodGroups){
417                                                 Hashtable methods = ((MethodGroup) de.Value).Methods;
418                                                 foreach (Method m in methods)
419                                                         walk_method (m);
420                                         }
421                                 }
422                         }
423
424                         
425                         internal VisitExpressions_Lambda (TypeContainer tc,
426                                                           VisitExpressionRoot vb,
427                                                           object user_data)
428                         {
429                                 this.vb = vb;
430                                 this.user_data = user_data;
431
432                                 tc.VisitTypes (new VisitContainer (type_walker_1), null);
433                         }
434                 }
435                 
436                 public delegate void VisitExpressionRoot (Expression e, object cback);
437                 // <summary>
438                 //   Use this method to visit all the code blocks in a TypeContainer
439                 // </summary>
440                 public void VisitExpressionRoots (VisitExpressionRoot vb, object cback)
441                 {
442                         VisitExpressions_Lambda l = new VisitExpressions_Lambda (this, vb, cback);
443                 }
444         }
445
446         public class Class : TypeContainer {
447                 // <summary>
448                 //   Modifiers allowed in a class declaration
449                 // </summary>
450                 public const int AllowedModifiers =
451                         Modifiers.NEW |
452                         Modifiers.PUBLIC |
453                         Modifiers.PROTECTED |
454                         Modifiers.INTERNAL |
455                         Modifiers.PRIVATE |
456                         Modifiers.ABSTRACT |
457                         Modifiers.SEALED;
458
459                 public Class (TypeContainer parent, string name, int mod)
460                         : base (parent, name)
461                 {
462                         int accmods;
463
464                         if (parent.Parent == null)
465                                 accmods = Modifiers.INTERNAL;
466                         else
467                                 accmods = Modifiers.PRIVATE;
468                         
469                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
470                 }
471         }
472
473         public class Struct : TypeContainer {
474                 // <summary>
475                 //   Modifiers allowed in a struct declaration
476                 // </summary>
477                 public const int AllowedModifiers =
478                         Modifiers.NEW |
479                         Modifiers.PUBLIC |
480                         Modifiers.PROTECTED |
481                         Modifiers.INTERNAL |
482                         Modifiers.PRIVATE;
483
484                 public Struct (TypeContainer parent, string name, int mod)
485                         : base (parent, name)
486                 {
487                         int accmods;
488                         
489                         if (parent.Parent == null)
490                                 accmods = Modifiers.INTERNAL;
491                         else
492                                 accmods = Modifiers.PRIVATE;
493                         
494                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
495                 }
496         }
497
498         public class Method {
499                 Parameters parameters;
500                 TypeRef    return_typeref;
501                 string     name;
502                 int        modifiers;
503                 Block      block;
504
505                 // return_type can be "null" for VOID values.
506                 public Method (TypeRef return_typeref, int mod, string name, Parameters parameters)
507                 {
508                         this.return_typeref = return_typeref;
509                         this.name = name;
510                         this.parameters = parameters;
511                         this.modifiers = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
512                 }
513
514                 // <summary>
515                 //   Modifiers allowed in a class declaration
516                 // </summary>
517                 const int AllowedModifiers =
518                         Modifiers.NEW |
519                         Modifiers.PUBLIC |
520                         Modifiers.PROTECTED |
521                         Modifiers.INTERNAL |
522                         Modifiers.PRIVATE |
523                         Modifiers.STATIC |
524                         Modifiers.VIRTUAL |
525                         Modifiers.SEALED |
526                         Modifiers.OVERRIDE |
527                         Modifiers.ABSTRACT |
528                         Modifiers.EXTERN;
529
530                 public Block Block {
531                         get {
532                                 return block;
533                         }
534
535                         set {
536                                 block = value;
537                         }
538                 }
539
540                 public string Name {
541                         get {
542                                 return name;
543                         }
544                 }
545
546                 public int ModFlags {
547                         get {
548                                 return modifiers;
549                         }
550                 }
551
552                 public Parameters Parameters {
553                         get {
554                                 return parameters;
555                         }
556                 }
557
558                 public Type ReturnType {
559                         get {
560                                 return return_typeref.Type;
561                         }
562                 }
563
564                 public string ArgumentSignature {
565                         get {
566                                 return ""; // TYPEFIX: Type.MakeParameterSignature (name, parameters);
567                         }
568                 }
569         }
570
571         public class Field {
572                 Type type;
573                 Object expr_or_array_init;
574                 string name;
575                 int modifiers;
576                 
577                 // <summary>
578                 //   Modifiers allowed in a class declaration
579                 // </summary>
580                 const int AllowedModifiers =
581                         Modifiers.NEW |
582                         Modifiers.PUBLIC |
583                         Modifiers.PROTECTED |
584                         Modifiers.INTERNAL |
585                         Modifiers.PRIVATE |
586                         Modifiers.STATIC |
587                         Modifiers.READONLY;
588
589                 public Field (TypeRef typeref, int mod, string name, Object expr_or_array_init)
590                 {
591                         this.type = type;
592                         this.modifiers = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
593                         this.name = name;
594                         this.expr_or_array_init = expr_or_array_init;
595                 }
596
597                 public Type Type {
598                         get {
599                                 return type;
600                         }
601                 }
602
603                 public object Initializer {
604                         get {
605                                 return expr_or_array_init;
606                         }
607                 }
608
609                 public string Name {
610                         get {
611                                 return name;
612                         }
613                 }
614
615                 public int ModFlags {
616                         get {
617                                 return modifiers;
618                         }
619                 }
620         }
621
622         public abstract class ConstructorInitializer {
623                 ArrayList argument_list;
624
625                 public ConstructorInitializer (ArrayList argument_list)
626                 {
627                         this.argument_list = argument_list;
628                 }
629
630                 public ArrayList Arguments {
631                         get {
632                                 return argument_list;
633                         }
634                 }
635         }
636
637         public class ConstructorBaseInitializer : ConstructorInitializer {
638                 public ConstructorBaseInitializer (ArrayList argument_list) : base (argument_list)
639                 {
640                 }
641         }
642
643         public class ConstructorThisInitializer : ConstructorInitializer {
644                 public ConstructorThisInitializer (ArrayList argument_list) : base (argument_list)
645                 {
646                 }
647         }
648         
649         public class Constructor {
650                 ConstructorInitializer init;
651                 string name;
652                 Parameters args;
653                 Block block;
654                 int mod_flags;
655
656                 // <summary>
657                 //   Modifiers allowed for a constructor.
658                 // </summary>
659                 const int AllowedModifiers =
660                         Modifiers.PUBLIC |
661                         Modifiers.PROTECTED |
662                         Modifiers.INTERNAL |
663                         Modifiers.STATIC |
664                         Modifiers.PRIVATE;
665
666                 //
667                 // The spec claims that static is not permitted, but
668                 // my very own code has static constructors.
669                 //
670                 
671                 public Constructor (string name, Parameters args, ConstructorInitializer init)
672                 {
673                         this.name = name;
674                         this.args = args;
675                         this.init = init;
676                 }
677
678                 public string Name {
679                         get {
680                                 return name;
681                         }
682                 }
683
684                 public ConstructorInitializer Initializer {
685                         get {
686                                 return init;
687                         }
688                 }
689
690                 public Parameters Parameters {
691                         get {
692                                 return args;
693                         }
694                 }
695
696                 public Block Block {
697                         get {
698                                 return block;
699                         }
700
701                         set {
702                                 block = value;
703                         }
704                 }
705
706                 public int ModFlags {
707                         get {
708                                 return mod_flags;
709                         }
710
711                         set {
712                                 mod_flags = Modifiers.Check (AllowedModifiers, value, 0);
713                         }
714                 }
715         }
716
717         public class Property {
718                 TypeRef typeref;
719                 string name;
720                 int mod_flags;
721                 Block get_block, set_block;
722
723                 const int AllowedModifiers =
724                         Modifiers.NEW |
725                         Modifiers.PUBLIC |
726                         Modifiers.PROTECTED |
727                         Modifiers.INTERNAL |
728                         Modifiers.PRIVATE |
729                         Modifiers.STATIC |
730                         Modifiers.SEALED |
731                         Modifiers.OVERRIDE |
732                         Modifiers.ABSTRACT |
733                         Modifiers.VIRTUAL;
734                 
735                 public Property (TypeRef typeref, string name, int mod_flags, Block get_block, Block set_block)
736                 {
737                         this.typeref = typeref;
738                         this.name = name;
739                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
740                         this.get_block = get_block;
741                         this.set_block = set_block;
742                 }
743
744                 public Type Type {
745                         get {
746                                 return typeref.Type;
747                         }
748                 }
749
750                 public string Name {
751                         get {
752                                 return name;
753                         }
754                 }
755
756                 public int ModFlags {
757                         get {
758                                 return mod_flags;
759                         }
760                 }
761
762                 public Block Get {
763                         get {
764                                 return get_block;
765                         }
766                 }
767
768                 public Block Set {
769                         get {
770                                 return set_block;
771                         }
772                 }
773         }
774 }
775