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 : FieldBase {
28 public Expression Expr;
31 object ConstantValue = null;
34 bool in_transit = false;
36 public const int AllowedModifiers =
43 public Const (Expression constant_type, string name, Expression expr,
44 int mod_flags, Attributes attrs, Location loc)
45 : base (constant_type, mod_flags, AllowedModifiers,
46 new MemberName (name), null, attrs, loc)
51 public FieldAttributes FieldAttr {
53 return FieldAttributes.Literal | FieldAttributes.Static |
54 Modifiers.FieldAttr (ModFlags) ;
59 void dump_tree (Type t)
61 Console.WriteLine ("Dumping hierarchy");
63 Console.WriteLine (" " + t.FullName + " " +
64 (t.GetType ().IsEnum ? "yes" : "no"));
71 /// Defines the constant in the @parent
73 public override bool Define (TypeContainer parent)
75 type = parent.ResolveType (Type, false, Location);
80 const_ec = new EmitContext (parent, Location, null, type, ModFlags);
84 ttype = TypeManager.GetElementType (ttype);
86 if (!TypeManager.IsBuiltinType (ttype) &&
87 (!ttype.IsSubclassOf (TypeManager.enum_type))) {
90 "Constant type is not valid (only system types are allowed)");
94 Type ptype = parent.TypeBuilder.BaseType;
97 MemberList list = TypeContainer.FindMembers (
98 ptype, MemberTypes.Field, BindingFlags.Public,
99 System.Type.FilterName, Name);
102 if ((ModFlags & Modifiers.NEW) != 0)
103 WarningNotHiding (parent);
105 } else if ((ModFlags & Modifiers.NEW) != 0)
106 WarningNotHiding (parent);
108 FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
110 TypeManager.RegisterConstant (FieldBuilder, this);
116 // Changes the type of the constant expression `expr' to the Type `type'
117 // Returns null on failure.
119 public static Constant ChangeType (Location loc, Constant expr, Type type)
123 // from the null type to any reference-type.
124 if (expr is NullLiteral && !type.IsValueType && !TypeManager.IsEnumType (type))
125 return NullLiteral.Null;
127 if (!Convert.ImplicitStandardConversionExists (expr, type)){
128 Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
132 object constant_value = TypeManager.ChangeType (expr.GetValue (), type, out fail);
134 Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
137 // We should always catch the error before this is ever
138 // reached, by calling Convert.ImplicitStandardConversionExists
140 throw new Exception (
141 String.Format ("LookupConstantValue: This should never be reached {0} {1}", expr.Type, type));
145 if (type == TypeManager.int32_type)
146 retval = new IntConstant ((int) constant_value);
147 else if (type == TypeManager.uint32_type)
148 retval = new UIntConstant ((uint) constant_value);
149 else if (type == TypeManager.int64_type)
150 retval = new LongConstant ((long) constant_value);
151 else if (type == TypeManager.uint64_type)
152 retval = new ULongConstant ((ulong) constant_value);
153 else if (type == TypeManager.float_type)
154 retval = new FloatConstant ((float) constant_value);
155 else if (type == TypeManager.double_type)
156 retval = new DoubleConstant ((double) constant_value);
157 else if (type == TypeManager.string_type)
158 retval = new StringConstant ((string) constant_value);
159 else if (type == TypeManager.short_type)
160 retval = new ShortConstant ((short) constant_value);
161 else if (type == TypeManager.ushort_type)
162 retval = new UShortConstant ((ushort) constant_value);
163 else if (type == TypeManager.sbyte_type)
164 retval = new SByteConstant ((sbyte) constant_value);
165 else if (type == TypeManager.byte_type)
166 retval = new ByteConstant ((byte) constant_value);
167 else if (type == TypeManager.char_type)
168 retval = new CharConstant ((char) constant_value);
169 else if (type == TypeManager.bool_type)
170 retval = new BoolConstant ((bool) constant_value);
172 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
178 /// Looks up the value of a constant field. Defines it if it hasn't
179 /// already been. Similar to LookupEnumValue in spirit.
181 public object LookupConstantValue ()
183 if (ConstantValue != null)
184 return ConstantValue;
187 Report.Error (110, Location,
188 "The evaluation of the constant value for `" +
189 Name + "' involves a circular definition.");
194 int errors = Report.Errors;
197 // We might have cleared Expr ourselves in a recursive definition
202 Expr = Expr.Resolve (const_ec);
207 if (errors == Report.Errors)
208 Report.Error (150, Location, "A constant value is expected");
212 Constant ce = Expr as Constant;
214 UnCheckedExpr un_expr = Expr as UnCheckedExpr;
215 CheckedExpr ch_expr = Expr as CheckedExpr;
217 if ((un_expr != null) && (un_expr.Expr is Constant))
219 else if ((ch_expr != null) && (ch_expr.Expr is Constant))
221 else if (Expr is ArrayCreation) {
222 ArrayCreation ac = (ArrayCreation) Expr;
224 Expr = ac.TurnIntoConstant ();
226 Report.Error (150, Location, "A constant value is expected");
230 if (errors == Report.Errors)
231 Report.Error (150, Location, "A constant value is expected");
236 if (type != ce.Type) {
237 ce = ChangeType (Location, ce, type);
242 ConstantValue = ce.GetValue ();
246 // This sadly does not work for our user-defined enumerations types ;-(
249 ConstantValue = System.Enum.ToObject (
250 type, ConstantValue);
251 } catch (ArgumentException){
254 ".NET SDK 1.0 does not permit to create the constant "+
255 " field from a user-defined enumeration");
259 FieldBuilder.SetConstant (ConstantValue);
261 if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
264 return ConstantValue;
269 /// Emits the field value by evaluating the expression
271 public void Emit (TypeContainer parent)
273 LookupConstantValue ();