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