2 // literal.cs: Literal representation for the IL tree.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
10 // Notice that during parsing we create objects of type Literal, but the
11 // types are not loaded (thats why the Resolve method has to assign the
12 // type at that point).
14 // Literals differ from the constants in that we know we encountered them
15 // as a literal in the source code (and some extra rules apply there) and
16 // they have to be resolved (since during parsing we have not loaded the
17 // types yet) while constants are created only after types have been loaded
18 // and are fully resolved when born.
22 using System
.Reflection
;
23 using System
.Reflection
.Emit
;
26 // I put System.Null just so we do not have to special case it on
27 // TypeManager.CSharpName
31 // Represents the Null Type, just used as a placeholder for the type in NullLiteral
37 namespace Mono
.CSharp
{
40 // The NullType just exists to compare type equality, and for
41 // expressions that might have the `null type'
43 public class NullType
{
47 // The null Literal constant
49 public class NullLiteral
: Constant
{
50 public NullLiteral (Location loc
):
53 eclass
= ExprClass
.Value
;
56 override public string AsString ()
61 public override object GetValue ()
66 public override Expression
DoResolve (EmitContext ec
)
68 type
= TypeManager
.null_type
;
72 public override void Emit (EmitContext ec
)
74 ec
.ig
.Emit (OpCodes
.Ldnull
);
77 public override Constant
Increment ()
79 throw new NotSupportedException ();
82 public override bool IsDefaultValue
{
88 public override bool IsNegative
{
94 public override bool IsZeroInteger
{
98 public override string GetSignatureForError()
103 public override void Error_ValueCannotBeConverted (Location loc
, Type t
, bool expl
)
105 Report
.Error (37, loc
, "Cannot convert null to `{0}' because it is a value type",
106 TypeManager
.CSharpName (t
));
109 public override Constant
ToType (Type type
, Location loc
)
111 if (!type
.IsValueType
&& !TypeManager
.IsEnumType (type
))
114 return base.ToType (type
, loc
);
117 public override Constant
Reduce(bool inCheckedContext
, Type target_type
)
119 if (!TypeManager
.IsValueType (target_type
))
120 return new NullCast (this, target_type
);
127 // A null literal in a pointer context
129 public class NullPointer
: NullLiteral
{
130 public static readonly NullLiteral Null
;
132 static NullPointer ()
134 Null
= new NullPointer ();
137 private NullPointer ():
140 type
= TypeManager
.object_type
;
143 public override void Emit (EmitContext ec
)
145 ILGenerator ig
= ec
.ig
;
147 ig
.Emit (OpCodes
.Ldc_I4_0
);
148 ig
.Emit (OpCodes
.Conv_U
);
152 public class BoolLiteral
: BoolConstant
{
153 public BoolLiteral (bool val
, Location loc
) : base (val
, loc
)
157 public override Expression
DoResolve (EmitContext ec
)
159 type
= TypeManager
.bool_type
;
164 public class CharLiteral
: CharConstant
{
165 public CharLiteral (char c
, Location loc
) : base (c
, loc
)
169 public override Expression
DoResolve (EmitContext ec
)
171 type
= TypeManager
.char_type
;
176 public class IntLiteral
: IntConstant
{
177 public IntLiteral (int l
, Location loc
) : base (l
, loc
)
181 public override Expression
DoResolve (EmitContext ec
)
183 type
= TypeManager
.int32_type
;
188 public class UIntLiteral
: UIntConstant
{
189 public UIntLiteral (uint l
, Location loc
) : base (l
, loc
)
193 public override Expression
DoResolve (EmitContext ec
)
195 type
= TypeManager
.uint32_type
;
200 public class LongLiteral
: LongConstant
{
201 public LongLiteral (long l
, Location loc
) : base (l
, loc
)
205 public override Expression
DoResolve (EmitContext ec
)
207 type
= TypeManager
.int64_type
;
213 public class ULongLiteral
: ULongConstant
{
214 public ULongLiteral (ulong l
, Location loc
) : base (l
, loc
)
218 public override Expression
DoResolve (EmitContext ec
)
220 type
= TypeManager
.uint64_type
;
225 public class FloatLiteral
: FloatConstant
{
227 public FloatLiteral (float f
, Location loc
) : base (f
, loc
)
231 public override Expression
DoResolve (EmitContext ec
)
233 type
= TypeManager
.float_type
;
238 public class DoubleLiteral
: DoubleConstant
{
239 public DoubleLiteral (double d
, Location loc
) : base (d
, loc
)
243 public override Expression
DoResolve (EmitContext ec
)
245 type
= TypeManager
.double_type
;
250 public override void Error_ValueCannotBeConverted (Location loc
, Type target
, bool expl
)
252 if (target
== TypeManager
.float_type
) {
253 Error_664 (loc
, "float", "f");
257 if (target
== TypeManager
.decimal_type
) {
258 Error_664 (loc
, "decimal", "m");
262 base.Error_ValueCannotBeConverted (loc
, target
, expl
);
265 static void Error_664 (Location loc
, string type
, string suffix
)
267 Report
.Error (664, loc
,
268 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
273 public class DecimalLiteral
: DecimalConstant
{
274 public DecimalLiteral (decimal d
, Location loc
) : base (d
, loc
)
278 public override Expression
DoResolve (EmitContext ec
)
280 type
= TypeManager
.decimal_type
;
285 public class StringLiteral
: StringConstant
{
286 public StringLiteral (string s
, Location loc
) : base (s
, loc
)
290 public override Expression
DoResolve (EmitContext ec
)
292 type
= TypeManager
.string_type
;