2 // const.cs: Constant declarations.
\r
5 // Miguel de Icaza (miguel@ximian.com)
\r
7 // (C) 2001 Ximian, Inc.
\r
12 // This is needed because the following situation arises:
\r
14 // The FieldBuilder is declared with the real type for an enumeration
\r
16 // When we attempt to set the value for the constant, the FieldBuilder.SetConstant
\r
17 // function aborts because it requires its argument to be of the same type
\r
20 namespace Mono.CSharp {
\r
23 using System.Reflection;
\r
24 using System.Reflection.Emit;
\r
25 using System.Collections;
\r
27 public class Const : MemberCore {
\r
28 public readonly string ConstantType;
\r
29 public Expression Expr;
\r
30 public Attributes OptAttributes;
\r
31 public FieldBuilder FieldBuilder;
\r
33 object ConstantValue = null;
\r
36 public const int AllowedModifiers =
\r
39 Modifiers.PROTECTED |
\r
40 Modifiers.INTERNAL |
\r
43 public Const (string constant_type, string name, Expression expr, int mod_flags,
\r
44 Attributes attrs, Location loc)
\r
47 ConstantType = constant_type;
\r
50 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
\r
51 OptAttributes = attrs;
\r
54 public FieldAttributes FieldAttr {
\r
56 return FieldAttributes.Literal | FieldAttributes.Static |
\r
57 Modifiers.FieldAttr (ModFlags) ;
\r
62 void dump_tree (Type t)
\r
64 Console.WriteLine ("Dumping hierarchy");
\r
66 Console.WriteLine (" " + t.FullName + " " +
\r
67 (t.GetType ().IsEnum ? "yes" : "no"));
\r
74 /// Defines the constant in the @parent
\r
76 public override bool Define (TypeContainer parent)
\r
78 type = RootContext.LookupType (parent, ConstantType, true, Location);
\r
83 if (!TypeManager.IsBuiltinType (type) &&
\r
84 (!type.IsSubclassOf (TypeManager.enum_type))) {
\r
87 "Constant type is not valid (only system types are allowed)");
\r
91 Type ptype = parent.TypeBuilder.BaseType;
\r
93 if (ptype != null) {
\r
94 MemberInfo [] mi = TypeContainer.FindMembers (
\r
95 ptype, MemberTypes.Field, BindingFlags.Public,
\r
96 Type.FilterName, Name);
\r
98 if (mi == null || mi.Length == 0)
\r
99 if ((ModFlags & Modifiers.NEW) != 0)
\r
100 WarningNotHiding (parent);
\r
102 } else if ((ModFlags & Modifiers.NEW) != 0)
\r
103 WarningNotHiding (parent);
\r
105 FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
\r
107 TypeManager.RegisterConstant (FieldBuilder, this);
\r
113 /// Looks up the value of a constant field. Defines it if it hasn't
\r
114 /// already been. Similar to LookupEnumValue in spirit.
\r
116 public object LookupConstantValue (EmitContext ec)
\r
118 if (ConstantValue != null)
\r
119 return ConstantValue;
\r
121 Expr = Expr.Resolve (ec);
\r
123 if (Expr == null) {
\r
124 Report.Error (150, Location, "A constant value is expected");
\r
128 if (!(Expr is Constant)) {
\r
129 Report.Error (150, Location, "A constant value is expected");
\r
133 ConstantValue = ((Constant) Expr).GetValue ();
\r
137 // This sadly does not work for our user-defined enumerations types ;-(
\r
140 ConstantValue = System.Enum.ToObject (
\r
141 type, ConstantValue);
\r
142 } catch (ArgumentException){
\r
145 ".NET SDK 1.0 does not permit to create the constant "+
\r
146 " field from a user-defined enumeration");
\r
150 FieldBuilder.SetConstant (ConstantValue);
\r
152 if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
\r
155 return ConstantValue;
\r
160 /// Emits the field value by evaluating the expression
\r
162 public void EmitConstant (TypeContainer parent)
\r
164 EmitContext ec = new EmitContext (parent, Location, null, type, ModFlags);
\r
165 LookupConstantValue (ec);
\r