2
// const.cs: Constant declarations.
5
// Miguel de Icaza (miguel@ximian.com)
6
// Marek Safar (marek.safar@seznam.cz)
8
// Copyright 2001-2003 Ximian, Inc.
9
// Copyright 2003-2008 Novell, Inc.
13
using IKVM.Reflection;
15
using System.Reflection;
18
namespace Mono.CSharp {
20
public class Const : FieldBase
22
const Modifiers AllowedModifiers =
29
public Const (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
30
: base (parent, type, mod_flags, AllowedModifiers, name, attrs)
32
ModFlags |= Modifiers.STATIC;
36
/// Defines the constant in the @parent
38
public override bool Define ()
43
if (!member_type.IsConstantCompatible) {
44
Error_InvalidConstantType (member_type, Location, Report);
47
FieldAttributes field_attr = FieldAttributes.Static | ModifiersExtensions.FieldAttr (ModFlags);
48
// Decimals cannot be emitted into the constant blob. So, convert to 'readonly'.
49
if (member_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
50
field_attr |= FieldAttributes.InitOnly;
52
field_attr |= FieldAttributes.Literal;
55
FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), field_attr);
56
spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer);
58
Parent.MemberCache.AddMember (spec);
60
if ((field_attr & FieldAttributes.InitOnly) != 0)
61
Parent.PartialContainer.RegisterFieldForInitialization (this,
62
new FieldInitializer (spec, initializer, this));
64
if (declarators != null) {
65
var t = new TypeExpression (MemberType, TypeExpression.Location);
66
foreach (var d in declarators) {
67
var c = new Const (Parent, t, ModFlags & ~Modifiers.STATIC, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
68
c.initializer = d.Initializer;
69
((ConstInitializer) c.initializer).Name = d.Name.Value;
71
Parent.PartialContainer.Members.Add (c);
78
public void DefineValue ()
80
var rc = new ResolveContext (this);
81
((ConstSpec) spec).GetConstant (rc);
85
/// Emits the field value by evaluating the expression
87
public override void Emit ()
89
var c = ((ConstSpec) spec).Value as Constant;
90
if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
91
Module.PredefinedAttributes.DecimalConstant.EmitAttribute (FieldBuilder, (decimal) c.GetValue (), c.Location);
93
FieldBuilder.SetConstant (c.GetValue ());
99
public static void Error_InvalidConstantType (TypeSpec t, Location loc, Report Report)
101
if (t.IsGenericParameter) {
102
Report.Error (1959, loc,
103
"Type parameter `{0}' cannot be declared const", TypeManager.CSharpName (t));
105
Report.Error (283, loc,
106
"The type `{0}' cannot be declared const", TypeManager.CSharpName (t));
110
public override void Accept (StructuralVisitor visitor)
112
visitor.Visit (this);
116
public class ConstSpec : FieldSpec
120
public ConstSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo fi, Modifiers mod, Expression value)
121
: base (declaringType, definition, memberType, fi, mod)
127
// This expresion is guarantee to be a constant at emit phase only
129
public Expression Value {
136
// For compiled constants we have to resolve the value as there could be constant dependecies. This
137
// is needed for imported constants too to get the right context type
139
public Constant GetConstant (ResolveContext rc)
141
if (value.eclass != ExprClass.Value)
142
value = value.Resolve (rc);
144
return (Constant) value;
148
public class ConstInitializer : ShimExpression
151
readonly FieldBase field;
153
public ConstInitializer (FieldBase field, Expression value, Location loc)
160
public string Name { get; set; }
162
protected override Expression DoResolve (ResolveContext unused)
167
var opt = ResolveContext.Options.ConstantScope;
168
if (field is EnumMember)
169
opt |= ResolveContext.Options.EnumScope;
172
// Use a context in which the constant was declared and
173
// not the one in which is referenced
175
var rc = new ResolveContext (field, opt);
176
expr = DoResolveInitializer (rc);
182
protected virtual Expression DoResolveInitializer (ResolveContext rc)
185
field.Compiler.Report.Error (110, expr.Location,
186
"The evaluation of the constant value for `{0}' involves a circular definition",
187
GetSignatureForError ());
192
expr = expr.Resolve (rc);
198
Constant c = expr as Constant;
200
c = field.ConvertInitializer (rc, c);
203
if (TypeSpec.IsReferenceType (field.MemberType))
204
Error_ConstantCanBeInitializedWithNullOnly (rc, field.MemberType, expr.Location, GetSignatureForError ());
205
else if (!(expr is Constant))
206
Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ());
208
expr.Error_ValueCannotBeConverted (rc, field.MemberType, false);
215
expr = New.Constantify (field.MemberType, Location);
217
expr = Constant.CreateConstantFromValue (field.MemberType, null, Location);
218
expr = expr.Resolve (rc);
224
public override string GetSignatureForError ()
227
return field.GetSignatureForError ();
229
return field.Parent.GetSignatureForError () + "." + Name;
232
public override object Accept (StructuralVisitor visitor)
234
return visitor.Visit (this);