**** Merged from MCS ****
[mono-project.git] / mcs / mbas / const.cs
blob09282a89d9dc61b2bae309b39a44477773a03145
1 //
2 // const.cs: Constant declarations.
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
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.MonoBASIC {
23 using System;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Collections;
28 public class Const : MemberCore {
29 public Expression ConstantType;
30 public Expression Expr;
31 public FieldBuilder FieldBuilder;
33 object ConstantValue = null;
34 Type type;
36 bool in_transit = false;
38 public const int AllowedModifiers =
39 Modifiers.PUBLIC |
40 Modifiers.PROTECTED |
41 Modifiers.INTERNAL |
42 Modifiers.PRIVATE |
43 Modifiers.SHADOWS;
45 public Const (Expression constant_type, string name, Expression expr, int mod_flags,
46 Attributes attrs, Location loc)
47 : base (name, attrs, loc)
49 ConstantType = constant_type;
50 Name = name;
51 Expr = expr;
52 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
55 public override AttributeTargets AttributeTargets {
56 get {
57 return AttributeTargets.Field;
61 public FieldAttributes FieldAttr {
62 get {
63 return FieldAttributes.Literal | FieldAttributes.Static |
64 Modifiers.FieldAttr (ModFlags) ;
68 #if DEBUG
69 void dump_tree (Type t)
71 Console.WriteLine ("Dumping hierarchy");
72 while (t != null){
73 Console.WriteLine (" " + t.FullName + " " +
74 (t.GetType ().IsEnum ? "yes" : "no"));
75 t = t.BaseType;
78 #endif
80 /// <summary>
81 /// Defines the constant in the @parent
82 /// </summary>
83 public override bool Define (TypeContainer parent)
85 type = parent.ResolveType (ConstantType, false, Location);
87 if (type == null)
88 return false;
90 if (!TypeManager.IsBuiltinType (type) &&
91 (!type.IsSubclassOf (TypeManager.enum_type))) {
92 Report.Error (
93 30424, Location,
94 "Constant type is not valid (only system types are allowed)");
95 return false;
98 // if no type is declared expicitely
99 // set the expression type as the type of constant
100 if (type == TypeManager.object_type){
101 if (Expr is IntLiteral)
102 type = TypeManager.int32_type;
103 else if (Expr is UIntLiteral)
104 type = TypeManager.uint32_type;
105 else if (Expr is LongLiteral)
106 type = TypeManager.int64_type;
107 else if (Expr is ULongLiteral)
108 type = TypeManager.uint64_type;
109 else if (Expr is FloatLiteral)
110 type = TypeManager.float_type;
111 else if (Expr is DoubleLiteral)
112 type = TypeManager.double_type;
113 else if (Expr is StringLiteral)
114 type = TypeManager.string_type;
115 else if (Expr is ShortLiteral)
116 type = TypeManager.short_type;
117 else if (Expr is UShortConstant)
118 type = TypeManager.ushort_type;
119 else if (Expr is SByteConstant)
120 type = TypeManager.sbyte_type;
121 else if (Expr is ByteConstant)
122 type = TypeManager.byte_type;
123 else if (Expr is CharConstant)
124 type = TypeManager.char_type;
125 else if (Expr is BoolConstant)
126 type = TypeManager.bool_type;
127 else if (Expr is DateConstant)
128 type = TypeManager.date_type;
130 Type ptype = parent.TypeBuilder.BaseType;
132 if (ptype != null) {
133 MemberList list = TypeContainer.FindMembers (
134 ptype, MemberTypes.Field, BindingFlags.Public,
135 Type.FilterName, Name);
137 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
138 Report.Warning (
139 40004, 2, Location,
140 "Const '" + Name + "' should be declared " +
141 "Shadows since the base type '" + ptype.Name +
142 "' has a Const with same name");
143 if (list.Count == 0) {
144 // if a member of module is not inherited from Object class
145 // can not be declared protected
146 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
147 Report.Error (30593, Location,
148 "'Const' inside a 'Module' can not be " +
149 "declared as 'Protected'");
151 /*if ((ModFlags & Modifiers.NEW) != 0)
152 WarningNotHiding (parent);*/
155 /*else if ((ModFlags & Modifiers.NEW) != 0)
156 WarningNotHiding (parent);*/
158 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
159 Report.Error (30435, Location,
160 "'Const' inside a 'Structure' can not be " +
161 "declared as 'Protected'");
163 FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
165 TypeManager.RegisterConstant (FieldBuilder, this);
167 return true;
170 /// <summary>
171 /// Looks up the value of a constant field. Defines it if it hasn't
172 /// already been. Similar to LookupEnumValue in spirit.
173 /// </summary>
174 public object LookupConstantValue (EmitContext ec)
176 if (ConstantValue != null)
177 return ConstantValue;
179 if (in_transit) {
180 Report.Error (110, Location,
181 "The evaluation of the constant value for `" +
182 Name + "' involves a circular definition.");
183 return null;
186 in_transit = true;
187 int errors = Report.Errors;
189 Expr = Expr.Resolve (ec);
191 in_transit = false;
193 if (Expr == null) {
194 if (errors == Report.Errors)
195 Report.Error (30059, Location, "A constant value is expected");
196 return null;
199 if (!(Expr is Constant)) {
200 UnCheckedExpr un_expr = Expr as UnCheckedExpr;
201 CheckedExpr ch_expr = Expr as CheckedExpr;
203 if ((un_expr != null) && (un_expr.Expr is Constant))
204 Expr = un_expr.Expr;
205 else if ((ch_expr != null) && (ch_expr.Expr is Constant))
206 Expr = ch_expr.Expr;
207 else
209 Report.Error (30059, Location, "A constant value is expected");
210 return null;
214 ConstantValue = ((Constant) Expr).GetValue ();
216 if (type != Expr.Type) {
217 try {
218 ConstantValue = TypeManager.ChangeType (ConstantValue, type);
219 } catch {
220 Expression.Error_CannotConvertImplicit (Location, Expr.Type, type);
221 return null;
224 if (type == TypeManager.int32_type)
225 Expr = new IntConstant ((int) ConstantValue);
226 else if (type == TypeManager.uint32_type)
227 Expr = new UIntConstant ((uint) ConstantValue);
228 else if (type == TypeManager.int64_type)
229 Expr = new LongConstant ((long) ConstantValue);
230 else if (type == TypeManager.uint64_type)
231 Expr = new ULongConstant ((ulong) ConstantValue);
232 else if (type == TypeManager.float_type)
233 Expr = new FloatConstant ((float) ConstantValue);
234 else if (type == TypeManager.double_type)
235 Expr = new DoubleConstant ((double) ConstantValue);
236 else if (type == TypeManager.string_type)
237 Expr = new StringConstant ((string) ConstantValue);
238 else if (type == TypeManager.short_type)
239 Expr = new ShortConstant ((short) ConstantValue);
240 else if (type == TypeManager.ushort_type)
241 Expr = new UShortConstant ((ushort) ConstantValue);
242 else if (type == TypeManager.sbyte_type)
243 Expr = new SByteConstant ((sbyte) ConstantValue);
244 else if (type == TypeManager.byte_type)
245 Expr = new ByteConstant ((byte) ConstantValue);
246 else if (type == TypeManager.char_type)
247 Expr = new CharConstant ((char) ConstantValue);
248 else if (type == TypeManager.bool_type)
249 Expr = new BoolConstant ((bool) ConstantValue);
252 if (type.IsEnum){
254 // This sadly does not work for our user-defined enumerations types ;-(
256 try {
257 ConstantValue = System.Enum.ToObject (
258 type, ConstantValue);
259 } catch (ArgumentException){
260 Report.Error (
261 -16, Location,
262 ".NET SDK 1.0 does not permit to create the constant "+
263 " field from a user-defined enumeration");
267 FieldBuilder.SetConstant (ConstantValue);
269 if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
270 return null;
272 return ConstantValue;
276 /// <summary>
277 /// Emits the field value by evaluating the expression
278 /// </summary>
279 public void EmitConstant (TypeContainer parent)
281 EmitContext ec = new EmitContext (parent, Location, null, type, ModFlags);
282 LookupConstantValue (ec);
284 return;
287 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
289 FieldBuilder.SetCustomAttribute (cb);