Persist parsed values of literal constants in full ast mode
[mono.git] / mcs / mcs / literal.cs
1 //
2 // literal.cs: Literal representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2001 Ximian, Inc.
9 //
10 //
11 // Notice that during parsing we create objects of type Literal, but the
12 // types are not loaded (thats why the Resolve method has to assign the
13 // type at that point).
14 //
15 // Literals differ from the constants in that we know we encountered them
16 // as a literal in the source code (and some extra rules apply there) and
17 // they have to be resolved (since during parsing we have not loaded the
18 // types yet) while constants are created only after types have been loaded
19 // and are fully resolved when born.
20 //
21
22 #if STATIC
23 using IKVM.Reflection.Emit;
24 #else
25 using System.Reflection.Emit;
26 #endif
27
28 namespace Mono.CSharp
29 {
30         public interface ILiteralConstant
31         {
32 #if FULL_AST
33                 char[] ParsedValue { get; set; }
34 #endif
35         }
36
37         //
38         // The null literal
39         //
40         // Note: C# specification null-literal is NullLiteral of NullType type
41         //
42         public class NullLiteral : NullConstant
43         {
44                 //
45                 // Default type of null is an object
46                 //
47                 public NullLiteral (Location loc)
48                         : base (InternalType.NullLiteral, loc)
49                 {
50                 }
51
52                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec t, bool expl)
53                 {
54                         if (t.IsGenericParameter) {
55                                 ec.Report.Error(403, loc,
56                                         "Cannot convert null to the type parameter `{0}' because it could be a value " +
57                                         "type. Consider using `default ({0})' instead", t.Name);
58                                 return;
59                         }
60
61                         if (TypeSpec.IsValueType (t)) {
62                                 ec.Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type",
63                                         TypeManager.CSharpName(t));
64                                 return;
65                         }
66
67                         base.Error_ValueCannotBeConverted (ec, loc, t, expl);
68                 }
69
70                 public override string GetValueAsLiteral ()
71                 {
72                         return "null";
73                 }
74
75                 public override bool IsLiteral {
76                         get { return true; }
77                 }
78
79                 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
80                 {
81                         return System.Linq.Expressions.Expression.Constant (null);
82                 }
83         }
84
85         public class BoolLiteral : BoolConstant, ILiteralConstant
86         {
87                 public BoolLiteral (BuiltinTypes types, bool val, Location loc)
88                         : base (types, val, loc)
89                 {
90                 }
91
92                 public override bool IsLiteral {
93                         get { return true; }
94                 }
95
96 #if FULL_AST
97                 char[] ILiteralConstant.ParsedValue { get; set; }
98 #endif
99         }
100
101         public class CharLiteral : CharConstant, ILiteralConstant
102         {
103                 public CharLiteral (BuiltinTypes types, char c, Location loc)
104                         : base (types, c, loc)
105                 {
106                 }
107
108                 public override bool IsLiteral {
109                         get { return true; }
110                 }
111
112 #if FULL_AST
113                 char[] ILiteralConstant.ParsedValue { get; set; }
114 #endif
115         }
116
117         public class IntLiteral : IntConstant, ILiteralConstant
118         {
119                 public IntLiteral (BuiltinTypes types, int l, Location loc)
120                         : base (types, l, loc)
121                 {
122                 }
123
124                 public override Constant ConvertImplicitly (TypeSpec type)
125                 {
126                         //
127                         // The 0 literal can be converted to an enum value
128                         //
129                         if (Value == 0 && TypeManager.IsEnumType (type)) {
130                                 Constant c = ConvertImplicitly (EnumSpec.GetUnderlyingType (type));
131                                 if (c == null)
132                                         return null;
133
134                                 return new EnumConstant (c, type);
135                         }
136
137                         return base.ConvertImplicitly (type);
138                 }
139
140                 public override bool IsLiteral {
141                         get { return true; }
142                 }
143
144 #if FULL_AST
145                 char[] ILiteralConstant.ParsedValue { get; set; }
146 #endif
147         }
148
149         public class UIntLiteral : UIntConstant, ILiteralConstant
150         {
151                 public UIntLiteral (BuiltinTypes types, uint l, Location loc)
152                         : base (types, l, loc)
153                 {
154                 }
155
156                 public override bool IsLiteral {
157                         get { return true; }
158                 }
159
160 #if FULL_AST
161                 char[] ILiteralConstant.ParsedValue { get; set; }
162 #endif
163         }
164
165         public class LongLiteral : LongConstant, ILiteralConstant
166         {
167                 public LongLiteral (BuiltinTypes types, long l, Location loc)
168                         : base (types, l, loc)
169                 {
170                 }
171
172                 public override bool IsLiteral {
173                         get { return true; }
174                 }
175
176 #if FULL_AST
177                 char[] ILiteralConstant.ParsedValue { get; set; }
178 #endif
179         }
180
181         public class ULongLiteral : ULongConstant, ILiteralConstant
182         {
183                 public ULongLiteral (BuiltinTypes types, ulong l, Location loc)
184                         : base (types, l, loc)
185                 {
186                 }
187
188                 public override bool IsLiteral {
189                         get { return true; }
190                 }
191
192 #if FULL_AST
193                 char[] ILiteralConstant.ParsedValue { get; set; }
194 #endif
195         }
196
197         public class FloatLiteral : FloatConstant, ILiteralConstant
198         {
199                 public FloatLiteral (BuiltinTypes types, float f, Location loc)
200                         : base (types, f, loc)
201                 {
202                 }
203
204                 public override bool IsLiteral {
205                         get { return true; }
206                 }
207
208 #if FULL_AST
209                 char[] ILiteralConstant.ParsedValue { get; set; }
210 #endif
211         }
212
213         public class DoubleLiteral : DoubleConstant, ILiteralConstant
214         {
215                 public DoubleLiteral (BuiltinTypes types, double d, Location loc)
216                         : base (types, d, loc)
217                 {
218                 }
219
220                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
221                 {
222                         if (target.BuiltinType == BuiltinTypeSpec.Type.Float) {
223                                 Error_664 (ec, loc, "float", "f");
224                                 return;
225                         }
226
227                         if (target.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
228                                 Error_664 (ec, loc, "decimal", "m");
229                                 return;
230                         }
231
232                         base.Error_ValueCannotBeConverted (ec, loc, target, expl);
233                 }
234
235                 static void Error_664 (ResolveContext ec, Location loc, string type, string suffix)
236                 {
237                         ec.Report.Error (664, loc,
238                                 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
239                                 type, suffix);
240                 }
241
242                 public override bool IsLiteral {
243                         get { return true; }
244                 }
245
246 #if FULL_AST
247                 char[] ILiteralConstant.ParsedValue { get; set; }
248 #endif
249         }
250
251         public class DecimalLiteral : DecimalConstant, ILiteralConstant
252         {
253                 public DecimalLiteral (BuiltinTypes types, decimal d, Location loc)
254                         : base (types, d, loc)
255                 {
256                 }
257
258                 public override bool IsLiteral {
259                         get { return true; }
260                 }
261
262 #if FULL_AST
263                 char[] ILiteralConstant.ParsedValue { get; set; }
264 #endif
265         }
266
267         public class StringLiteral : StringConstant, ILiteralConstant
268         {
269                 public StringLiteral (BuiltinTypes types, string s, Location loc)
270                         : base (types, s, loc)
271                 {
272                 }
273
274                 public override bool IsLiteral {
275                         get { return true; }
276                 }
277
278 #if FULL_AST
279                 char[] ILiteralConstant.ParsedValue { get; set; }
280 #endif
281         }
282 }