2 // enum.cs: Enum handling.
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
6 // Anirban Bhattacharjee (banirban@novell.com)
7 // Jambunathan K (kjambunathan@novell.com)
9 // Licensed under the terms of the GNU GPL
11 // (C) 2001 Ximian, Inc (http://www.ximian.com)
15 using System.Collections;
16 using System.Reflection;
17 using System.Reflection.Emit;
19 namespace Mono.MonoBASIC {
21 public class EnumMember : MemberCore
30 bool in_transit = false;
31 FieldAttributes field_attrs = FieldAttributes.Public | FieldAttributes.Static
32 | FieldAttributes.Literal;
34 public EnumMember (Enum parent_enum, Expression expr, string name,
35 Location loc, Attributes attrs, int index):
36 base (name, attrs, loc)
38 this.parent_enum = parent_enum;
43 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
45 builder.SetCustomAttribute (cb);
48 public override AttributeTargets AttributeTargets {
50 return AttributeTargets.Field;
54 public override bool Define (TypeContainer tc)
56 throw new NotImplementedException ();
59 public object GetValue ()
67 public FieldBuilder DefineMember ()
75 parent_enum.RemoveEnumMember (this.Name);
80 public FieldBuilder DoDefineMember ()
82 object default_value = null;
84 Type UnderlyingType = parent_enum.UnderlyingType;
85 EmitContext ec = parent_enum.EmitContext;
87 default_value = enum_value;
90 Report.Error (30500, Location, "The evaluation of the constant value for `" +
91 parent_enum.Name + "." + Name + "' involves a circular definition.");
96 // So if the above doesn't happen, we have a member that is undefined
97 // We now proceed to define it
99 Expression val = expr;
107 EnumMember em = parent_enum [i];
110 default_value = em.GetValue ();
113 if (default_value == null)
116 default_value = Enum.GetNextDefaultValue (default_value, UnderlyingType);
120 bool old = ec.InEnumContext;
121 ec.InEnumContext = true;
123 val = val.Resolve (ec);
125 ec.InEnumContext = old;
130 if (! Enum.IsValidEnumConstant (val)) {
133 "Type byte, sbyte, short, ushort, int, uint, long, or " +
134 "ulong expected (have: " + val + ")");
140 default_value = c.GetValue ();
142 if (default_value == null) {
143 Enum.Error_ConstantValueCannotBeConverted (c, Location, UnderlyingType);
148 builder = parent_enum.TypeBuilder.DefineField (Name, parent_enum.TypeBuilder, field_attrs);
151 //FXME: ChangeType is not the right thing to do.
152 default_value = TypeManager.ChangeType (default_value, UnderlyingType);
154 Enum.Error_ConstantValueCannotBeConverted (c, Location, UnderlyingType);
158 enum_value = default_value;
160 builder.SetConstant (enum_value);
162 if (!TypeManager.RegisterFieldValue (builder, enum_value))
165 if (OptAttributes != null)
166 OptAttributes.Emit (ec, this);
175 /// Enumeration container
177 public class Enum : DeclSpace {
178 ArrayList ordered_enums;
179 public Expression BaseType;
180 public Type UnderlyingType;
181 ArrayList field_builders;
183 public const int AllowedModifiers =
186 Modifiers.PROTECTED |
190 EmitContext emit_context;
192 public Enum (TypeContainer parent, Expression type, int mod_flags, string name, Attributes attrs, Location l)
193 : base (parent, name, attrs, l)
195 this.BaseType = type;
196 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
197 IsTopLevel ? Modifiers.INTERNAL : Modifiers.PUBLIC, l);
199 ordered_enums = new ArrayList ();
200 field_builders = new ArrayList ();
203 public override AttributeTargets AttributeTargets {
205 return AttributeTargets.Enum;
210 /// Adds @name to the enumeration space, with @expr
211 /// being its definition.
213 public AdditionResult AddEnumMember (string name, Expression expr, Location loc,
214 Attributes opt_attrs)
219 if (defined_names.Contains (name))
220 return AdditionResult.NameExists;
222 index = ordered_enums.Add (name);
223 em = new EnumMember (this, expr, name, loc, opt_attrs, index);
224 DefineName (name, em);
226 return AdditionResult.Success;
229 public void RemoveEnumMember (string name)
231 defined_names.Remove (name);
234 public override TypeBuilder DefineType ()
236 if (TypeBuilder != null)
239 emit_context = new EmitContext (Parent, this, Location, null,
240 UnderlyingType, ModFlags, false);
242 TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel);
244 attr |= TypeAttributes.Class | TypeAttributes.Sealed;
246 UnderlyingType = ResolveType (BaseType, false, Location);
248 if (UnderlyingType != TypeManager.int32_type &&
249 UnderlyingType != TypeManager.uint32_type &&
250 UnderlyingType != TypeManager.int64_type &&
251 UnderlyingType != TypeManager.uint64_type &&
252 UnderlyingType != TypeManager.short_type &&
253 UnderlyingType != TypeManager.ushort_type &&
254 UnderlyingType != TypeManager.byte_type &&
255 UnderlyingType != TypeManager.sbyte_type) {
256 Report.Error (30650, Location,
257 "Type byte, sbyte, short, ushort, int, uint, " +
258 "long, or ulong expected (got: " +
259 TypeManager.MonoBASIC_Name (UnderlyingType) + ")");
264 ModuleBuilder builder = CodeGen.ModuleBuilder;
266 TypeBuilder = builder.DefineType (Name, attr, TypeManager.enum_type);
268 TypeBuilder builder = Parent.TypeBuilder;
270 TypeBuilder = builder.DefineNestedType (
271 Basename, attr, TypeManager.enum_type);
274 TypeBuilder.DefineField ("value__", UnderlyingType,
275 FieldAttributes.Public | FieldAttributes.SpecialName
276 | FieldAttributes.RTSpecialName);
278 TypeManager.AddEnumType (Name, TypeBuilder, this);
283 public static bool IsValidEnumConstant (Expression e)
285 if (!(e is Constant))
288 if (e is IntConstant || e is UIntConstant || e is LongConstant ||
289 e is ByteConstant || e is SByteConstant || e is ShortConstant ||
290 e is UShortConstant || e is ULongConstant || e is EnumConstant)
296 static public object GetNextDefaultValue (object default_value, Type UnderlyingType)
298 if (UnderlyingType == TypeManager.int32_type) {
299 int i = (int) default_value;
301 if (i < System.Int32.MaxValue)
305 } else if (UnderlyingType == TypeManager.uint32_type) {
306 uint i = (uint) default_value;
308 if (i < System.UInt32.MaxValue)
312 } else if (UnderlyingType == TypeManager.int64_type) {
313 long i = (long) default_value;
315 if (i < System.Int64.MaxValue)
319 } else if (UnderlyingType == TypeManager.uint64_type) {
320 ulong i = (ulong) default_value;
322 if (i < System.UInt64.MaxValue)
326 } else if (UnderlyingType == TypeManager.short_type) {
327 short i = (short) default_value;
329 if (i < System.Int16.MaxValue)
333 } else if (UnderlyingType == TypeManager.ushort_type) {
334 ushort i = (ushort) default_value;
336 if (i < System.UInt16.MaxValue)
340 } else if (UnderlyingType == TypeManager.byte_type) {
341 byte i = (byte) default_value;
343 if (i < System.Byte.MaxValue)
347 } else if (UnderlyingType == TypeManager.sbyte_type) {
348 sbyte i = (sbyte) default_value;
350 if (i < System.SByte.MaxValue)
359 public static void Error_ConstantValueCannotBeConverted (object val, Location loc, Type UnderlyingType)
362 Report.Error (30439, loc, "Constant value '" + ((Constant) val).AsString () +
363 "' cannot be converted" +
364 " to a " + TypeManager.MonoBASIC_Name (UnderlyingType));
366 Report.Error (30439, loc, "Constant value '" + val +
367 "' cannot be converted" +
368 " to a " + TypeManager.MonoBASIC_Name (UnderlyingType));
373 /// This is used to lookup the value of an enum member. If the member is undefined,
374 /// it attempts to define it and return its value
376 public object LookupEnumValue (string name)
380 // first check whether the requested name is there
381 // in the member list of enum
389 FieldBuilder fb = em.DefineMember ();
395 if (! field_builders.Contains (fb)) {
396 field_builders.Add (fb);
399 return em.GetValue ();
402 public override bool DefineMembers (TypeContainer parent)
407 public override bool Define (TypeContainer parent)
409 if (TypeBuilder == null)
412 EmitContext ec = new EmitContext (parent, this, Location, null,
413 UnderlyingType, ModFlags, false);
415 foreach (string name in ordered_enums) {
416 EnumMember em = this [name];
417 FieldBuilder fb = em.DefineMember ();
423 if (!field_builders.Contains (fb)) {
424 field_builders.Add (fb);
428 if (OptAttributes != null)
429 OptAttributes.Emit (EmitContext, this);
437 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
438 MemberFilter filter, object criteria)
440 ArrayList members = new ArrayList ();
442 if ((mt & MemberTypes.Field) != 0) {
444 if (criteria is string){
445 LookupEnumValue ((string) criteria);
448 foreach (FieldBuilder fb in field_builders)
449 if (filter (fb, criteria) == true)
453 return new MemberList (members);
456 public override MemberCache MemberCache {
462 public ArrayList ValueNames {
464 return ordered_enums;
469 public EnumMember this [string name] {
471 EnumMember em = (EnumMember) defined_names [name];
476 name = name.ToLower();
477 foreach (string nm in ordered_enums) {
478 if (nm.ToLower() == name) {
479 em = (EnumMember) defined_names [name];
488 public EnumMember this[int mem_index] {
490 string mem_name = (string) ordered_enums [mem_index];;
491 return (EnumMember) defined_names[mem_name];
495 public EmitContext EmitContext {