2009-07-20 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / literal.cs
blobb23d0004c0e692572c3b89bf037eff9faf679c39
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 //
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).
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.
22 using System;
23 using System.Reflection;
24 using System.Reflection.Emit;
26 namespace Mono.CSharp {
29 // The null literal
31 // Note: C# specification null-literal is NullLiteral of NullType type
33 class NullLiteral : Constant
36 // Default type of null is an object
38 public NullLiteral (Location loc):
39 this (typeof (NullLiteral), loc)
44 // Null can have its own type, think of default (Foo)
46 public NullLiteral (Type type, Location loc)
47 : base (loc)
49 eclass = ExprClass.Value;
50 this.type = type;
53 override public string AsString ()
55 return GetSignatureForError ();
58 public override Expression CreateExpressionTree (EmitContext ec)
60 // HACK: avoid referencing mcs internal type
61 if (type == typeof (NullLiteral))
62 type = TypeManager.object_type;
64 return base.CreateExpressionTree (ec);
67 public override Expression DoResolve (EmitContext ec)
69 return this;
72 public override void Emit (EmitContext ec)
74 ec.ig.Emit (OpCodes.Ldnull);
76 #if GMCS_SOURCE
77 // Only to make verifier happy
78 if (TypeManager.IsGenericParameter (type))
79 ec.ig.Emit (OpCodes.Unbox_Any, type);
80 #endif
83 public override string ExprClassName {
84 get {
85 return GetSignatureForError ();
89 public override string GetSignatureForError ()
91 return "null";
94 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type t, bool expl)
96 if (TypeManager.IsGenericParameter (t)) {
97 Report.Error(403, loc,
98 "Cannot convert null to the type parameter `{0}' because it could be a value " +
99 "type. Consider using `default ({0})' instead", t.Name);
100 return;
103 if (TypeManager.IsValueType (t)) {
104 Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type",
105 TypeManager.CSharpName(t));
106 return;
109 base.Error_ValueCannotBeConverted (ec, loc, t, expl);
112 public override Constant ConvertExplicitly (bool inCheckedContext, Type targetType)
114 if (targetType.IsPointer) {
115 if (type == TypeManager.null_type || this is NullPointer)
116 return new EmptyConstantCast (new NullPointer (loc), targetType);
118 return null;
121 // Exlude internal compiler types
122 if (targetType == InternalType.AnonymousMethod)
123 return null;
125 if (type != TypeManager.null_type && !Convert.ImplicitStandardConversionExists (this, targetType))
126 return null;
128 if (TypeManager.IsReferenceType (targetType))
129 return new NullLiteral (targetType, loc);
131 if (TypeManager.IsNullableType (targetType))
132 return Nullable.LiftedNull.Create (targetType, loc);
134 return null;
137 public override Constant ConvertImplicitly (Type targetType)
140 // Null literal is of object type
142 if (targetType == TypeManager.object_type)
143 return this;
145 return ConvertExplicitly (false, targetType);
148 public override object GetValue ()
150 return null;
153 public override Constant Increment ()
155 throw new NotSupportedException ();
158 public override bool IsDefaultValue {
159 get { return true; }
162 public override bool IsLiteral {
163 get { return true; }
166 public override bool IsNegative {
167 get { return false; }
170 public override bool IsNull {
171 get { return true; }
174 public override bool IsZeroInteger {
175 get { return true; }
178 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
180 type = storey.MutateType (type);
185 // A null literal in a pointer context
187 class NullPointer : NullLiteral {
188 public NullPointer (Location loc):
189 base (loc)
191 type = TypeManager.object_type;
194 public override void Emit (EmitContext ec)
196 ILGenerator ig = ec.ig;
199 // Emits null pointer
201 ig.Emit (OpCodes.Ldc_I4_0);
202 ig.Emit (OpCodes.Conv_U);
206 public class BoolLiteral : BoolConstant {
207 public BoolLiteral (bool val, Location loc) : base (val, loc)
211 public override Expression DoResolve (EmitContext ec)
213 type = TypeManager.bool_type;
214 return this;
217 public override bool IsLiteral {
218 get { return true; }
222 public class CharLiteral : CharConstant {
223 public CharLiteral (char c, Location loc) : base (c, loc)
227 public override Expression DoResolve (EmitContext ec)
229 type = TypeManager.char_type;
230 return this;
233 public override bool IsLiteral {
234 get { return true; }
238 public class IntLiteral : IntConstant {
239 public IntLiteral (int l, Location loc) : base (l, loc)
243 public override Expression DoResolve (EmitContext ec)
245 type = TypeManager.int32_type;
246 return this;
249 public override Constant ConvertImplicitly (Type type)
252 /// The 0 literal can be converted to an enum value,
254 if (Value == 0 && TypeManager.IsEnumType (type)) {
255 Constant c = ConvertImplicitly (TypeManager.GetEnumUnderlyingType (type));
256 if (c == null)
257 return null;
259 return new EnumConstant (c, type);
261 return base.ConvertImplicitly (type);
264 public override bool IsLiteral {
265 get { return true; }
269 public class UIntLiteral : UIntConstant {
270 public UIntLiteral (uint l, Location loc) : base (l, loc)
274 public override Expression DoResolve (EmitContext ec)
276 type = TypeManager.uint32_type;
277 return this;
280 public override bool IsLiteral {
281 get { return true; }
285 public class LongLiteral : LongConstant {
286 public LongLiteral (long l, Location loc) : base (l, loc)
290 public override Expression DoResolve (EmitContext ec)
292 type = TypeManager.int64_type;
293 return this;
296 public override bool IsLiteral {
297 get { return true; }
301 public class ULongLiteral : ULongConstant {
302 public ULongLiteral (ulong l, Location loc) : base (l, loc)
306 public override Expression DoResolve (EmitContext ec)
308 type = TypeManager.uint64_type;
309 return this;
312 public override bool IsLiteral {
313 get { return true; }
317 public class FloatLiteral : FloatConstant {
319 public FloatLiteral (float f, Location loc) : base (f, loc)
323 public override Expression DoResolve (EmitContext ec)
325 type = TypeManager.float_type;
326 return this;
329 public override bool IsLiteral {
330 get { return true; }
335 public class DoubleLiteral : DoubleConstant {
336 public DoubleLiteral (double d, Location loc) : base (d, loc)
340 public override Expression DoResolve (EmitContext ec)
342 type = TypeManager.double_type;
344 return this;
347 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
349 if (target == TypeManager.float_type) {
350 Error_664 (loc, "float", "f");
351 return;
354 if (target == TypeManager.decimal_type) {
355 Error_664 (loc, "decimal", "m");
356 return;
359 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
362 static void Error_664 (Location loc, string type, string suffix)
364 Report.Error (664, loc,
365 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
366 type, suffix);
369 public override bool IsLiteral {
370 get { return true; }
375 public class DecimalLiteral : DecimalConstant {
376 public DecimalLiteral (decimal d, Location loc) : base (d, loc)
380 public override Expression DoResolve (EmitContext ec)
382 type = TypeManager.decimal_type;
383 return this;
386 public override bool IsLiteral {
387 get { return true; }
391 public class StringLiteral : StringConstant {
392 public StringLiteral (string s, Location loc) : base (s, loc)
396 public override Expression DoResolve (EmitContext ec)
398 type = TypeManager.string_type;
400 return this;
403 public override bool IsLiteral {
404 get { return true; }