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);
108 EnumBuilder.DefineField ("value__", UnderlyingType,
109 FieldAttributes.Public | FieldAttributes.SpecialName);
111 RootContext.TypeManager.AddEnumType (EnumName, EnumBuilder, this);
114 bool IsValidEnumLiteral (Expression e)
119 if (e is IntLiteral || e is UIntLiteral || e is LongLiteral || e is ULongLiteral)
125 object GetNextDefaultValue (object default_value)
127 if (UnderlyingType == TypeManager.int32_type) {
128 int i = (int) default_value;
130 if (i < System.Int32.MaxValue)
134 } else if (UnderlyingType == TypeManager.uint32_type) {
135 uint i = (uint) default_value;
137 if (i < System.UInt32.MaxValue)
141 } else if (UnderlyingType == TypeManager.int64_type) {
142 long i = (long) default_value;
144 if (i < System.Int64.MaxValue)
148 } else if (UnderlyingType == TypeManager.uint64_type) {
149 ulong i = (ulong) default_value;
151 if (i < System.UInt64.MaxValue)
155 } else if (UnderlyingType == TypeManager.short_type) {
156 short i = (short) default_value;
158 if (i < System.Int16.MaxValue)
162 } else if (UnderlyingType == TypeManager.ushort_type) {
163 ushort i = (ushort) default_value;
165 if (i < System.UInt16.MaxValue)
169 } else if (UnderlyingType == TypeManager.byte_type) {
170 byte i = (byte) default_value;
172 if (i < System.Byte.MaxValue)
176 } else if (UnderlyingType == TypeManager.sbyte_type) {
177 sbyte i = (sbyte) default_value;
179 if (i < System.SByte.MaxValue)
188 void error31 (Literal l, Location loc)
190 Report.Error (31, loc, "Constant value '" + l.AsString () +
191 "' cannot be converted" +
192 " to a " + TypeManager.CSharpName (UnderlyingType));
196 public void Populate (TypeContainer tc)
198 EmitContext ec = new EmitContext (tc, null, UnderlyingType, ModFlags);
200 object default_value = 0;
202 FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
203 | FieldAttributes.Literal;
206 foreach (string name in ordered_enums) {
207 Expression e = this [name];
208 Location loc = (Location) member_to_location [name];
211 e = Expression.Reduce (ec, e);
213 if (IsValidEnumLiteral (e)) {
214 Literal l = (Literal) e;
215 default_value = l.GetValue ();
217 if (default_value == null) {
223 Report.Error (1008, loc,
224 "Type byte, sbyte, short, ushort, int, uint, long, or ulong expected");
229 FieldBuilder fb = EnumBuilder.DefineField (name, UnderlyingType, attr);
231 if (default_value == null) {
232 Report.Error (543, loc, "Enumerator value for '" + name + "' is too large to " +
238 default_value = Convert.ChangeType (default_value, UnderlyingType);
240 error31 ((Literal) e, loc);
244 fb.SetConstant (default_value);
245 field_builders.Add (fb);
247 if (!TypeManager.RegisterField (fb, default_value))
250 default_value = GetNextDefaultValue (default_value);
253 if (OptAttributes == null)
256 if (OptAttributes.AttributeSections == null)
259 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
260 if (asec.Attributes == null)
263 foreach (Attribute a in asec.Attributes) {
264 CustomAttributeBuilder cb = a.Resolve (ec);
269 EnumBuilder.SetCustomAttribute (cb);
275 // Hack around System.Reflection as found everywhere else
277 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
279 ArrayList members = new ArrayList ();
281 if ((mt & MemberTypes.Field) != 0) {
282 foreach (FieldBuilder fb in field_builders)
283 if (filter (fb, criteria) == true)
287 int count = members.Count;
290 MemberInfo [] mi = new MemberInfo [count];
291 members.CopyTo (mi, 0);
298 public void CloseEnum ()
300 EnumBuilder.CreateType ();
303 public ArrayList ValueNames {
305 return ordered_enums;
309 public int ModFlags {
316 public Expression this [string name] {
318 return (Expression) defined_names [name];