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

« back to all changes in this revision

Viewing changes to contrib/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 (spec, initializer, this));
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
 
}