Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/const.cs @ 15682

Last change on this file since 15682 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 6.1 KB
Line 
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
13using IKVM.Reflection;
14#else
15using System.Reflection;
16#endif
17
18namespace 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", t.GetSignatureForError ());
104      } else {
105        Report.Error (283, loc,
106          "The type `{0}' cannot be declared const", t.GetSignatureForError ());
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}
Note: See TracBrowser for help on using the repository browser.