Revert the recent fixes until 1-2-2 is branched
[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 // (C) 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 using System;
23 using System.Reflection;
24 using System.Reflection.Emit;
25
26 //
27 // I put System.Null just so we do not have to special case it on 
28 // TypeManager.CSharpName
29 //
30 namespace System {
31         //
32         // Represents the Null Type, just used as a placeholder for the type in NullLiteral
33         //
34         public class Null {
35         }
36 }
37         
38 namespace Mono.CSharp {
39
40         //
41         // The NullType just exists to compare type equality, and for
42         // expressions that might have the `null type'
43         //
44         public class NullType {
45         }
46
47
48         public abstract class NullConstant : Constant
49         {
50                 public NullConstant (Location loc):
51                         base (loc)
52                 {
53                         eclass = ExprClass.Value;
54                 }
55                 
56                 override public string AsString ()
57                 {
58                         return "null";
59                 }
60
61                 public override object GetValue ()
62                 {
63                         return null;
64                 }
65
66                 public override void Emit (EmitContext ec)
67                 {
68                         ec.ig.Emit(OpCodes.Ldnull);
69                 }
70
71                 public override string GetSignatureForError ()
72                 {
73                         return "null";
74                 }
75
76                 public override Constant Increment ()
77                 {
78                         throw new NotSupportedException ();
79                 }
80
81                 public override bool IsDefaultValue 
82                 {
83                         get { return true; }
84                 }
85
86                 public override bool IsNegative 
87                 {
88                         get { return false; }
89                 }
90
91                 public override bool IsZeroInteger 
92                 {
93                         get { return true; }
94                 }
95
96                 public override Constant Reduce(bool inCheckedContext, Type target_type)
97                 {
98                         if (!TypeManager.IsValueType (target_type))
99                                 return new EmptyConstantCast (this, target_type);
100
101                         return null;
102                 }
103
104                 public override Constant ToType(Type targetType)
105                 {
106                         if (!TypeManager.IsValueType (targetType))
107                                 return new EmptyConstantCast (this, targetType);
108
109                         return null;
110                 }
111         }
112
113         //
114         // Represents default(X) when result can be reduced to null
115         //
116         public class NullDefault : EmptyConstantCast
117         {
118                 public NullDefault(Constant value, Type type)
119                         : base (value, type)
120                 {
121                 }
122
123                 public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
124                 {
125                         base.Error_ValueCannotBeConverted(loc, target, expl);
126                 }
127         }
128
129         //
130         // The null Literal constant
131         //
132         public class NullLiteral : NullConstant {
133                 public NullLiteral (Location loc):
134                         base (loc)
135                 {
136                 }
137
138                 public override Expression DoResolve (EmitContext ec)
139                 {
140                         type = TypeManager.null_type;
141                         return this;
142                 }
143
144                 public override void Error_ValueCannotBeConverted (Location loc, Type t, bool expl)
145                 {
146                         if (TypeManager.IsGenericParameter (t)) {
147                                 Report.Error(403, loc,
148                                         "Cannot convert null to the type parameter `{0}' becaues it could be a value " +
149                                         "type. Consider using `default ({0})' instead", t.Name);
150                         } else {
151                                 Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type",
152                                         TypeManager.CSharpName(t));
153                         }
154                 }
155
156                 public override Constant ToType (Type targetType)
157                 {
158                         if (targetType.IsPointer)
159                                 return new EmptyConstantCast (NullPointer.Null, targetType);
160
161                         if (TypeManager.IsGenericParameter(targetType)) {
162                                 GenericConstraints gc = null;
163
164 #if GMCS_SOURCE
165                                 gc = TypeManager.GetTypeParameterConstraints(targetType);
166 #endif
167                                 if (gc != null && gc.IsReferenceType)
168                                         return new EmptyConstantCast (this, targetType);
169
170                                 Error_ValueCannotBeConverted (loc, targetType, false);
171                                 return null;
172                         }
173
174                         return base.ToType(targetType);
175                 }
176
177         }
178
179         //
180         // A null literal in a pointer context
181         //
182         public class NullPointer : NullLiteral {
183                 public static readonly NullLiteral Null;
184
185                 static NullPointer ()
186                 {
187                         Null = new NullPointer ();
188                 }
189
190                 private NullPointer ():
191                         base (Location.Null)
192                 {
193                         type = TypeManager.object_type;
194                 }
195
196                 public override void Emit (EmitContext ec)
197                 {
198                         ILGenerator ig = ec.ig;
199                                 
200                         // TODO: why not use Ldnull instead ?
201                         ig.Emit (OpCodes.Ldc_I4_0);
202                         ig.Emit (OpCodes.Conv_U);
203                 }
204         }
205
206         public class BoolLiteral : BoolConstant {
207                 public BoolLiteral (bool val, Location loc) : base (val, loc)
208                 {
209                 }
210
211                 public override Expression DoResolve (EmitContext ec)
212                 {
213                         type = TypeManager.bool_type;
214                         return this;
215                 }
216         }
217
218         public class CharLiteral : CharConstant {
219                 public CharLiteral (char c, Location loc) : base (c, loc)
220                 {
221                 }
222
223                 public override Expression DoResolve (EmitContext ec)
224                 {
225                         type = TypeManager.char_type;
226                         return this;
227                 }
228         }
229
230         public class IntLiteral : IntConstant {
231                 public IntLiteral (int l, Location loc) : base (l, loc)
232                 {
233                 }
234
235                 public override Expression DoResolve (EmitContext ec)
236                 {
237                         type = TypeManager.int32_type;
238                         return this;
239                 }
240         }
241
242         public class UIntLiteral : UIntConstant {
243                 public UIntLiteral (uint l, Location loc) : base (l, loc)
244                 {
245                 }
246
247                 public override Expression DoResolve (EmitContext ec)
248                 {
249                         type = TypeManager.uint32_type;
250                         return this;
251                 }
252         }
253         
254         public class LongLiteral : LongConstant {
255                 public LongLiteral (long l, Location loc) : base (l, loc)
256                 {
257                 }
258
259                 public override Expression DoResolve (EmitContext ec)
260                 {
261                         type = TypeManager.int64_type;
262
263                         return this;
264                 }
265         }
266
267         public class ULongLiteral : ULongConstant {
268                 public ULongLiteral (ulong l, Location loc) : base (l, loc)
269                 {
270                 }
271
272                 public override Expression DoResolve (EmitContext ec)
273                 {
274                         type = TypeManager.uint64_type;
275                         return this;
276                 }
277         }
278         
279         public class FloatLiteral : FloatConstant {
280                 
281                 public FloatLiteral (float f, Location loc) : base (f, loc)
282                 {
283                 }
284
285                 public override Expression DoResolve (EmitContext ec)
286                 {
287                         type = TypeManager.float_type;
288                         return this;
289                 }
290         }
291
292         public class DoubleLiteral : DoubleConstant {
293                 public DoubleLiteral (double d, Location loc) : base (d, loc)
294                 {
295                 }
296
297                 public override Expression DoResolve (EmitContext ec)
298                 {
299                         type = TypeManager.double_type;
300
301                         return this;
302                 }
303
304                 public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
305                 {
306                         if (target == TypeManager.float_type) {
307                                 Error_664 (loc, "float", "f");
308                                 return;
309                         }
310
311                         if (target == TypeManager.decimal_type) {
312                                 Error_664 (loc, "decimal", "m");
313                                 return;
314                         }
315
316                         base.Error_ValueCannotBeConverted (loc, target, expl);
317                 }
318
319                 static void Error_664 (Location loc, string type, string suffix)
320                 {
321                         Report.Error (664, loc,
322                                 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
323                                 type, suffix);
324                 }
325         }
326
327         public class DecimalLiteral : DecimalConstant {
328                 public DecimalLiteral (decimal d, Location loc) : base (d, loc)
329                 {
330                 }
331
332                 public override Expression DoResolve (EmitContext ec)
333                 {
334                         type = TypeManager.decimal_type;
335                         return this;
336                 }
337         }
338
339         public class StringLiteral : StringConstant {
340                 public StringLiteral (string s, Location loc) : base (s, loc)
341                 {
342                 }
343
344                 public override Expression DoResolve (EmitContext ec)
345                 {
346                         type = TypeManager.string_type;
347
348                         return this;
349                 }
350         }
351 }