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 Attributes OptAttributes
;
32 public FieldBuilder FieldBuilder
;
34 object ConstantValue
= null;
37 bool in_transit
= false;
39 public const int AllowedModifiers
=
46 public Const (Expression constant_type
, string name
, Expression expr
, int mod_flags
,
47 Attributes attrs
, Location loc
)
50 ConstantType
= constant_type
;
53 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
, Modifiers
.PRIVATE
, loc
);
54 OptAttributes
= attrs
;
57 public FieldAttributes FieldAttr
{
59 return FieldAttributes
.Literal
| FieldAttributes
.Static
|
60 Modifiers
.FieldAttr (ModFlags
) ;
65 void dump_tree (Type t
)
67 Console
.WriteLine ("Dumping hierarchy");
69 Console
.WriteLine (" " + t
.FullName
+ " " +
70 (t
.GetType ().IsEnum
? "yes" : "no"));
77 /// Defines the constant in the @parent
79 public override bool Define (TypeContainer parent
)
81 type
= parent
.ResolveType (ConstantType
, false, Location
);
86 if (!TypeManager
.IsBuiltinType (type
) &&
87 (!type
.IsSubclassOf (TypeManager
.enum_type
))) {
90 "Constant type is not valid (only system types are allowed)");
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
;
129 MemberList list
= TypeContainer
.FindMembers (
130 ptype
, MemberTypes
.Field
, BindingFlags
.Public
,
131 Type
.FilterName
, Name
);
133 if ((list
.Count
> 0) && ((ModFlags
& Modifiers
.SHADOWS
) == 0))
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);
167 /// Looks up the value of a constant field. Defines it if it hasn't
168 /// already been. Similar to LookupEnumValue in spirit.
170 public object LookupConstantValue (EmitContext ec
)
172 if (ConstantValue
!= null)
173 return ConstantValue
;
176 Report
.Error (110, Location
,
177 "The evaluation of the constant value for `" +
178 Name
+ "' involves a circular definition.");
183 int errors
= Report
.Errors
;
185 Expr
= Expr
.Resolve (ec
);
190 if (errors
== Report
.Errors
)
191 Report
.Error (30059, Location
, "A constant value is expected");
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
))
201 else if ((ch_expr
!= null) && (ch_expr
.Expr
is Constant
))
205 Report
.Error (30059, Location
, "A constant value is expected");
210 ConstantValue
= ((Constant
) Expr
).GetValue ();
212 if (type
!= Expr
.Type
) {
214 ConstantValue
= TypeManager
.ChangeType (ConstantValue
, type
);
216 Expression
.Error_CannotConvertImplicit (Location
, Expr
.Type
, type
);
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
);
250 // This sadly does not work for our user-defined enumerations types ;-(
253 ConstantValue
= System
.Enum
.ToObject (
254 type
, ConstantValue
);
255 } catch (ArgumentException
){
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
))
268 return ConstantValue
;
273 /// Emits the field value by evaluating the expression
275 public void EmitConstant (TypeContainer parent
)
277 EmitContext ec
= new EmitContext (parent
, Location
, null, type
, ModFlags
);
278 LookupConstantValue (ec
);