8fc020aae2b61c3d22e3f68dc3ba11d1e4e20086
[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 Type ResolveName (string name)
294                 {
295                         return null;
296                 }
297
298                 public CSC.Namespace Namespace {
299                         get {
300                                 return my_namespace;
301                         }
302
303                         set {
304                                 my_namespace = value;
305                         }
306                 }
307                 
308                 public int ResolveParents (Tree root)
309                 {
310                         if (Bases != null){
311                                 if (type_bases.Count == 0){
312                                         base_class_name = "System.Object";
313                                         return 0;
314                                 }
315                         } else
316                                 return 0;
317                         
318                         foreach (Type t in Bases){
319                                 Type resolved = ResolveName (t.Name);
320
321                                 
322                         }
323                         return 0;
324                 }
325
326                 public delegate void VisitContainer (TypeContainer container, object cback_data);
327
328                 void VisitTypesAt (TypeContainer root, VisitContainer visit, object cback)
329                 {
330                         if (root == null)
331                                 return;
332                         
333                         foreach (DictionaryEntry de in root.Types){
334                                 TypeContainer type = (TypeContainer) de.Value;
335
336                                 visit (type, cback);
337                                 VisitTypesAt (type, visit, cback);
338                         }
339                 }
340
341                 // <summary>
342                 //   Use this method to visit all the types in a type container.
343                 //   You can use cback to pass arbitrary data to your callback.
344                 // </summary>
345                 public void VisitTypes (VisitContainer visit, object cback)
346                 {
347                         foreach (DictionaryEntry de in types){
348                                 TypeContainer type = (TypeContainer) de.Value;
349
350                                 VisitTypesAt (type, visit, cback);
351                         }
352                         
353                 }
354
355                 internal class VisitExpressions_Lambda {
356                         VisitExpressionRoot vb;
357                         object user_data;
358
359                         void walk_arguments (ArrayList args)
360                         {
361                                 if (args == null)
362                                         return;
363                                 
364                                 int top = args.Count;
365
366                                 for (int i = 0; i < top; i++){
367                                         Argument arg = (Argument) args [i];
368
369                                         vb (arg.Expr, user_data);
370                                 }
371                         }
372
373                         void walk_block (Block b)
374                         {
375                         }
376                         
377                         void walk_constructor (Constructor c)
378                         {
379                                 ConstructorInitializer init = c.Initializer;
380                                 
381                                 if (init != null && init.Arguments != null)
382                                         walk_arguments (init.Arguments);
383
384                                 walk_block (c.Block);
385                         }
386
387                         void walk_properties (Property p)
388                         {
389                         }
390
391                         void walk_method (Method m)
392                         {
393                         }
394                                 
395                         void type_walker_1 (TypeContainer type, object cback)
396                         {
397                                 if (type.Fields != null){
398                                         foreach (DictionaryEntry de in type.Fields){
399                                                 Field f = (Field) de.Value;
400                                                 
401                                                 if (f.Initializer != null){
402                                                         if (f.Initializer is Expression)
403                                                                 vb ((Expression) f.Initializer, user_data);
404                                                 }
405                                         }
406                                 }
407
408                                 if (type.Constructors != null){
409                                         foreach (DictionaryEntry de in type.Constructors)
410                                                 walk_constructor ((Constructor) de.Value);
411                                 }
412
413                                 if (type.Properties != null){
414                                         foreach (DictionaryEntry de in type.Properties)
415                                                 walk_properties ((Property) de.Value);
416                                 }
417
418                                 if (type.MethodGroups != null){
419                                         foreach (DictionaryEntry de in type.MethodGroups){
420                                                 Hashtable methods = ((MethodGroup) de.Value).Methods;
421                                                 foreach (Method m in methods)
422                                                         walk_method (m);
423                                         }
424                                 }
425                         }
426
427                         
428                         internal VisitExpressions_Lambda (TypeContainer tc,
429                                                           VisitExpressionRoot vb,
430                                                           object user_data)
431                         {
432                                 this.vb = vb;
433                                 this.user_data = user_data;
434
435                                 tc.VisitTypes (new VisitContainer (type_walker_1), null);
436                         }
437                 }
438                 
439                 public delegate void VisitExpressionRoot (Expression e, object cback);
440                 // <summary>
441                 //   Use this method to visit all the code blocks in a TypeContainer
442                 // </summary>
443                 public void VisitExpressionRoots (VisitExpressionRoot vb, object cback)
444                 {
445                         VisitExpressions_Lambda l = new VisitExpressions_Lambda (this, vb, cback);
446                 }
447         }
448
449         public class Class : TypeContainer {
450                 // <summary>
451                 //   Modifiers allowed in a class declaration
452                 // </summary>
453                 public const int AllowedModifiers =
454                         Modifiers.NEW |
455                         Modifiers.PUBLIC |
456                         Modifiers.PROTECTED |
457                         Modifiers.INTERNAL |
458                         Modifiers.PRIVATE |
459                         Modifiers.ABSTRACT |
460                         Modifiers.SEALED;
461
462                 public Class (TypeContainer parent, string name, int mod)
463                         : base (parent, name)
464                 {
465                         int accmods;
466
467                         if (parent.Parent == null)
468                                 accmods = Modifiers.INTERNAL;
469                         else
470                                 accmods = Modifiers.PRIVATE;
471                         
472                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
473                 }
474         }
475
476         public class Struct : TypeContainer {
477                 // <summary>
478                 //   Modifiers allowed in a struct declaration
479                 // </summary>
480                 public const int AllowedModifiers =
481                         Modifiers.NEW |
482                         Modifiers.PUBLIC |
483                         Modifiers.PROTECTED |
484                         Modifiers.INTERNAL |
485                         Modifiers.PRIVATE;
486
487                 public Struct (TypeContainer parent, string name, int mod)
488                         : base (parent, name)
489                 {
490                         int accmods;
491                         
492                         if (parent.Parent == null)
493                                 accmods = Modifiers.INTERNAL;
494                         else
495                                 accmods = Modifiers.PRIVATE;
496                         
497                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
498                 }
499         }
500
501         public class Method {
502                 Parameters parameters;
503                 TypeRef    return_typeref;
504                 string     name;
505                 int        modifiers;
506                 Block      block;
507
508                 // return_type can be "null" for VOID values.
509                 public Method (TypeRef return_typeref, int mod, string name, Parameters parameters)
510                 {
511                         this.return_typeref = return_typeref;
512                         this.name = name;
513                         this.parameters = parameters;
514                         this.modifiers = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
515                 }
516
517                 // <summary>
518                 //   Modifiers allowed in a class declaration
519                 // </summary>
520                 const int AllowedModifiers =
521                         Modifiers.NEW |
522                         Modifiers.PUBLIC |
523                         Modifiers.PROTECTED |
524                         Modifiers.INTERNAL |
525                         Modifiers.PRIVATE |
526                         Modifiers.STATIC |
527                         Modifiers.VIRTUAL |
528                         Modifiers.SEALED |
529                         Modifiers.OVERRIDE |
530                         Modifiers.ABSTRACT |
531                         Modifiers.EXTERN;
532
533                 public Block Block {
534                         get {
535                                 return block;
536                         }
537
538                         set {
539                                 block = value;
540                         }
541                 }
542
543                 public string Name {
544                         get {
545                                 return name;
546                         }
547                 }
548
549                 public int ModFlags {
550                         get {
551                                 return modifiers;
552                         }
553                 }
554
555                 public Parameters Parameters {
556                         get {
557                                 return parameters;
558                         }
559                 }
560
561                 public Type ReturnType {
562                         get {
563                                 return return_typeref.Type;
564                         }
565                 }
566
567                 public string ArgumentSignature {
568                         get {
569                                 return ""; // TYPEFIX: Type.MakeParameterSignature (name, parameters);
570                         }
571                 }
572         }
573
574         public class Field {
575                 Type type;
576                 Object expr_or_array_init;
577                 string name;
578                 int modifiers;
579                 
580                 // <summary>
581                 //   Modifiers allowed in a class declaration
582                 // </summary>
583                 const int AllowedModifiers =
584                         Modifiers.NEW |
585                         Modifiers.PUBLIC |
586                         Modifiers.PROTECTED |
587                         Modifiers.INTERNAL |
588                         Modifiers.PRIVATE |
589                         Modifiers.STATIC |
590                         Modifiers.READONLY;
591
592                 public Field (TypeRef typeref, int mod, string name, Object expr_or_array_init)
593                 {
594                         this.type = type;
595                         this.modifiers = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
596                         this.name = name;
597                         this.expr_or_array_init = expr_or_array_init;
598                 }
599
600                 public Type Type {
601                         get {
602                                 return type;
603                         }
604                 }
605
606                 public object Initializer {
607                         get {
608                                 return expr_or_array_init;
609                         }
610                 }
611
612                 public string Name {
613                         get {
614                                 return name;
615                         }
616                 }
617
618                 public int ModFlags {
619                         get {
620                                 return modifiers;
621                         }
622                 }
623         }
624
625         public abstract class ConstructorInitializer {
626                 ArrayList argument_list;
627
628                 public ConstructorInitializer (ArrayList argument_list)
629                 {
630                         this.argument_list = argument_list;
631                 }
632
633                 public ArrayList Arguments {
634                         get {
635                                 return argument_list;
636                         }
637                 }
638         }
639
640         public class ConstructorBaseInitializer : ConstructorInitializer {
641                 public ConstructorBaseInitializer (ArrayList argument_list) : base (argument_list)
642                 {
643                 }
644         }
645
646         public class ConstructorThisInitializer : ConstructorInitializer {
647                 public ConstructorThisInitializer (ArrayList argument_list) : base (argument_list)
648                 {
649                 }
650         }
651         
652         public class Constructor {
653                 ConstructorInitializer init;
654                 string name;
655                 Parameters args;
656                 Block block;
657                 int mod_flags;
658
659                 // <summary>
660                 //   Modifiers allowed for a constructor.
661                 // </summary>
662                 const int AllowedModifiers =
663                         Modifiers.PUBLIC |
664                         Modifiers.PROTECTED |
665                         Modifiers.INTERNAL |
666                         Modifiers.STATIC |
667                         Modifiers.PRIVATE;
668
669                 //
670                 // The spec claims that static is not permitted, but
671                 // my very own code has static constructors.
672                 //
673                 
674                 public Constructor (string name, Parameters args, ConstructorInitializer init)
675                 {
676                         this.name = name;
677                         this.args = args;
678                         this.init = init;
679                 }
680
681                 public string Name {
682                         get {
683                                 return name;
684                         }
685                 }
686
687                 public ConstructorInitializer Initializer {
688                         get {
689                                 return init;
690                         }
691                 }
692
693                 public Parameters Parameters {
694                         get {
695                                 return args;
696                         }
697                 }
698
699                 public Block Block {
700                         get {
701                                 return block;
702                         }
703
704                         set {
705                                 block = value;
706                         }
707                 }
708
709                 public int ModFlags {
710                         get {
711                                 return mod_flags;
712                         }
713
714                         set {
715                                 mod_flags = Modifiers.Check (AllowedModifiers, value, 0);
716                         }
717                 }
718         }
719
720         public class Property {
721                 TypeRef typeref;
722                 string name;
723                 int mod_flags;
724                 Block get_block, set_block;
725
726                 const int AllowedModifiers =
727                         Modifiers.NEW |
728                         Modifiers.PUBLIC |
729                         Modifiers.PROTECTED |
730                         Modifiers.INTERNAL |
731                         Modifiers.PRIVATE |
732                         Modifiers.STATIC |
733                         Modifiers.SEALED |
734                         Modifiers.OVERRIDE |
735                         Modifiers.ABSTRACT |
736                         Modifiers.VIRTUAL;
737                 
738                 public Property (TypeRef typeref, string name, int mod_flags, Block get_block, Block set_block)
739                 {
740                         this.typeref = typeref;
741                         this.name = name;
742                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
743                         this.get_block = get_block;
744                         this.set_block = set_block;
745                 }
746
747                 public Type Type {
748                         get {
749                                 return typeref.Type;
750                         }
751                 }
752
753                 public string Name {
754                         get {
755                                 return name;
756                         }
757                 }
758
759                 public int ModFlags {
760                         get {
761                                 return mod_flags;
762                         }
763                 }
764
765                 public Block Get {
766                         get {
767                                 return get_block;
768                         }
769                 }
770
771                 public Block Set {
772                         get {
773                                 return set_block;
774                         }
775                 }
776         }
777 }
778