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 readonly string ConstantType;
29 public Expression Expr;
30 public Attributes OptAttributes;
31 public FieldBuilder FieldBuilder;
33 object ConstantValue = null;
36 public const int AllowedModifiers =
43 public Const (string constant_type, string name, Expression expr, int mod_flags,
44 Attributes attrs, Location loc)
47 ConstantType = constant_type;
50 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
51 OptAttributes = attrs;
54 public FieldAttributes FieldAttr {
56 return FieldAttributes.Literal | FieldAttributes.Static |
57 Modifiers.FieldAttr (ModFlags) ;
62 void dump_tree (Type t)
64 Console.WriteLine ("Dumping hierarchy");
66 Console.WriteLine (" " + t.FullName + " " +
67 (t.GetType ().IsEnum ? "yes" : "no"));
74 /// Defines the constant in the @parent
76 public override bool Define (TypeContainer parent)
78 type = RootContext.LookupType (parent, ConstantType, true, Location);
83 if (!TypeManager.IsBuiltinType (type) &&
84 (!type.IsSubclassOf (TypeManager.enum_type))) {
87 "Constant type is not valid (only system types are allowed)");
91 Type ptype = parent.TypeBuilder.BaseType;
94 MemberInfo [] mi = TypeContainer.FindMembers (
95 ptype, MemberTypes.Field, BindingFlags.Public,
96 Type.FilterName, Name);
98 if (mi == null || mi.Length == 0)
99 if ((ModFlags & Modifiers.NEW) != 0)
100 WarningNotHiding (parent);
102 } else if ((ModFlags & Modifiers.NEW) != 0)
103 WarningNotHiding (parent);
105 FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
107 TypeManager.RegisterConstant (FieldBuilder, this);
113 /// Looks up the value of a constant field. Defines it if it hasn't
114 /// already been. Similar to LookupEnumValue in spirit.
116 public object LookupConstantValue (EmitContext ec)
118 if (ConstantValue != null)
119 return ConstantValue;
121 Expr = Expr.Resolve (ec);
124 Report.Error (150, Location, "A constant value is expected");
128 if (!(Expr is Constant)) {
129 Report.Error (150, Location, "A constant value is expected");
133 ConstantValue = ((Constant) Expr).GetValue ();
135 if (type != Expr.Type) {
137 ConstantValue = TypeManager.ChangeType (ConstantValue, type);
139 Expression.Error_CannotConvertImplicit (Location, Expr.Type, type);
143 if (type == TypeManager.int32_type)
144 Expr = new IntConstant ((int) ConstantValue);
145 else if (type == TypeManager.uint32_type)
146 Expr = new UIntConstant ((uint) ConstantValue);
147 else if (type == TypeManager.int64_type)
148 Expr = new LongConstant ((long) ConstantValue);
149 else if (type == TypeManager.uint64_type)
150 Expr = new ULongConstant ((ulong) ConstantValue);
151 else if (type == TypeManager.float_type)
152 Expr = new FloatConstant ((float) ConstantValue);
153 else if (type == TypeManager.double_type)
154 Expr = new DoubleConstant ((double) ConstantValue);
155 else if (type == TypeManager.string_type)
156 Expr = new StringConstant ((string) ConstantValue);
157 else if (type == TypeManager.short_type)
158 Expr = new ShortConstant ((short) ConstantValue);
159 else if (type == TypeManager.ushort_type)
160 Expr = new UShortConstant ((ushort) ConstantValue);
161 else if (type == TypeManager.sbyte_type)
162 Expr = new SByteConstant ((sbyte) ConstantValue);
163 else if (type == TypeManager.byte_type)
164 Expr = new ByteConstant ((byte) ConstantValue);
165 else if (type == TypeManager.char_type)
166 Expr = new CharConstant ((char) ConstantValue);
167 else if (type == TypeManager.bool_type)
168 Expr = new BoolConstant ((bool) ConstantValue);
173 // This sadly does not work for our user-defined enumerations types ;-(
176 ConstantValue = System.Enum.ToObject (
177 type, ConstantValue);
178 } catch (ArgumentException){
181 ".NET SDK 1.0 does not permit to create the constant "+
182 " field from a user-defined enumeration");
186 FieldBuilder.SetConstant (ConstantValue);
188 if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
191 return ConstantValue;
196 /// Emits the field value by evaluating the expression
198 public void EmitConstant (TypeContainer parent)
200 EmitContext ec = new EmitContext (parent, Location, null, type, ModFlags);
201 LookupConstantValue (ec);