(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / mcs / const.cs
blobfbab41568ecf0ae6ca93c517a0ccc785b121ad9f
1 //
2 // const.cs: Constant declarations.
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
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 {
22 using System;
23 using System.Reflection;
24 using System.Reflection.Emit;
25 using System.Collections;
27 public class Const : FieldMember {
28 public Expression Expr;
29 EmitContext const_ec;
31 bool resolved = false;
32 object ConstantValue = null;
34 bool in_transit = false;
36 public const int AllowedModifiers =
37 Modifiers.NEW |
38 Modifiers.PUBLIC |
39 Modifiers.PROTECTED |
40 Modifiers.INTERNAL |
41 Modifiers.PRIVATE;
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)
48 Expr = expr;
49 ModFlags |= Modifiers.STATIC;
52 public FieldAttributes FieldAttr {
53 get {
54 return FieldAttributes.Literal | FieldAttributes.Static |
55 Modifiers.FieldAttr (ModFlags) ;
59 #if DEBUG
60 void dump_tree (Type t)
62 Console.WriteLine ("Dumping hierarchy");
63 while (t != null){
64 Console.WriteLine (" " + t.FullName + " " +
65 (t.GetType ().IsEnum ? "yes" : "no"));
66 t = t.BaseType;
69 #endif
71 /// <summary>
72 /// Defines the constant in the @parent
73 /// </summary>
74 public override bool Define ()
76 if (!base.Define ())
77 return false;
79 const_ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
81 Type ttype = MemberType;
82 while (ttype.IsArray)
83 ttype = TypeManager.GetElementType (ttype);
85 if (!TypeManager.IsBuiltinType (ttype) && (!ttype.IsSubclassOf (TypeManager.enum_type)) && !(Expr is NullLiteral)) {
86 Report.Error (
87 -3, Location,
88 "Constant type is not valid (only system types are allowed)");
89 return false;
92 FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, FieldAttr);
94 TypeManager.RegisterConstant (FieldBuilder, this);
96 return true;
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)
106 return expr;
108 bool fail;
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);
116 return null;
119 object constant_value = TypeManager.ChangeType (expr.GetValue (), type, out fail);
120 if (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));
131 Constant retval;
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);
158 else
159 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
161 return retval;
164 /// <summary>
165 /// Looks up the value of a constant field. Defines it if it hasn't
166 /// already been. Similar to LookupEnumValue in spirit.
167 /// </summary>
168 public bool LookupConstantValue (out object value)
170 if (resolved) {
171 value = ConstantValue;
172 return true;
175 if (in_transit) {
176 Report.Error (110, Location,
177 "The evaluation of the constant value for `" +
178 Name + "' involves a circular definition.");
179 value = null;
180 return false;
183 in_transit = true;
184 int errors = Report.Errors;
187 // We might have cleared Expr ourselves in a recursive definition
189 if (Expr == null){
190 value = null;
191 return false;
194 Expr = Expr.Resolve (const_ec);
196 in_transit = false;
198 if (Expr == null) {
199 if (errors == Report.Errors)
200 Report.Error (150, Location, "A constant value is expected");
201 value = null;
202 return false;
205 Expression real_expr = Expr;
207 Constant ce = Expr as Constant;
208 if (ce == null){
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))
214 Expr = un_expr.Expr;
215 else if ((ch_expr != null) && (ch_expr.Expr is Constant))
216 Expr = ch_expr.Expr;
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");
221 } else {
222 if (errors == Report.Errors)
223 Report.Error (150, Location, "A constant value is expected");
224 value = null;
225 return false;
228 ce = Expr as Constant;
231 if (MemberType != real_expr.Type) {
232 ce = ChangeType (Location, ce, MemberType);
233 if (ce == null){
234 value = null;
235 return false;
237 Expr = ce;
239 ConstantValue = ce.GetValue ();
241 if (MemberType.IsEnum){
243 // This sadly does not work for our user-defined enumerations types ;-(
245 try {
246 ConstantValue = System.Enum.ToObject (
247 MemberType, ConstantValue);
248 } catch (ArgumentException){
249 Report.Error (
250 -16, Location,
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;
262 resolved = true;
263 return true;
267 /// <summary>
268 /// Emits the field value by evaluating the expression
269 /// </summary>
270 public override void Emit ()
272 object value;
273 LookupConstantValue (out value);
275 if (OptAttributes != null) {
276 OptAttributes.Emit (const_ec, this);
279 base.Emit ();