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 (Type targetType
)
72 // Null literal is of object type
74 if (targetType
== TypeManager
.object_type
)
77 return base.ConvertImplicitly (targetType
);
80 public override bool IsLiteral
{
85 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
87 return System
.Linq
.Expressions
.Expression
.Constant (null);
93 // A null literal in a pointer context
95 class NullPointer
: NullLiteral
{
96 public NullPointer (Location loc
):
99 type
= TypeManager
.object_type
;
102 public override void Emit (EmitContext ec
)
104 ILGenerator ig
= ec
.ig
;
107 // Emits null pointer
109 ig
.Emit (OpCodes
.Ldc_I4_0
);
110 ig
.Emit (OpCodes
.Conv_U
);
114 public class BoolLiteral
: BoolConstant
{
115 public BoolLiteral (bool val
, Location loc
) : base (val
, loc
)
119 public override Expression
DoResolve (ResolveContext ec
)
121 type
= TypeManager
.bool_type
;
125 public override bool IsLiteral
{
130 public class CharLiteral
: CharConstant
{
131 public CharLiteral (char c
, Location loc
) : base (c
, loc
)
135 public override Expression
DoResolve (ResolveContext ec
)
137 type
= TypeManager
.char_type
;
141 public override bool IsLiteral
{
146 public class IntLiteral
: IntConstant
{
147 public IntLiteral (int l
, Location loc
) : base (l
, loc
)
151 public override Expression
DoResolve (ResolveContext ec
)
153 type
= TypeManager
.int32_type
;
157 public override Constant
ConvertImplicitly (Type type
)
160 /// The 0 literal can be converted to an enum value,
162 if (Value
== 0 && TypeManager
.IsEnumType (type
)) {
163 Constant c
= ConvertImplicitly (TypeManager
.GetEnumUnderlyingType (type
));
167 return new EnumConstant (c
, type
);
169 return base.ConvertImplicitly (type
);
172 public override bool IsLiteral
{
177 public class UIntLiteral
: UIntConstant
{
178 public UIntLiteral (uint l
, Location loc
) : base (l
, loc
)
182 public override Expression
DoResolve (ResolveContext ec
)
184 type
= TypeManager
.uint32_type
;
188 public override bool IsLiteral
{
193 public class LongLiteral
: LongConstant
{
194 public LongLiteral (long l
, Location loc
) : base (l
, loc
)
198 public override Expression
DoResolve (ResolveContext ec
)
200 type
= TypeManager
.int64_type
;
204 public override bool IsLiteral
{
209 public class ULongLiteral
: ULongConstant
{
210 public ULongLiteral (ulong l
, Location loc
) : base (l
, loc
)
214 public override Expression
DoResolve (ResolveContext ec
)
216 type
= TypeManager
.uint64_type
;
220 public override bool IsLiteral
{
225 public class FloatLiteral
: FloatConstant
{
227 public FloatLiteral (float f
, Location loc
) : base (f
, loc
)
231 public override Expression
DoResolve (ResolveContext ec
)
233 type
= TypeManager
.float_type
;
237 public override bool IsLiteral
{
243 public class DoubleLiteral
: DoubleConstant
{
244 public DoubleLiteral (double d
, Location loc
) : base (d
, loc
)
248 public override Expression
DoResolve (ResolveContext ec
)
250 type
= TypeManager
.double_type
;
255 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
257 if (target
== TypeManager
.float_type
) {
258 Error_664 (ec
, loc
, "float", "f");
262 if (target
== TypeManager
.decimal_type
) {
263 Error_664 (ec
, loc
, "decimal", "m");
267 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
270 static void Error_664 (ResolveContext ec
, Location loc
, string type
, string suffix
)
272 ec
.Report
.Error (664, loc
,
273 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
277 public override bool IsLiteral
{
283 public class DecimalLiteral
: DecimalConstant
{
284 public DecimalLiteral (decimal d
, Location loc
) : base (d
, loc
)
288 public override Expression
DoResolve (ResolveContext ec
)
290 type
= TypeManager
.decimal_type
;
294 public override bool IsLiteral
{
299 public class StringLiteral
: StringConstant
{
300 public StringLiteral (string s
, Location loc
) : base (s
, loc
)
304 public override Expression
DoResolve (ResolveContext ec
)
306 type
= TypeManager
.string_type
;
311 public override bool IsLiteral
{