~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/const.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// const.cs: Constant declarations.
 
3
//
 
4
// Author:
 
5
//   Miguel de Icaza (miguel@ximian.com)
 
6
//   Marek Safar (marek.safar@seznam.cz)
 
7
//
 
8
// Copyright 2001-2003 Ximian, Inc.
 
9
// Copyright 2003-2008 Novell, Inc.
 
10
//
 
11
 
 
12
#if STATIC
 
13
using IKVM.Reflection;
 
14
#else
 
15
using System.Reflection;
 
16
#endif
 
17
 
 
18
namespace Mono.CSharp {
 
19
 
 
20
        public class Const : FieldBase
 
21
        {
 
22
                const Modifiers AllowedModifiers =
 
23
                        Modifiers.NEW |
 
24
                        Modifiers.PUBLIC |
 
25
                        Modifiers.PROTECTED |
 
26
                        Modifiers.INTERNAL |
 
27
                        Modifiers.PRIVATE;
 
28
 
 
29
                public Const (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
 
30
                        : base (parent, type, mod_flags, AllowedModifiers, name, attrs)
 
31
                {
 
32
                        ModFlags |= Modifiers.STATIC;
 
33
                }
 
34
 
 
35
                /// <summary>
 
36
                ///   Defines the constant in the @parent
 
37
                /// </summary>
 
38
                public override bool Define ()
 
39
                {
 
40
                        if (!base.Define ())
 
41
                                return false;
 
42
 
 
43
                        if (!member_type.IsConstantCompatible) {
 
44
                                Error_InvalidConstantType (member_type, Location, Report);
 
45
                        }
 
46
 
 
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;
 
51
                        } else {
 
52
                                field_attr |= FieldAttributes.Literal;
 
53
                        }
 
54
 
 
55
                        FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), field_attr);
 
56
                        spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer);
 
57
 
 
58
                        Parent.MemberCache.AddMember (spec);
 
59
 
 
60
                        if ((field_attr & FieldAttributes.InitOnly) != 0)
 
61
                                Parent.PartialContainer.RegisterFieldForInitialization (this,
 
62
                                        new FieldInitializer (this, initializer, Location));
 
63
 
 
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;
 
70
                                        c.Define ();
 
71
                                        Parent.PartialContainer.Members.Add (c);
 
72
                                }
 
73
                        }
 
74
 
 
75
                        return true;
 
76
                }
 
77
 
 
78
                public void DefineValue ()
 
79
                {
 
80
                        var rc = new ResolveContext (this);
 
81
                        ((ConstSpec) spec).GetConstant (rc);
 
82
                }
 
83
 
 
84
                /// <summary>
 
85
                ///  Emits the field value by evaluating the expression
 
86
                /// </summary>
 
87
                public override void Emit ()
 
88
                {
 
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);
 
92
                        } else {
 
93
                                FieldBuilder.SetConstant (c.GetValue ());
 
94
                        }
 
95
 
 
96
                        base.Emit ();
 
97
                }
 
98
 
 
99
                public static void Error_InvalidConstantType (TypeSpec t, Location loc, Report Report)
 
100
                {
 
101
                        if (t.IsGenericParameter) {
 
102
                                Report.Error (1959, loc,
 
103
                                        "Type parameter `{0}' cannot be declared const", TypeManager.CSharpName (t));
 
104
                        } else {
 
105
                                Report.Error (283, loc,
 
106
                                        "The type `{0}' cannot be declared const", TypeManager.CSharpName (t));
 
107
                        }
 
108
                }
 
109
 
 
110
                public override void Accept (StructuralVisitor visitor)
 
111
                {
 
112
                        visitor.Visit (this);
 
113
                }
 
114
        }
 
115
 
 
116
        public class ConstSpec : FieldSpec
 
117
        {
 
118
                Expression value;
 
119
 
 
120
                public ConstSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo fi, Modifiers mod, Expression value)
 
121
                        : base (declaringType, definition, memberType, fi, mod)
 
122
                {
 
123
                        this.value = value;
 
124
                }
 
125
 
 
126
                //
 
127
                // This expresion is guarantee to be a constant at emit phase only
 
128
                //
 
129
                public Expression Value {
 
130
                        get {
 
131
                                return value;
 
132
                        }
 
133
                }
 
134
 
 
135
                //
 
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
 
138
                //
 
139
                public Constant GetConstant (ResolveContext rc)
 
140
                {
 
141
                        if (value.eclass != ExprClass.Value)
 
142
                                value = value.Resolve (rc);
 
143
 
 
144
                        return (Constant) value;
 
145
                }
 
146
        }
 
147
 
 
148
        public class ConstInitializer : ShimExpression
 
149
        {
 
150
                bool in_transit;
 
151
                readonly FieldBase field;
 
152
 
 
153
                public ConstInitializer (FieldBase field, Expression value, Location loc)
 
154
                        : base (value)
 
155
                {
 
156
                        this.loc = loc;
 
157
                        this.field = field;
 
158
                }
 
159
 
 
160
                public string Name { get; set; }
 
161
 
 
162
                protected override Expression DoResolve (ResolveContext unused)
 
163
                {
 
164
                        if (type != null)
 
165
                                return expr;
 
166
 
 
167
                        var opt = ResolveContext.Options.ConstantScope;
 
168
                        if (field is EnumMember)
 
169
                                opt |= ResolveContext.Options.EnumScope;
 
170
 
 
171
                        //
 
172
                        // Use a context in which the constant was declared and
 
173
                        // not the one in which is referenced
 
174
                        //
 
175
                        var rc = new ResolveContext (field, opt);
 
176
                        expr = DoResolveInitializer (rc);
 
177
                        type = expr.Type;
 
178
 
 
179
                        return expr;
 
180
                }
 
181
 
 
182
                protected virtual Expression DoResolveInitializer (ResolveContext rc)
 
183
                {
 
184
                        if (in_transit) {
 
185
                                field.Compiler.Report.Error (110, expr.Location,
 
186
                                        "The evaluation of the constant value for `{0}' involves a circular definition",
 
187
                                        GetSignatureForError ());
 
188
 
 
189
                                expr = null;
 
190
                        } else {
 
191
                                in_transit = true;
 
192
                                expr = expr.Resolve (rc);
 
193
                        }
 
194
 
 
195
                        in_transit = false;
 
196
 
 
197
                        if (expr != null) {
 
198
                                Constant c = expr as Constant;
 
199
                                if (c != null)
 
200
                                        c = field.ConvertInitializer (rc, c);
 
201
 
 
202
                                if (c == null) {
 
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 ());
 
207
                                        else
 
208
                                                expr.Error_ValueCannotBeConverted (rc, field.MemberType, false);
 
209
                                }
 
210
 
 
211
                                expr = c;
 
212
                        }
 
213
 
 
214
                        if (expr == null) {
 
215
                                expr = New.Constantify (field.MemberType, Location);
 
216
                                if (expr == null)
 
217
                                        expr = Constant.CreateConstantFromValue (field.MemberType, null, Location);
 
218
                                expr = expr.Resolve (rc);
 
219
                        }
 
220
 
 
221
                        return expr;
 
222
                }
 
223
 
 
224
                public override string GetSignatureForError ()
 
225
                {
 
226
                        if (Name == null)
 
227
                                return field.GetSignatureForError ();
 
228
 
 
229
                        return field.Parent.GetSignatureForError () + "." + Name;
 
230
                }
 
231
 
 
232
                public override object Accept (StructuralVisitor visitor)
 
233
                {
 
234
                        return visitor.Visit (this);
 
235
                }
 
236
        }
 
237
}