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