2 // literal.cs: Literal representation for the IL tree.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001 Ximian, Inc.
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.
23 using System.Reflection;
24 using System.Reflection.Emit;
26 namespace Mono.CSharp {
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)
49 eclass = ExprClass.Value;
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)
72 public override void Emit (EmitContext ec)
74 ec.ig.Emit (OpCodes.Ldnull);
77 // Only to make verifier happy
78 if (TypeManager.IsGenericParameter (type))
79 ec.ig.Emit (OpCodes.Unbox_Any, type);
83 public override string ExprClassName {
85 return GetSignatureForError ();
89 public override string GetSignatureForError ()
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);
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));
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);
121 // Exlude internal compiler types
122 if (targetType == TypeManager.anonymous_method_type)
125 if (TypeManager.IsReferenceType (targetType))
126 return new NullLiteral (targetType, loc);
128 if (TypeManager.IsNullableType (targetType))
129 return Nullable.LiftedNull.Create (targetType, loc);
134 public override Constant ConvertImplicitly (Type targetType)
137 // Null literal is of object type
139 if (targetType == TypeManager.object_type)
142 return ConvertExplicitly (false, targetType);
145 public override object GetValue ()
150 public override Constant Increment ()
152 throw new NotSupportedException ();
155 public override bool IsDefaultValue {
159 public override bool IsLiteral {
163 public override bool IsNegative {
164 get { return false; }
167 public override bool IsNull {
171 public override bool IsZeroInteger {
177 // A null literal in a pointer context
179 class NullPointer : NullLiteral {
180 public NullPointer (Location loc):
183 type = TypeManager.object_type;
186 public override void Emit (EmitContext ec)
188 ILGenerator ig = ec.ig;
191 // Emits null pointer
193 ig.Emit (OpCodes.Ldc_I4_0);
194 ig.Emit (OpCodes.Conv_U);
198 public class BoolLiteral : BoolConstant {
199 public BoolLiteral (bool val, Location loc) : base (val, loc)
203 public override Expression DoResolve (EmitContext ec)
205 type = TypeManager.bool_type;
209 public override bool IsLiteral {
214 public class CharLiteral : CharConstant {
215 public CharLiteral (char c, Location loc) : base (c, loc)
219 public override Expression DoResolve (EmitContext ec)
221 type = TypeManager.char_type;
225 public override bool IsLiteral {
230 public class IntLiteral : IntConstant {
231 public IntLiteral (int l, Location loc) : base (l, loc)
235 public override Expression DoResolve (EmitContext ec)
237 type = TypeManager.int32_type;
241 public override Constant ConvertImplicitly (Type type)
244 /// The 0 literal can be converted to an enum value,
246 if (Value == 0 && TypeManager.IsEnumType (type)) {
247 Constant c = ConvertImplicitly (TypeManager.GetEnumUnderlyingType (type));
251 return new EnumConstant (c, type);
253 return base.ConvertImplicitly (type);
256 public override bool IsLiteral {
261 public class UIntLiteral : UIntConstant {
262 public UIntLiteral (uint l, Location loc) : base (l, loc)
266 public override Expression DoResolve (EmitContext ec)
268 type = TypeManager.uint32_type;
272 public override bool IsLiteral {
277 public class LongLiteral : LongConstant {
278 public LongLiteral (long l, Location loc) : base (l, loc)
282 public override Expression DoResolve (EmitContext ec)
284 type = TypeManager.int64_type;
288 public override bool IsLiteral {
293 public class ULongLiteral : ULongConstant {
294 public ULongLiteral (ulong l, Location loc) : base (l, loc)
298 public override Expression DoResolve (EmitContext ec)
300 type = TypeManager.uint64_type;
304 public override bool IsLiteral {
309 public class FloatLiteral : FloatConstant {
311 public FloatLiteral (float f, Location loc) : base (f, loc)
315 public override Expression DoResolve (EmitContext ec)
317 type = TypeManager.float_type;
321 public override bool IsLiteral {
327 public class DoubleLiteral : DoubleConstant {
328 public DoubleLiteral (double d, Location loc) : base (d, loc)
332 public override Expression DoResolve (EmitContext ec)
334 type = TypeManager.double_type;
339 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
341 if (target == TypeManager.float_type) {
342 Error_664 (loc, "float", "f");
346 if (target == TypeManager.decimal_type) {
347 Error_664 (loc, "decimal", "m");
351 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
354 static void Error_664 (Location loc, string type, string suffix)
356 Report.Error (664, loc,
357 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
361 public override bool IsLiteral {
367 public class DecimalLiteral : DecimalConstant {
368 public DecimalLiteral (decimal d, Location loc) : base (d, loc)
372 public override Expression DoResolve (EmitContext ec)
374 type = TypeManager.decimal_type;
378 public override bool IsLiteral {
383 public class StringLiteral : StringConstant {
384 public StringLiteral (string s, Location loc) : base (s, loc)
388 public override Expression DoResolve (EmitContext ec)
390 type = TypeManager.string_type;
395 public override bool IsLiteral {