2 // enum.cs: Enum handling.
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Ravi Pratap (ravi@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 using System
.Collections
;
15 using System
.Collections
.Specialized
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Globalization
;
20 namespace Mono
.CSharp
{
22 public class EnumMember
: Const
{
23 protected readonly Enum ParentEnum
;
24 protected readonly Expression ValueExpr
;
25 readonly EnumMember prev_member
;
27 public EnumMember (Enum parent
, EnumMember prev_member
, string name
, Expression expr
,
28 Attributes attrs
, Location loc
)
29 : base (parent
, new EnumTypeExpr (parent
), name
, expr
, Modifiers
.PUBLIC
,
32 this.ParentEnum
= parent
;
33 this.ValueExpr
= expr
;
34 this.prev_member
= prev_member
;
37 protected class EnumTypeExpr
: TypeExpr
39 public readonly Enum Enum
;
41 public EnumTypeExpr (Enum e
)
46 protected override TypeExpr
DoResolveAsTypeStep (IResolveContext ec
)
48 type
= Enum
.CurrentType
!= null ? Enum
.CurrentType
: Enum
.TypeBuilder
;
52 public override TypeExpr
ResolveAsTypeTerminal (IResolveContext ec
, bool silent
)
54 return DoResolveAsTypeStep (ec
);
57 public override string Name
{
58 get { return Enum.Name; }
61 public override string FullName
{
62 get { return Enum.Name; }
66 static bool IsValidEnumType (Type t
)
68 return (t
== TypeManager
.int32_type
|| t
== TypeManager
.uint32_type
|| t
== TypeManager
.int64_type
||
69 t
== TypeManager
.byte_type
|| t
== TypeManager
.sbyte_type
|| t
== TypeManager
.short_type
||
70 t
== TypeManager
.ushort_type
|| t
== TypeManager
.uint64_type
|| t
== TypeManager
.char_type
||
75 get { return value.GetValue (); }
78 public override bool Define ()
80 const FieldAttributes attr
= FieldAttributes
.Public
| FieldAttributes
.Static
| FieldAttributes
.Literal
;
81 FieldBuilder
= Parent
.TypeBuilder
.DefineField (Name
, MemberType
, attr
);
82 TypeManager
.RegisterConstant (FieldBuilder
, this);
86 protected override Constant
DoResolveValue (EmitContext ec
)
88 if (ValueExpr
!= null) {
89 Constant c
= ValueExpr
.ResolveAsConstant (ec
, this);
93 if (c
is EnumConstant
)
94 c
= ((EnumConstant
)c
).Child
;
96 c
= c
.ImplicitConversionRequired (ParentEnum
.UnderlyingType
, Location
);
100 if (!IsValidEnumType (c
.Type
)) {
101 Enum
.Error_1008 (Location
);
105 return new EnumConstant (c
, MemberType
);
108 if (prev_member
== null) {
109 return new EnumConstant (
110 New
.Constantify (ParentEnum
.UnderlyingType
), MemberType
);
113 if (!prev_member
.ResolveValue ()) {
114 prev_member
.value = new EnumConstant (
115 New
.Constantify (ParentEnum
.UnderlyingType
), MemberType
);
120 return (EnumConstant
) prev_member
.value.Increment ();
121 } catch (OverflowException
) {
122 Report
.Error (543, Location
, "The enumerator value `{0}' is too " +
123 "large to fit in its type `{1}'", GetSignatureForError (),
124 TypeManager
.CSharpName (ParentEnum
.UnderlyingType
));
131 /// Enumeration container
133 public class Enum
: TypeContainer
135 Expression base_type
;
137 public Type UnderlyingType
;
139 public const int AllowedModifiers
=
142 Modifiers
.PROTECTED
|
146 public Enum (NamespaceEntry ns
, DeclSpace parent
, Expression type
,
147 int mod_flags
, MemberName name
, Attributes attrs
)
148 : base (ns
, parent
, name
, attrs
, Kind
.Enum
)
150 this.base_type
= type
;
151 int accmods
= IsTopLevel
? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
152 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
, accmods
, Location
);
155 public void AddEnumMember (EnumMember em
)
157 if (em
.Name
== "value__") {
158 Report
.Error (76, em
.Location
, "An item in an enumeration cannot " +
159 "have an identifier `value__'");
166 public static void Error_1008 (Location loc
)
168 Report
.Error (1008, loc
, "Type byte, sbyte, short, ushort, " +
169 "int, uint, long or ulong expected");
172 protected override bool DefineNestedTypes ()
174 if (!base.DefineNestedTypes ())
177 if (!(base_type
is TypeLookupExpression
)) {
178 Error_1008 (Location
);
182 TypeExpr ute
= base_type
.ResolveAsTypeTerminal (this, false);
183 UnderlyingType
= ute
.Type
;
185 if (UnderlyingType
!= TypeManager
.int32_type
&&
186 UnderlyingType
!= TypeManager
.uint32_type
&&
187 UnderlyingType
!= TypeManager
.int64_type
&&
188 UnderlyingType
!= TypeManager
.uint64_type
&&
189 UnderlyingType
!= TypeManager
.short_type
&&
190 UnderlyingType
!= TypeManager
.ushort_type
&&
191 UnderlyingType
!= TypeManager
.byte_type
&&
192 UnderlyingType
!= TypeManager
.sbyte_type
) {
193 Error_1008 (Location
);
198 // Call MapToInternalType for corlib
200 TypeBuilder
.DefineField ("value__", UnderlyingType
,
201 FieldAttributes
.Public
| FieldAttributes
.SpecialName
202 | FieldAttributes
.RTSpecialName
);
208 // Used for error reporting only
210 public EnumMember
GetDefinition (object value)
212 foreach (EnumMember e
in defined_names
.Values
) {
213 if (e
.Value
.Equals (value))
217 throw new ArgumentOutOfRangeException (value.ToString ());
220 protected override bool VerifyClsCompliance ()
222 if (!base.VerifyClsCompliance ())
225 if (UnderlyingType
== TypeManager
.uint32_type
||
226 UnderlyingType
== TypeManager
.uint64_type
||
227 UnderlyingType
== TypeManager
.ushort_type
) {
228 Report
.Error (3009, Location
, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager
.CSharpName (UnderlyingType
));
234 public override AttributeTargets AttributeTargets
{
236 return AttributeTargets
.Enum
;
240 protected override TypeAttributes TypeAttr
{
242 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
243 TypeAttributes
.Class
| TypeAttributes
.Sealed
| base.TypeAttr
;