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
.MonoBASIC
{
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;
36 bool in_transit
= false;
38 public const int AllowedModifiers
=
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
;
52 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
, Modifiers
.PRIVATE
, loc
);
55 public override AttributeTargets AttributeTargets
{
57 return AttributeTargets
.Field
;
61 public FieldAttributes FieldAttr
{
63 return FieldAttributes
.Literal
| FieldAttributes
.Static
|
64 Modifiers
.FieldAttr (ModFlags
) ;
69 void dump_tree (Type t
)
71 Console
.WriteLine ("Dumping hierarchy");
73 Console
.WriteLine (" " + t
.FullName
+ " " +
74 (t
.GetType ().IsEnum
? "yes" : "no"));
81 /// Defines the constant in the @parent
83 public override bool Define (TypeContainer parent
)
85 type
= parent
.ResolveType (ConstantType
, false, Location
);
90 if (!TypeManager
.IsBuiltinType (type
) &&
91 (!type
.IsSubclassOf (TypeManager
.enum_type
))) {
94 "Constant type is not valid (only system types are allowed)");
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
;
133 MemberList list
= TypeContainer
.FindMembers (
134 ptype
, MemberTypes
.Field
, BindingFlags
.Public
,
135 Type
.FilterName
, Name
);
137 if ((list
.Count
> 0) && ((ModFlags
& Modifiers
.SHADOWS
) == 0))
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);
171 /// Looks up the value of a constant field. Defines it if it hasn't
172 /// already been. Similar to LookupEnumValue in spirit.
174 public object LookupConstantValue (EmitContext ec
)
176 if (ConstantValue
!= null)
177 return ConstantValue
;
180 Report
.Error (110, Location
,
181 "The evaluation of the constant value for `" +
182 Name
+ "' involves a circular definition.");
187 int errors
= Report
.Errors
;
189 Expr
= Expr
.Resolve (ec
);
194 if (errors
== Report
.Errors
)
195 Report
.Error (30059, Location
, "A constant value is expected");
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
))
205 else if ((ch_expr
!= null) && (ch_expr
.Expr
is Constant
))
209 Report
.Error (30059, Location
, "A constant value is expected");
214 ConstantValue
= ((Constant
) Expr
).GetValue ();
216 if (type
!= Expr
.Type
) {
218 ConstantValue
= TypeManager
.ChangeType (ConstantValue
, type
);
220 Expression
.Error_CannotConvertImplicit (Location
, Expr
.Type
, type
);
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
);
254 // This sadly does not work for our user-defined enumerations types ;-(
257 ConstantValue
= System
.Enum
.ToObject (
258 type
, ConstantValue
);
259 } catch (ArgumentException
){
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
))
272 return ConstantValue
;
277 /// Emits the field value by evaluating the expression
279 public void EmitConstant (TypeContainer parent
)
281 EmitContext ec
= new EmitContext (parent
, Location
, null, type
, ModFlags
);
282 LookupConstantValue (ec
);
287 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
)
289 FieldBuilder
.SetCustomAttribute (cb
);