2004-11-07 Ben Maurer <bmaurer@ximian.com>
[mono-project.git] / mcs / mbas / const.cs
blob9e197c55642ba293f8b0d497c0ce99ddfc55e2bb
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 Attributes OptAttributes;
32 public FieldBuilder FieldBuilder;
34 object ConstantValue = null;
35 Type type;
37 bool in_transit = false;
39 public const int AllowedModifiers =
40 Modifiers.PUBLIC |
41 Modifiers.PROTECTED |
42 Modifiers.INTERNAL |
43 Modifiers.PRIVATE |
44 Modifiers.SHADOWS;
46 public Const (Expression constant_type, string name, Expression expr, int mod_flags,
47 Attributes attrs, Location loc)
48 : base (name, loc)
50 ConstantType = constant_type;
51 Name = name;
52 Expr = expr;
53 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
54 OptAttributes = attrs;
57 public FieldAttributes FieldAttr {
58 get {
59 return FieldAttributes.Literal | FieldAttributes.Static |
60 Modifiers.FieldAttr (ModFlags) ;
64 #if DEBUG
65 void dump_tree (Type t)
67 Console.WriteLine ("Dumping hierarchy");
68 while (t != null){
69 Console.WriteLine (" " + t.FullName + " " +
70 (t.GetType ().IsEnum ? "yes" : "no"));
71 t = t.BaseType;
74 #endif
76 /// <summary>
77 /// Defines the constant in the @parent
78 /// </summary>
79 public override bool Define (TypeContainer parent)
81 type = parent.ResolveType (ConstantType, false, Location);
83 if (type == null)
84 return false;
86 if (!TypeManager.IsBuiltinType (type) &&
87 (!type.IsSubclassOf (TypeManager.enum_type))) {
88 Report.Error (
89 30424, Location,
90 "Constant type is not valid (only system types are allowed)");
91 return false;
94 // if no type is declared expicitely
95 // set the expression type as the type of constant
96 if (type == TypeManager.object_type){
97 if (Expr is IntLiteral)
98 type = TypeManager.int32_type;
99 else if (Expr is UIntLiteral)
100 type = TypeManager.uint32_type;
101 else if (Expr is LongLiteral)
102 type = TypeManager.int64_type;
103 else if (Expr is ULongLiteral)
104 type = TypeManager.uint64_type;
105 else if (Expr is FloatLiteral)
106 type = TypeManager.float_type;
107 else if (Expr is DoubleLiteral)
108 type = TypeManager.double_type;
109 else if (Expr is StringLiteral)
110 type = TypeManager.string_type;
111 else if (Expr is ShortLiteral)
112 type = TypeManager.short_type;
113 else if (Expr is UShortConstant)
114 type = TypeManager.ushort_type;
115 else if (Expr is SByteConstant)
116 type = TypeManager.sbyte_type;
117 else if (Expr is ByteConstant)
118 type = TypeManager.byte_type;
119 else if (Expr is CharConstant)
120 type = TypeManager.char_type;
121 else if (Expr is BoolConstant)
122 type = TypeManager.bool_type;
123 else if (Expr is DateConstant)
124 type = TypeManager.date_type;
126 Type ptype = parent.TypeBuilder.BaseType;
128 if (ptype != null) {
129 MemberList list = TypeContainer.FindMembers (
130 ptype, MemberTypes.Field, BindingFlags.Public,
131 Type.FilterName, Name);
133 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
134 Report.Warning (
135 40004, 2, Location,
136 "Const '" + Name + "' should be declared " +
137 "Shadows since the base type '" + ptype.Name +
138 "' has a Const with same name");
139 if (list.Count == 0) {
140 // if a member of module is not inherited from Object class
141 // can not be declared protected
142 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
143 Report.Error (30593, Location,
144 "'Const' inside a 'Module' can not be " +
145 "declared as 'Protected'");
147 /*if ((ModFlags & Modifiers.NEW) != 0)
148 WarningNotHiding (parent);*/
151 /*else if ((ModFlags & Modifiers.NEW) != 0)
152 WarningNotHiding (parent);*/
154 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
155 Report.Error (30435, Location,
156 "'Const' inside a 'Structure' can not be " +
157 "declared as 'Protected'");
159 FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
161 TypeManager.RegisterConstant (FieldBuilder, this);
163 return true;
166 /// <summary>
167 /// Looks up the value of a constant field. Defines it if it hasn't
168 /// already been. Similar to LookupEnumValue in spirit.
169 /// </summary>
170 public object LookupConstantValue (EmitContext ec)
172 if (ConstantValue != null)
173 return ConstantValue;
175 if (in_transit) {
176 Report.Error (110, Location,
177 "The evaluation of the constant value for `" +
178 Name + "' involves a circular definition.");
179 return null;
182 in_transit = true;
183 int errors = Report.Errors;
185 Expr = Expr.Resolve (ec);
187 in_transit = false;
189 if (Expr == null) {
190 if (errors == Report.Errors)
191 Report.Error (30059, Location, "A constant value is expected");
192 return null;
195 if (!(Expr is Constant)) {
196 UnCheckedExpr un_expr = Expr as UnCheckedExpr;
197 CheckedExpr ch_expr = Expr as CheckedExpr;
199 if ((un_expr != null) && (un_expr.Expr is Constant))
200 Expr = un_expr.Expr;
201 else if ((ch_expr != null) && (ch_expr.Expr is Constant))
202 Expr = ch_expr.Expr;
203 else
205 Report.Error (30059, Location, "A constant value is expected");
206 return null;
210 ConstantValue = ((Constant) Expr).GetValue ();
212 if (type != Expr.Type) {
213 try {
214 ConstantValue = TypeManager.ChangeType (ConstantValue, type);
215 } catch {
216 Expression.Error_CannotConvertImplicit (Location, Expr.Type, type);
217 return null;
220 if (type == TypeManager.int32_type)
221 Expr = new IntConstant ((int) ConstantValue);
222 else if (type == TypeManager.uint32_type)
223 Expr = new UIntConstant ((uint) ConstantValue);
224 else if (type == TypeManager.int64_type)
225 Expr = new LongConstant ((long) ConstantValue);
226 else if (type == TypeManager.uint64_type)
227 Expr = new ULongConstant ((ulong) ConstantValue);
228 else if (type == TypeManager.float_type)
229 Expr = new FloatConstant ((float) ConstantValue);
230 else if (type == TypeManager.double_type)
231 Expr = new DoubleConstant ((double) ConstantValue);
232 else if (type == TypeManager.string_type)
233 Expr = new StringConstant ((string) ConstantValue);
234 else if (type == TypeManager.short_type)
235 Expr = new ShortConstant ((short) ConstantValue);
236 else if (type == TypeManager.ushort_type)
237 Expr = new UShortConstant ((ushort) ConstantValue);
238 else if (type == TypeManager.sbyte_type)
239 Expr = new SByteConstant ((sbyte) ConstantValue);
240 else if (type == TypeManager.byte_type)
241 Expr = new ByteConstant ((byte) ConstantValue);
242 else if (type == TypeManager.char_type)
243 Expr = new CharConstant ((char) ConstantValue);
244 else if (type == TypeManager.bool_type)
245 Expr = new BoolConstant ((bool) ConstantValue);
248 if (type.IsEnum){
250 // This sadly does not work for our user-defined enumerations types ;-(
252 try {
253 ConstantValue = System.Enum.ToObject (
254 type, ConstantValue);
255 } catch (ArgumentException){
256 Report.Error (
257 -16, Location,
258 ".NET SDK 1.0 does not permit to create the constant "+
259 " field from a user-defined enumeration");
263 FieldBuilder.SetConstant (ConstantValue);
265 if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
266 return null;
268 return ConstantValue;
272 /// <summary>
273 /// Emits the field value by evaluating the expression
274 /// </summary>
275 public void EmitConstant (TypeContainer parent)
277 EmitContext ec = new EmitContext (parent, Location, null, type, ModFlags);
278 LookupConstantValue (ec);
280 return;