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 : MemberCore {
28 public Expression ConstantType;
29 public Expression Expr;
30 public Attributes OptAttributes;
31 public FieldBuilder FieldBuilder;
34 object ConstantValue = null;
37 bool in_transit = false;
39 public const int AllowedModifiers =
46 public Const (Expression constant_type, string name, Expression expr, int mod_flags,
47 Attributes attrs, Location loc)
50 ConstantType = constant_type;
53 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
54 OptAttributes = attrs;
57 public FieldAttributes FieldAttr {
59 return FieldAttributes.Literal | FieldAttributes.Static |
60 Modifiers.FieldAttr (ModFlags) ;
65 void dump_tree (Type t)
67 Console.WriteLine ("Dumping hierarchy");
69 Console.WriteLine (" " + t.FullName + " " +
70 (t.GetType ().IsEnum ? "yes" : "no"));
77 /// Defines the constant in the @parent
79 public override bool Define (TypeContainer parent)
81 type = parent.ResolveType (ConstantType, false, Location);
86 const_ec = new EmitContext (parent, Location, null, type, ModFlags);
88 if (!TypeManager.IsBuiltinType (type) &&
89 (!type.IsSubclassOf (TypeManager.enum_type))) {
92 "Constant type is not valid (only system types are allowed)");
96 Type ptype = parent.TypeBuilder.BaseType;
99 MemberList list = TypeContainer.FindMembers (
100 ptype, MemberTypes.Field, BindingFlags.Public,
101 Type.FilterName, Name);
104 if ((ModFlags & Modifiers.NEW) != 0)
105 WarningNotHiding (parent);
107 } else if ((ModFlags & Modifiers.NEW) != 0)
108 WarningNotHiding (parent);
110 FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
112 TypeManager.RegisterConstant (FieldBuilder, this);
118 /// Looks up the value of a constant field. Defines it if it hasn't
119 /// already been. Similar to LookupEnumValue in spirit.
121 public object LookupConstantValue ()
123 if (ConstantValue != null)
124 return ConstantValue;
127 Report.Error (110, Location,
128 "The evaluation of the constant value for `" +
129 Name + "' involves a circular definition.");
134 int errors = Report.Errors;
136 Expr = Expr.Resolve (const_ec);
141 if (errors == Report.Errors)
142 Report.Error (150, Location, "A constant value is expected");
146 if (!(Expr is Constant)) {
147 UnCheckedExpr un_expr = Expr as UnCheckedExpr;
148 CheckedExpr ch_expr = Expr as CheckedExpr;
150 if ((un_expr != null) && (un_expr.Expr is Constant))
152 else if ((ch_expr != null) && (ch_expr.Expr is Constant))
155 if (errors == Report.Errors)
156 Report.Error (150, Location, "A constant value is expected");
161 ConstantValue = ((Constant) Expr).GetValue ();
163 if (type != Expr.Type) {
166 // from the null type to any reference-type.
167 if (Expr is NullLiteral && !type.IsValueType &&
168 !TypeManager.IsEnumType (type)){
169 return NullLiteral.Null;
172 ConstantValue = TypeManager.ChangeType (ConstantValue, type, out fail);
174 Convert.Error_CannotImplicitConversion (Location, Expr.Type, type);
178 if (type == TypeManager.int32_type)
179 Expr = new IntConstant ((int) ConstantValue);
180 else if (type == TypeManager.uint32_type)
181 Expr = new UIntConstant ((uint) ConstantValue);
182 else if (type == TypeManager.int64_type)
183 Expr = new LongConstant ((long) ConstantValue);
184 else if (type == TypeManager.uint64_type)
185 Expr = new ULongConstant ((ulong) ConstantValue);
186 else if (type == TypeManager.float_type)
187 Expr = new FloatConstant ((float) ConstantValue);
188 else if (type == TypeManager.double_type)
189 Expr = new DoubleConstant ((double) ConstantValue);
190 else if (type == TypeManager.string_type)
191 Expr = new StringConstant ((string) ConstantValue);
192 else if (type == TypeManager.short_type)
193 Expr = new ShortConstant ((short) ConstantValue);
194 else if (type == TypeManager.ushort_type)
195 Expr = new UShortConstant ((ushort) ConstantValue);
196 else if (type == TypeManager.sbyte_type)
197 Expr = new SByteConstant ((sbyte) ConstantValue);
198 else if (type == TypeManager.byte_type)
199 Expr = new ByteConstant ((byte) ConstantValue);
200 else if (type == TypeManager.char_type)
201 Expr = new CharConstant ((char) ConstantValue);
202 else if (type == TypeManager.bool_type)
203 Expr = new BoolConstant ((bool) ConstantValue);
208 // This sadly does not work for our user-defined enumerations types ;-(
211 ConstantValue = System.Enum.ToObject (
212 type, ConstantValue);
213 } catch (ArgumentException){
216 ".NET SDK 1.0 does not permit to create the constant "+
217 " field from a user-defined enumeration");
221 FieldBuilder.SetConstant (ConstantValue);
223 if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
226 return ConstantValue;
231 /// Emits the field value by evaluating the expression
233 public void EmitConstant (TypeContainer parent)
235 LookupConstantValue ();