2002-05-31 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / const.cs
1 //\r
2 // const.cs: Constant declarations.\r
3 //\r
4 // Author:\r
5 //   Miguel de Icaza (miguel@ximian.com)\r
6 //\r
7 // (C) 2001 Ximian, Inc.\r
8 //\r
9 //\r
10 \r
11 //\r
12 // This is needed because the following situation arises:\r
13 //\r
14 //     The FieldBuilder is declared with the real type for an enumeration\r
15 //\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
18 //\r
19 \r
20 namespace Mono.CSharp {\r
21 \r
22         using System;\r
23         using System.Reflection;\r
24         using System.Reflection.Emit;\r
25         using System.Collections;\r
26 \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
32 \r
33                 object ConstantValue = null;\r
34                 Type type;\r
35 \r
36                 public const int AllowedModifiers =\r
37                         Modifiers.NEW |\r
38                         Modifiers.PUBLIC |\r
39                         Modifiers.PROTECTED |\r
40                         Modifiers.INTERNAL |\r
41                         Modifiers.PRIVATE;\r
42 \r
43                 public Const (string constant_type, string name, Expression expr, int mod_flags,\r
44                               Attributes attrs, Location loc)\r
45                         : base (name, loc)\r
46                 {\r
47                         ConstantType = constant_type;\r
48                         Name = name;\r
49                         Expr = expr;\r
50                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);\r
51                         OptAttributes = attrs;\r
52                 }\r
53 \r
54                 public FieldAttributes FieldAttr {\r
55                         get {\r
56                                 return FieldAttributes.Literal | FieldAttributes.Static |\r
57                                         Modifiers.FieldAttr (ModFlags) ;\r
58                         }\r
59                 }\r
60 \r
61 #if DEBUG\r
62                 void dump_tree (Type t)\r
63                 {\r
64                         Console.WriteLine ("Dumping hierarchy");\r
65                         while (t != null){\r
66                                 Console.WriteLine ("   " + t.FullName + " " +\r
67                                         (t.GetType ().IsEnum ? "yes" : "no"));\r
68                                 t = t.BaseType;\r
69                         }\r
70                 }\r
71 #endif\r
72 \r
73                 /// <summary>\r
74                 ///   Defines the constant in the @parent\r
75                 /// </summary>\r
76                 public override bool Define (TypeContainer parent)\r
77                 {\r
78                         type = RootContext.LookupType (parent, ConstantType, true, Location);\r
79 \r
80                         if (type == null)\r
81                                 return false;\r
82 \r
83                         if (!TypeManager.IsBuiltinType (type) &&\r
84                             (!type.IsSubclassOf (TypeManager.enum_type))) {\r
85                                 Report.Error (\r
86                                         -3, Location,\r
87                                         "Constant type is not valid (only system types are allowed)");\r
88                                 return false;\r
89                         }\r
90 \r
91                         Type ptype = parent.TypeBuilder.BaseType;\r
92 \r
93                         if (ptype != null) {\r
94                                 MemberInfo [] mi = TypeContainer.FindMembers (\r
95                                         ptype, MemberTypes.Field, BindingFlags.Public,\r
96                                         Type.FilterName, Name);\r
97                                 \r
98                                 if (mi == null || mi.Length == 0)\r
99                                         if ((ModFlags & Modifiers.NEW) != 0)\r
100                                                 WarningNotHiding (parent);\r
101 \r
102                         } else if ((ModFlags & Modifiers.NEW) != 0)\r
103                                 WarningNotHiding (parent);\r
104 \r
105                         FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);\r
106 \r
107                         TypeManager.RegisterConstant (FieldBuilder, this);\r
108 \r
109                         return true;\r
110                 }\r
111 \r
112                 /// <summary>\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
115                 /// </summary>\r
116                 public object LookupConstantValue (EmitContext ec)\r
117                 {\r
118                         if (ConstantValue != null)\r
119                                 return ConstantValue;\r
120                         \r
121                         Expr = Expr.Resolve (ec);\r
122 \r
123                         if (Expr == null) {\r
124                                 Report.Error (150, Location, "A constant value is expected");\r
125                                 return null;\r
126                         }\r
127 \r
128                         if (!(Expr is Constant)) {\r
129                                 Report.Error (150, Location, "A constant value is expected");\r
130                                 return null;\r
131                         }\r
132 \r
133                         ConstantValue = ((Constant) Expr).GetValue ();\r
134 \r
135                         if (type.IsEnum){\r
136                                 //\r
137                                 // This sadly does not work for our user-defined enumerations types ;-(\r
138                                 //\r
139                                 try {\r
140                                         ConstantValue = System.Enum.ToObject (\r
141                                                 type, ConstantValue);\r
142                                 } catch (ArgumentException){\r
143                                         Report.Error (\r
144                                                 -16, Location,\r
145                                                 ".NET SDK 1.0 does not permit to create the constant "+\r
146                                                 " field from a user-defined enumeration");\r
147                                 }\r
148                         }\r
149 \r
150                         FieldBuilder.SetConstant (ConstantValue);\r
151 \r
152                         if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))\r
153                                 return null;\r
154 \r
155                         return ConstantValue;\r
156                 }\r
157                 \r
158                 \r
159                 /// <summary>\r
160                 ///  Emits the field value by evaluating the expression\r
161                 /// </summary>\r
162                 public void EmitConstant (TypeContainer parent)\r
163                 {\r
164                         EmitContext ec = new EmitContext (parent, Location, null, type, ModFlags);\r
165                         LookupConstantValue (ec);\r
166                         \r
167                         return;\r
168                 }\r
169         }\r
170 }\r
171 \r
172 \r