2001-11-08 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / enum.cs
1 //
2 // enum.cs: Enum handling.
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 using System;
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
15
16 namespace CIR {
17
18         public class Enum : DeclSpace {
19
20                 ArrayList ordered_enums;
21                 public readonly string BaseType;
22                 public readonly string EnumName;
23                 int mod_flags;
24                 public TypeBuilder EnumBuilder;
25                 public Attributes  OptAttributes;
26
27                 Type UnderlyingType;
28
29                 public readonly RootContext RootContext;
30                 
31                 public const int AllowedModifiers =
32                         Modifiers.NEW |
33                         Modifiers.PUBLIC |
34                         Modifiers.PROTECTED |
35                         Modifiers.INTERNAL |
36                         Modifiers.PRIVATE;
37
38                 public Enum (RootContext rc, string type, int mod_flags, string name, Attributes attrs, Location l)
39                         : base (name, l)
40                 {
41                         RootContext = rc;
42                         this.BaseType = type;
43                         this.EnumName = name;
44                         this.mod_flags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PUBLIC);
45                         OptAttributes = attrs;
46                         ordered_enums = new ArrayList ();
47                 }
48
49                 // <summary>
50                 //   Adds @name to the enumeration space, with @expr
51                 //   being its definition.  
52                 // </summary>
53                 public AdditionResult AddEnumMember (string name, Expression expr)
54                 {
55                         if (defined_names.Contains (name))
56                                 return AdditionResult.NameExists;
57
58                         DefineName (name, expr);
59
60                         ordered_enums.Add (name);
61                         return AdditionResult.Success;
62                 }
63
64                 public void DefineEnum (object parent_builder)
65                 {
66                         TypeAttributes attr = TypeAttributes.Class | TypeAttributes.Sealed;
67
68                         UnderlyingType = RootContext.TypeManager.LookupType (BaseType);
69
70                         if (parent_builder is ModuleBuilder) {
71                                 ModuleBuilder builder = (ModuleBuilder) parent_builder;
72
73                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
74                                         attr |= TypeAttributes.Public;
75                                 else
76                                         attr |= TypeAttributes.NotPublic;
77                                 
78                                 EnumBuilder = builder.DefineType (EnumName, attr, TypeManager.enum_type);
79
80                         } else {
81                                 TypeBuilder builder = (TypeBuilder) parent_builder;
82
83                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
84                                         attr |= TypeAttributes.NestedPublic;
85                                 else
86                                         attr |= TypeAttributes.NestedPrivate;
87                                 
88                                 EnumBuilder = builder.DefineNestedType (EnumName, attr, TypeManager.enum_type);
89                         }
90
91                         EnumBuilder.DefineField ("value__", UnderlyingType,
92                                                  FieldAttributes.Public | FieldAttributes.SpecialName);
93                         
94                         RootContext.TypeManager.AddEnumType (EnumName, EnumBuilder, this);
95                 }
96
97                 bool IsValidEnumLiteral (Expression e)
98                 {
99                         if (!(e is Literal))
100                                 return false;
101
102                         if (e is IntLiteral || e is UIntLiteral || e is LongLiteral || e is ULongLiteral)
103                                 return true;
104                         else
105                                 return false;
106                 }
107                 
108                 public void Emit (TypeContainer tc)
109                 {
110                         EmitContext ec = new EmitContext (tc, null, UnderlyingType, ModFlags);
111
112                         int default_value = 0;
113
114                         FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
115                                              | FieldAttributes.Literal;
116
117                         foreach (string name in ordered_enums) {
118                                 Expression e = this [name];
119
120                                 if (e != null) {
121                                         e = Expression.Reduce (ec, e);
122
123                                         if (IsValidEnumLiteral (e))
124                                                 default_value = (int) ((Literal) e).GetValue ();
125                                         else {
126                                                 Report.Error (1008, Location,
127                                                   "Type byte, sbyte, short, ushort, int, uint, long, or ulong expected");
128                                                 return;
129                                         }
130                                 }
131                                 
132                                 FieldBuilder fb = EnumBuilder.DefineField (name, UnderlyingType, attr);
133
134                                 fb.SetConstant (default_value++);
135                         }
136
137                         if (OptAttributes != null) {
138                                 if (OptAttributes.AttributeSections != null) {
139                                         foreach (AttributeSection asec in OptAttributes.AttributeSections) {
140                                                 if (asec.Attributes != null) {
141                                                         foreach (Attribute a in asec.Attributes) {
142                                                                 CustomAttributeBuilder cb = a.Resolve (ec);
143                                                                 if (cb != null)
144                                                                         EnumBuilder.SetCustomAttribute (cb);
145                                                         }
146                                                 }
147                                         }
148                                 }
149                         }
150                         
151                 }
152
153                 public void CloseEnum ()
154                 {
155                         EnumBuilder.CreateType ();
156                 }
157                 
158                 public ArrayList ValueNames {
159                         get {
160                                 return ordered_enums;
161                         }
162                 }
163
164                 public int ModFlags {
165                         get {
166                                 return mod_flags;
167                         }
168                 }
169                 
170                 // indexer
171                 public Expression this [string name] {
172                         get {
173                                 return (Expression) defined_names [name];
174                         }
175                 }
176         }
177 }