2 // enum.cs: Enum handling.
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
18 public class Enum : DeclSpace {
20 ArrayList ordered_enums;
21 public readonly string BaseType;
22 public readonly string EnumName;
24 public TypeBuilder EnumBuilder;
25 public Attributes OptAttributes;
29 public readonly RootContext RootContext;
31 Hashtable member_to_location;
32 ArrayList field_builders;
34 public const int AllowedModifiers =
41 public Enum (RootContext rc, string type, int mod_flags, string name, Attributes attrs, Location l)
47 this.mod_flags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PUBLIC);
48 OptAttributes = attrs;
49 ordered_enums = new ArrayList ();
50 member_to_location = new Hashtable ();
51 field_builders = new ArrayList ();
55 // Adds @name to the enumeration space, with @expr
56 // being its definition.
58 public AdditionResult AddEnumMember (string name, Expression expr, Location loc)
60 if (defined_names.Contains (name))
61 return AdditionResult.NameExists;
63 DefineName (name, expr);
65 ordered_enums.Add (name);
66 member_to_location.Add (name, loc);
68 return AdditionResult.Success;
71 public void DefineEnum (object parent_builder)
73 TypeAttributes attr = TypeAttributes.Class | TypeAttributes.Sealed;
75 UnderlyingType = RootContext.TypeManager.LookupType (BaseType);
77 if (UnderlyingType != TypeManager.int32_type && UnderlyingType != TypeManager.uint32_type &&
78 UnderlyingType != TypeManager.int64_type && UnderlyingType != TypeManager.uint64_type &&
79 UnderlyingType != TypeManager.short_type && UnderlyingType != TypeManager.ushort_type &&
80 UnderlyingType != TypeManager.byte_type && UnderlyingType != TypeManager.sbyte_type) {
81 Report.Error (1008, Location,
82 "Type byte, sbyte, short, ushort, int, uint, long, or ulong expected");
86 if (parent_builder is ModuleBuilder) {
87 ModuleBuilder builder = (ModuleBuilder) parent_builder;
89 if ((ModFlags & Modifiers.PUBLIC) != 0)
90 attr |= TypeAttributes.Public;
92 attr |= TypeAttributes.NotPublic;
94 EnumBuilder = builder.DefineType (EnumName, attr, TypeManager.enum_type);
97 TypeBuilder builder = (TypeBuilder) parent_builder;
99 if ((ModFlags & Modifiers.PUBLIC) != 0)
100 attr |= TypeAttributes.NestedPublic;
102 attr |= TypeAttributes.NestedPrivate;
104 EnumBuilder = builder.DefineNestedType (EnumName, attr, TypeManager.enum_type);
107 EnumBuilder.DefineField ("value__", UnderlyingType,
108 FieldAttributes.Public | FieldAttributes.SpecialName);
110 RootContext.TypeManager.AddEnumType (EnumName, EnumBuilder, this);
115 bool IsValidEnumLiteral (Expression e)
120 if (e is IntLiteral || e is UIntLiteral || e is LongLiteral || e is ULongLiteral)
126 object GetNextDefaultValue (object default_value)
128 if (UnderlyingType == TypeManager.int32_type) {
129 int i = (int) default_value;
131 if (i < System.Int32.MaxValue)
135 } else if (UnderlyingType == TypeManager.uint32_type) {
136 uint i = (uint) default_value;
138 if (i < System.UInt32.MaxValue)
142 } else if (UnderlyingType == TypeManager.int64_type) {
143 long i = (long) default_value;
145 if (i < System.Int64.MaxValue)
149 } else if (UnderlyingType == TypeManager.uint64_type) {
150 ulong i = (ulong) default_value;
152 if (i < System.UInt64.MaxValue)
156 } else if (UnderlyingType == TypeManager.short_type) {
157 short i = (short) default_value;
159 if (i < System.Int16.MaxValue)
163 } else if (UnderlyingType == TypeManager.ushort_type) {
164 ushort i = (ushort) default_value;
166 if (i < System.UInt16.MaxValue)
170 } else if (UnderlyingType == TypeManager.byte_type) {
171 byte i = (byte) default_value;
173 if (i < System.Byte.MaxValue)
177 } else if (UnderlyingType == TypeManager.sbyte_type) {
178 sbyte i = (sbyte) default_value;
180 if (i < System.SByte.MaxValue)
189 void error31 (Literal l, Location loc)
191 Report.Error (31, loc, "Constant value '" + l.AsString () +
192 "' cannot be converted" +
193 " to a " + TypeManager.CSharpName (UnderlyingType));
197 public void Populate (TypeContainer tc)
200 // If there was an error during DefineEnum, return
202 if (EnumBuilder == null){
206 EmitContext ec = new EmitContext (tc, null, UnderlyingType, ModFlags);
208 object default_value = 0;
210 FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
211 | FieldAttributes.Literal;
214 foreach (string name in ordered_enums) {
215 Expression e = this [name];
216 Location loc = (Location) member_to_location [name];
219 e = Expression.Reduce (ec, e);
221 if (IsValidEnumLiteral (e)) {
222 Literal l = (Literal) e;
223 default_value = l.GetValue ();
225 if (default_value == null) {
231 Report.Error (1008, loc,
232 "Type byte, sbyte, short, ushort, int, uint, long, or ulong expected");
237 FieldBuilder fb = EnumBuilder.DefineField (name, UnderlyingType, attr);
239 if (default_value == null) {
240 Report.Error (543, loc, "Enumerator value for '" + name + "' is too large to " +
246 default_value = Convert.ChangeType (default_value, UnderlyingType);
248 error31 ((Literal) e, loc);
252 fb.SetConstant (default_value);
253 field_builders.Add (fb);
255 if (!TypeManager.RegisterField (fb, default_value))
258 default_value = GetNextDefaultValue (default_value);
261 if (OptAttributes == null)
264 if (OptAttributes.AttributeSections == null)
267 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
268 if (asec.Attributes == null)
271 foreach (Attribute a in asec.Attributes) {
272 CustomAttributeBuilder cb = a.Resolve (ec);
277 EnumBuilder.SetCustomAttribute (cb);
283 // Hack around System.Reflection as found everywhere else
285 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
287 ArrayList members = new ArrayList ();
289 if ((mt & MemberTypes.Field) != 0) {
290 foreach (FieldBuilder fb in field_builders)
291 if (filter (fb, criteria) == true)
295 int count = members.Count;
298 MemberInfo [] mi = new MemberInfo [count];
299 members.CopyTo (mi, 0);
306 public void CloseEnum ()
308 EnumBuilder.CreateType ();
311 public ArrayList ValueNames {
313 return ordered_enums;
317 public int ModFlags {
324 public Expression this [string name] {
326 return (Expression) defined_names [name];