2 // const.cs: Constant declarations.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
12 // This is needed because the following situation arises:
14 // The FieldBuilder is declared with the real type for an enumeration
16 // When we attempt to set the value for the constant, the FieldBuilder.SetConstant
17 // function aborts because it requires its argument to be of the same type
20 namespace Mono
.CSharp
{
23 using System
.Reflection
;
24 using System
.Reflection
.Emit
;
25 using System
.Collections
;
27 public class Const
: FieldMember
{
28 public Expression Expr
;
31 bool resolved
= false;
32 object ConstantValue
= null;
34 bool in_transit
= false;
36 public const int AllowedModifiers
=
43 public Const (TypeContainer parent
, Expression constant_type
, string name
,
44 Expression expr
, int mod_flags
, Attributes attrs
, Location loc
)
45 : base (parent
, constant_type
, mod_flags
, AllowedModifiers
,
46 new MemberName (name
), null, attrs
, loc
)
49 ModFlags
|= Modifiers
.STATIC
;
52 public FieldAttributes FieldAttr
{
54 return FieldAttributes
.Literal
| FieldAttributes
.Static
|
55 Modifiers
.FieldAttr (ModFlags
) ;
60 void dump_tree (Type t
)
62 Console
.WriteLine ("Dumping hierarchy");
64 Console
.WriteLine (" " + t
.FullName
+ " " +
65 (t
.GetType ().IsEnum
? "yes" : "no"));
72 /// Defines the constant in the @parent
74 public override bool Define ()
79 const_ec
= new EmitContext (Parent
, Location
, null, MemberType
, ModFlags
);
81 Type ttype
= MemberType
;
83 ttype
= TypeManager
.GetElementType (ttype
);
85 if (!TypeManager
.IsBuiltinType (ttype
) && (!ttype
.IsSubclassOf (TypeManager
.enum_type
)) && !(Expr
is NullLiteral
)) {
88 "Constant type is not valid (only system types are allowed)");
92 FieldBuilder
= Parent
.TypeBuilder
.DefineField (Name
, MemberType
, FieldAttr
);
94 TypeManager
.RegisterConstant (FieldBuilder
, this);
100 // Changes the type of the constant expression `expr' to the Type `type'
101 // Returns null on failure.
103 public static Constant
ChangeType (Location loc
, Constant expr
, Type type
)
105 if (type
== TypeManager
.object_type
)
110 // from the null type to any reference-type.
111 if (expr
is NullLiteral
&& !type
.IsValueType
&& !TypeManager
.IsEnumType (type
))
112 return NullLiteral
.Null
;
114 if (!Convert
.ImplicitStandardConversionExists (Convert
.ConstantEC
, expr
, type
)){
115 Convert
.Error_CannotImplicitConversion (loc
, expr
.Type
, type
);
119 object constant_value
= TypeManager
.ChangeType (expr
.GetValue (), type
, out fail
);
121 Convert
.Error_CannotImplicitConversion (loc
, expr
.Type
, type
);
124 // We should always catch the error before this is ever
125 // reached, by calling Convert.ImplicitStandardConversionExists
127 throw new Exception (
128 String
.Format ("LookupConstantValue: This should never be reached {0} {1}", expr
.Type
, type
));
132 if (type
== TypeManager
.int32_type
)
133 retval
= new IntConstant ((int) constant_value
);
134 else if (type
== TypeManager
.uint32_type
)
135 retval
= new UIntConstant ((uint) constant_value
);
136 else if (type
== TypeManager
.int64_type
)
137 retval
= new LongConstant ((long) constant_value
);
138 else if (type
== TypeManager
.uint64_type
)
139 retval
= new ULongConstant ((ulong) constant_value
);
140 else if (type
== TypeManager
.float_type
)
141 retval
= new FloatConstant ((float) constant_value
);
142 else if (type
== TypeManager
.double_type
)
143 retval
= new DoubleConstant ((double) constant_value
);
144 else if (type
== TypeManager
.string_type
)
145 retval
= new StringConstant ((string) constant_value
);
146 else if (type
== TypeManager
.short_type
)
147 retval
= new ShortConstant ((short) constant_value
);
148 else if (type
== TypeManager
.ushort_type
)
149 retval
= new UShortConstant ((ushort) constant_value
);
150 else if (type
== TypeManager
.sbyte_type
)
151 retval
= new SByteConstant ((sbyte) constant_value
);
152 else if (type
== TypeManager
.byte_type
)
153 retval
= new ByteConstant ((byte) constant_value
);
154 else if (type
== TypeManager
.char_type
)
155 retval
= new CharConstant ((char) constant_value
);
156 else if (type
== TypeManager
.bool_type
)
157 retval
= new BoolConstant ((bool) constant_value
);
159 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type
);
165 /// Looks up the value of a constant field. Defines it if it hasn't
166 /// already been. Similar to LookupEnumValue in spirit.
168 public bool LookupConstantValue (out object value)
171 value = ConstantValue
;
176 Report
.Error (110, Location
,
177 "The evaluation of the constant value for `" +
178 Name
+ "' involves a circular definition.");
184 int errors
= Report
.Errors
;
187 // We might have cleared Expr ourselves in a recursive definition
194 Expr
= Expr
.Resolve (const_ec
);
199 if (errors
== Report
.Errors
)
200 Report
.Error (150, Location
, "A constant value is expected");
205 Expression real_expr
= Expr
;
207 Constant ce
= Expr
as Constant
;
209 UnCheckedExpr un_expr
= Expr
as UnCheckedExpr
;
210 CheckedExpr ch_expr
= Expr
as CheckedExpr
;
211 EmptyCast ec_expr
= Expr
as EmptyCast
;
213 if ((un_expr
!= null) && (un_expr
.Expr
is Constant
))
215 else if ((ch_expr
!= null) && (ch_expr
.Expr
is Constant
))
217 else if ((ec_expr
!= null) && (ec_expr
.Child
is Constant
))
218 Expr
= ec_expr
.Child
;
219 else if (Expr
is ArrayCreation
){
220 Report
.Error (133, Location
, "Arrays can not be constant");
222 if (errors
== Report
.Errors
)
223 Report
.Error (150, Location
, "A constant value is expected");
228 ce
= Expr
as Constant
;
231 if (MemberType
!= real_expr
.Type
) {
232 ce
= ChangeType (Location
, ce
, MemberType
);
239 ConstantValue
= ce
.GetValue ();
241 if (MemberType
.IsEnum
){
243 // This sadly does not work for our user-defined enumerations types ;-(
246 ConstantValue
= System
.Enum
.ToObject (
247 MemberType
, ConstantValue
);
248 } catch (ArgumentException
){
251 ".NET SDK 1.0 does not permit to create the constant "+
252 " field from a user-defined enumeration");
256 FieldBuilder
.SetConstant (ConstantValue
);
258 if (!TypeManager
.RegisterFieldValue (FieldBuilder
, ConstantValue
))
259 throw new Exception ("Cannot register const value");
261 value = ConstantValue
;
268 /// Emits the field value by evaluating the expression
270 public override void Emit ()
273 LookupConstantValue (out value);
275 if (OptAttributes
!= null) {
276 OptAttributes
.Emit (const_ec
, this);