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 public class NullLiteral
: NullConstant
36 // Default type of null is an object
38 public NullLiteral (Location loc
)
39 : base (typeof (NullLiteral
), loc
)
43 public override Expression
CreateExpressionTree (ResolveContext ec
)
45 // Optimized version, also avoids referencing literal internal type
46 Arguments args
= new Arguments (1);
47 args
.Add (new Argument (this));
48 return CreateExpressionFactoryCall (ec
, "Constant", args
);
51 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type t
, bool expl
)
53 if (TypeManager
.IsGenericParameter (t
)) {
54 ec
.Report
.Error(403, loc
,
55 "Cannot convert null to the type parameter `{0}' because it could be a value " +
56 "type. Consider using `default ({0})' instead", t
.Name
);
60 if (TypeManager
.IsValueType (t
)) {
61 ec
.Report
.Error(37, loc
, "Cannot convert null to `{0}' because it is a value type",
62 TypeManager
.CSharpName(t
));
66 base.Error_ValueCannotBeConverted (ec
, loc
, t
, expl
);
69 public override Constant
ConvertImplicitly (ResolveContext rc
, Type targetType
)
72 // Null literal is of object type
74 if (targetType
== TypeManager
.object_type
)
77 return base.ConvertImplicitly (rc
, targetType
);
80 public override bool IsLiteral
{
84 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
86 return System
.Linq
.Expressions
.Expression
.Constant (null);
91 // A null literal in a pointer context
93 class NullPointer
: NullLiteral
{
94 public NullPointer (Location loc
):
97 type
= TypeManager
.object_type
;
100 public override void Emit (EmitContext ec
)
102 ILGenerator ig
= ec
.ig
;
105 // Emits null pointer
107 ig
.Emit (OpCodes
.Ldc_I4_0
);
108 ig
.Emit (OpCodes
.Conv_U
);
112 public class BoolLiteral
: BoolConstant
{
113 public BoolLiteral (bool val
, Location loc
) : base (val
, loc
)
117 public override bool IsLiteral
{
122 public class CharLiteral
: CharConstant
{
123 public CharLiteral (char c
, Location loc
) : base (c
, loc
)
127 public override bool IsLiteral
{
132 public class IntLiteral
: IntConstant
{
133 public IntLiteral (int l
, Location loc
) : base (l
, loc
)
137 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
140 // The 0 literal can be converted to an enum value
142 if (Value
== 0 && TypeManager
.IsEnumType (type
)) {
143 Constant c
= ConvertImplicitly (rc
, TypeManager
.GetEnumUnderlyingType (type
));
147 return new EnumConstant (c
, type
).Resolve (rc
);
150 return base.ConvertImplicitly (rc
, type
);
153 public override bool IsLiteral
{
158 public class UIntLiteral
: UIntConstant
{
159 public UIntLiteral (uint l
, Location loc
) : base (l
, loc
)
163 public override bool IsLiteral
{
168 public class LongLiteral
: LongConstant
{
169 public LongLiteral (long l
, Location loc
) : base (l
, loc
)
173 public override bool IsLiteral
{
178 public class ULongLiteral
: ULongConstant
{
179 public ULongLiteral (ulong l
, Location loc
) : base (l
, loc
)
183 public override bool IsLiteral
{
188 public class FloatLiteral
: FloatConstant
{
190 public FloatLiteral (float f
, Location loc
) : base (f
, loc
)
194 public override bool IsLiteral
{
200 public class DoubleLiteral
: DoubleConstant
{
201 public DoubleLiteral (double d
, Location loc
) : base (d
, loc
)
205 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
207 if (target
== TypeManager
.float_type
) {
208 Error_664 (ec
, loc
, "float", "f");
212 if (target
== TypeManager
.decimal_type
) {
213 Error_664 (ec
, loc
, "decimal", "m");
217 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
220 static void Error_664 (ResolveContext ec
, Location loc
, string type
, string suffix
)
222 ec
.Report
.Error (664, loc
,
223 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
227 public override bool IsLiteral
{
233 public class DecimalLiteral
: DecimalConstant
{
234 public DecimalLiteral (decimal d
, Location loc
) : base (d
, loc
)
238 public override bool IsLiteral
{
243 public class StringLiteral
: StringConstant
{
244 public StringLiteral (string s
, Location loc
) : base (s
, loc
)
248 public override bool IsLiteral
{