2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
12 namespace Mono
.CSharp
{
15 using System
.Reflection
.Emit
;
16 using System
.Collections
;
19 /// Base class for constants and literals.
21 public abstract class Constant
: Expression
{
23 protected Constant (Location loc
)
29 /// This is different from ToString in that ToString
30 /// is supposed to be there for debugging purposes,
31 /// and is not guaranteed to be useful for anything else,
32 /// AsString() will provide something that can be used
33 /// for round-tripping C# code. Maybe it can be used
34 /// for IL assembly as well.
36 public abstract string AsString ();
38 override public string ToString ()
40 return this.GetType ().Name
+ " (" + AsString () + ")";
43 public override bool GetAttributableValue (ResolveContext ec
, Type value_type
, out object value)
45 if (value_type
== TypeManager
.object_type
) {
46 value = GetTypedValue ();
50 Constant c
= ImplicitConversionRequired (ec
, value_type
, loc
);
56 value = c
.GetTypedValue ();
61 /// This is used to obtain the actual value of the literal
62 /// cast into an object.
64 public abstract object GetValue ();
66 public virtual object GetTypedValue ()
72 /// Constants are always born in a fully resolved state
74 public override Expression
DoResolve (ResolveContext ec
)
79 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
81 if (!expl
&& IsLiteral
&&
82 (TypeManager
.IsPrimitiveType (target
) || type
== TypeManager
.decimal_type
) &&
83 (TypeManager
.IsPrimitiveType (type
) || type
== TypeManager
.decimal_type
)) {
84 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
85 AsString (), TypeManager
.CSharpName (target
));
87 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
91 public Constant
ImplicitConversionRequired (ResolveContext ec
, Type type
, Location loc
)
93 Constant c
= ConvertImplicitly (type
);
95 Error_ValueCannotBeConverted (ec
, loc
, type
, false);
99 public virtual Constant
ConvertImplicitly (Type type
)
101 if (this.type
== type
)
104 if (Convert
.ImplicitNumericConversion (this, type
) == null)
108 object constant_value
= TypeManager
.ChangeType (GetValue (), type
, out fail
);
111 // We should always catch the error before this is ever
112 // reached, by calling Convert.ImplicitStandardConversionExists
114 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
115 TypeManager
.CSharpName (Type
), TypeManager
.CSharpName (type
));
118 return CreateConstant (type
, constant_value
, loc
);
121 /// Returns a constant instance based on Type
122 /// The returned value is already resolved.
123 public static Constant
CreateConstant (Type t
, object v
, Location loc
)
125 if (t
== TypeManager
.int32_type
)
126 return new IntConstant ((int) v
, loc
);
127 if (t
== TypeManager
.string_type
)
128 return new StringConstant ((string) v
, loc
);
129 if (t
== TypeManager
.uint32_type
)
130 return new UIntConstant ((uint) v
, loc
);
131 if (t
== TypeManager
.int64_type
)
132 return new LongConstant ((long) v
, loc
);
133 if (t
== TypeManager
.uint64_type
)
134 return new ULongConstant ((ulong) v
, loc
);
135 if (t
== TypeManager
.float_type
)
136 return new FloatConstant ((float) v
, loc
);
137 if (t
== TypeManager
.double_type
)
138 return new DoubleConstant ((double) v
, loc
);
139 if (t
== TypeManager
.short_type
)
140 return new ShortConstant ((short)v
, loc
);
141 if (t
== TypeManager
.ushort_type
)
142 return new UShortConstant ((ushort)v
, loc
);
143 if (t
== TypeManager
.sbyte_type
)
144 return new SByteConstant ((sbyte)v
, loc
);
145 if (t
== TypeManager
.byte_type
)
146 return new ByteConstant ((byte)v
, loc
);
147 if (t
== TypeManager
.char_type
)
148 return new CharConstant ((char)v
, loc
);
149 if (t
== TypeManager
.bool_type
)
150 return new BoolConstant ((bool) v
, loc
);
151 if (t
== TypeManager
.decimal_type
)
152 return new DecimalConstant ((decimal) v
, loc
);
153 if (TypeManager
.IsEnumType (t
)) {
154 Type real_type
= TypeManager
.GetEnumUnderlyingType (t
);
155 return new EnumConstant (CreateConstant (real_type
, v
, loc
), t
);
158 if (TypeManager
.IsNullableType (t
))
159 return Nullable
.LiftedNull
.Create (t
, loc
);
161 if (TypeManager
.IsReferenceType (t
))
162 return new NullConstant (t
, loc
);
165 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
166 v
, TypeManager
.CSharpName (t
));
169 public override Expression
CreateExpressionTree (ResolveContext ec
)
171 Arguments args
= new Arguments (2);
172 args
.Add (new Argument (this));
173 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
175 return CreateExpressionFactoryCall (ec
, "Constant", args
);
180 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
181 /// It throws OverflowException
183 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
184 public abstract Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
);
187 /// Attempts to do a compile-time folding of a constant cast.
189 public Constant
TryReduce (ResolveContext ec
, Type target_type
, Location loc
)
192 return TryReduce (ec
, target_type
);
194 catch (OverflowException
) {
195 if (ec
.ConstantCheckState
) {
196 ec
.Report
.Error (221, loc
, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
197 GetValue ().ToString (), TypeManager
.CSharpName (target_type
));
199 Error_ValueCannotBeConverted (ec
, loc
, target_type
, false);
202 return New
.Constantify (target_type
);
206 Constant
TryReduce (ResolveContext ec
, Type target_type
)
208 if (Type
== target_type
)
211 if (TypeManager
.IsEnumType (target_type
)) {
212 Constant c
= TryReduce (ec
, TypeManager
.GetEnumUnderlyingType (target_type
));
216 return new EnumConstant (c
, target_type
);
219 return ConvertExplicitly (ec
.ConstantCheckState
, target_type
);
222 public abstract Constant
Increment ();
225 /// Need to pass type as the constant can require a boxing
226 /// and in such case no optimization is possible
228 public bool IsDefaultInitializer (Type type
)
231 return IsDefaultValue
;
233 return this is NullLiteral
;
236 public abstract bool IsDefaultValue
{
240 public abstract bool IsNegative
{
245 // When constant is declared as literal
247 public virtual bool IsLiteral
{
248 get { return false; }
252 // Returns true iff 1) the stack type of this is one of Object,
253 // int32, int64 and 2) this == 0 or this == null.
255 public virtual bool IsZeroInteger
{
256 get { return false; }
259 public override void EmitSideEffect (EmitContext ec
)
264 protected override void CloneTo (CloneContext clonectx
, Expression target
)
266 // CloneTo: Nothing, we do not keep any state on this expression
270 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
272 return System
.Linq
.Expressions
.Expression
.Constant (GetTypedValue (), type
);
276 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
278 // A constant cannot be of generic type
282 public abstract class IntegralConstant
: Constant
{
283 protected IntegralConstant (Location loc
) :
288 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
291 ConvertExplicitly (true, target
);
292 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
296 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
297 GetValue ().ToString (), TypeManager
.CSharpName (target
));
302 public class BoolConstant
: Constant
{
303 public readonly bool Value
;
305 public BoolConstant (bool val
, Location loc
):
308 type
= TypeManager
.bool_type
;
309 eclass
= ExprClass
.Value
;
314 override public string AsString ()
316 return Value
? "true" : "false";
319 public override object GetValue ()
321 return (object) Value
;
325 public override void Emit (EmitContext ec
)
328 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
330 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
333 public override Constant
Increment ()
335 throw new NotSupportedException ();
338 public override bool IsDefaultValue
{
344 public override bool IsNegative
{
350 public override bool IsZeroInteger
{
351 get { return Value == false; }
354 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
361 public class ByteConstant
: IntegralConstant
{
362 public readonly byte Value
;
364 public ByteConstant (byte v
, Location loc
):
367 type
= TypeManager
.byte_type
;
368 eclass
= ExprClass
.Value
;
372 public override void Emit (EmitContext ec
)
374 IntLiteral
.EmitInt (ec
.ig
, Value
);
377 public override string AsString ()
379 return Value
.ToString ();
382 public override object GetValue ()
387 public override Constant
Increment ()
389 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
392 public override bool IsDefaultValue
{
398 public override bool IsNegative
{
404 public override bool IsZeroInteger
{
405 get { return Value == 0; }
408 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
410 if (target_type
== TypeManager
.sbyte_type
) {
411 if (in_checked_context
){
412 if (Value
> SByte
.MaxValue
)
413 throw new OverflowException ();
415 return new SByteConstant ((sbyte) Value
, Location
);
417 if (target_type
== TypeManager
.short_type
)
418 return new ShortConstant ((short) Value
, Location
);
419 if (target_type
== TypeManager
.ushort_type
)
420 return new UShortConstant ((ushort) Value
, Location
);
421 if (target_type
== TypeManager
.int32_type
)
422 return new IntConstant ((int) Value
, Location
);
423 if (target_type
== TypeManager
.uint32_type
)
424 return new UIntConstant ((uint) Value
, Location
);
425 if (target_type
== TypeManager
.int64_type
)
426 return new LongConstant ((long) Value
, Location
);
427 if (target_type
== TypeManager
.uint64_type
)
428 return new ULongConstant ((ulong) Value
, Location
);
429 if (target_type
== TypeManager
.float_type
)
430 return new FloatConstant ((float) Value
, Location
);
431 if (target_type
== TypeManager
.double_type
)
432 return new DoubleConstant ((double) Value
, Location
);
433 if (target_type
== TypeManager
.char_type
)
434 return new CharConstant ((char) Value
, Location
);
435 if (target_type
== TypeManager
.decimal_type
)
436 return new DecimalConstant ((decimal) Value
, Location
);
443 public class CharConstant
: Constant
{
444 public readonly char Value
;
446 public CharConstant (char v
, Location loc
):
449 type
= TypeManager
.char_type
;
450 eclass
= ExprClass
.Value
;
454 public override void Emit (EmitContext ec
)
456 IntLiteral
.EmitInt (ec
.ig
, Value
);
459 static public string descape (char c
)
485 return c
.ToString ();
488 public override string AsString ()
490 return "\"" + descape (Value
) + "\"";
493 public override object GetValue ()
498 public override Constant
Increment ()
500 return new CharConstant (checked ((char)(Value
+ 1)), loc
);
503 public override bool IsDefaultValue
{
509 public override bool IsNegative
{
515 public override bool IsZeroInteger
{
516 get { return Value == '\0'; }
519 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
521 if (target_type
== TypeManager
.byte_type
) {
522 if (in_checked_context
){
523 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
524 throw new OverflowException ();
526 return new ByteConstant ((byte) Value
, Location
);
528 if (target_type
== TypeManager
.sbyte_type
) {
529 if (in_checked_context
){
530 if (Value
> SByte
.MaxValue
)
531 throw new OverflowException ();
533 return new SByteConstant ((sbyte) Value
, Location
);
535 if (target_type
== TypeManager
.short_type
) {
536 if (in_checked_context
){
537 if (Value
> Int16
.MaxValue
)
538 throw new OverflowException ();
540 return new ShortConstant ((short) Value
, Location
);
542 if (target_type
== TypeManager
.int32_type
)
543 return new IntConstant ((int) Value
, Location
);
544 if (target_type
== TypeManager
.uint32_type
)
545 return new UIntConstant ((uint) Value
, Location
);
546 if (target_type
== TypeManager
.int64_type
)
547 return new LongConstant ((long) Value
, Location
);
548 if (target_type
== TypeManager
.uint64_type
)
549 return new ULongConstant ((ulong) Value
, Location
);
550 if (target_type
== TypeManager
.float_type
)
551 return new FloatConstant ((float) Value
, Location
);
552 if (target_type
== TypeManager
.double_type
)
553 return new DoubleConstant ((double) Value
, Location
);
554 if (target_type
== TypeManager
.decimal_type
)
555 return new DecimalConstant ((decimal) Value
, Location
);
562 public class SByteConstant
: IntegralConstant
{
563 public readonly sbyte Value
;
565 public SByteConstant (sbyte v
, Location loc
):
568 type
= TypeManager
.sbyte_type
;
569 eclass
= ExprClass
.Value
;
573 public override void Emit (EmitContext ec
)
575 IntLiteral
.EmitInt (ec
.ig
, Value
);
578 public override string AsString ()
580 return Value
.ToString ();
583 public override object GetValue ()
588 public override Constant
Increment ()
590 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
593 public override bool IsDefaultValue
{
599 public override bool IsNegative
{
605 public override bool IsZeroInteger
{
606 get { return Value == 0; }
609 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
611 if (target_type
== TypeManager
.byte_type
) {
612 if (in_checked_context
&& Value
< 0)
613 throw new OverflowException ();
614 return new ByteConstant ((byte) Value
, Location
);
616 if (target_type
== TypeManager
.short_type
)
617 return new ShortConstant ((short) Value
, Location
);
618 if (target_type
== TypeManager
.ushort_type
) {
619 if (in_checked_context
&& Value
< 0)
620 throw new OverflowException ();
621 return new UShortConstant ((ushort) Value
, Location
);
622 } if (target_type
== TypeManager
.int32_type
)
623 return new IntConstant ((int) Value
, Location
);
624 if (target_type
== TypeManager
.uint32_type
) {
625 if (in_checked_context
&& Value
< 0)
626 throw new OverflowException ();
627 return new UIntConstant ((uint) Value
, Location
);
628 } if (target_type
== TypeManager
.int64_type
)
629 return new LongConstant ((long) Value
, Location
);
630 if (target_type
== TypeManager
.uint64_type
) {
631 if (in_checked_context
&& Value
< 0)
632 throw new OverflowException ();
633 return new ULongConstant ((ulong) Value
, Location
);
635 if (target_type
== TypeManager
.float_type
)
636 return new FloatConstant ((float) Value
, Location
);
637 if (target_type
== TypeManager
.double_type
)
638 return new DoubleConstant ((double) Value
, Location
);
639 if (target_type
== TypeManager
.char_type
) {
640 if (in_checked_context
&& Value
< 0)
641 throw new OverflowException ();
642 return new CharConstant ((char) Value
, Location
);
644 if (target_type
== TypeManager
.decimal_type
)
645 return new DecimalConstant ((decimal) Value
, Location
);
652 public class ShortConstant
: IntegralConstant
{
653 public readonly short Value
;
655 public ShortConstant (short v
, Location loc
):
658 type
= TypeManager
.short_type
;
659 eclass
= ExprClass
.Value
;
663 public override void Emit (EmitContext ec
)
665 IntLiteral
.EmitInt (ec
.ig
, Value
);
668 public override string AsString ()
670 return Value
.ToString ();
673 public override object GetValue ()
678 public override Constant
Increment ()
680 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
683 public override bool IsDefaultValue
{
689 public override bool IsZeroInteger
{
690 get { return Value == 0; }
693 public override bool IsNegative
{
699 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
701 if (target_type
== TypeManager
.byte_type
) {
702 if (in_checked_context
){
703 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
704 throw new OverflowException ();
706 return new ByteConstant ((byte) Value
, Location
);
708 if (target_type
== TypeManager
.sbyte_type
) {
709 if (in_checked_context
){
710 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
711 throw new OverflowException ();
713 return new SByteConstant ((sbyte) Value
, Location
);
715 if (target_type
== TypeManager
.ushort_type
) {
716 if (in_checked_context
&& Value
< 0)
717 throw new OverflowException ();
719 return new UShortConstant ((ushort) Value
, Location
);
721 if (target_type
== TypeManager
.int32_type
)
722 return new IntConstant ((int) Value
, Location
);
723 if (target_type
== TypeManager
.uint32_type
) {
724 if (in_checked_context
&& Value
< 0)
725 throw new OverflowException ();
726 return new UIntConstant ((uint) Value
, Location
);
728 if (target_type
== TypeManager
.int64_type
)
729 return new LongConstant ((long) Value
, Location
);
730 if (target_type
== TypeManager
.uint64_type
) {
731 if (in_checked_context
&& Value
< 0)
732 throw new OverflowException ();
733 return new ULongConstant ((ulong) Value
, Location
);
735 if (target_type
== TypeManager
.float_type
)
736 return new FloatConstant ((float) Value
, Location
);
737 if (target_type
== TypeManager
.double_type
)
738 return new DoubleConstant ((double) Value
, Location
);
739 if (target_type
== TypeManager
.char_type
) {
740 if (in_checked_context
){
741 if (Value
< Char
.MinValue
)
742 throw new OverflowException ();
744 return new CharConstant ((char) Value
, Location
);
746 if (target_type
== TypeManager
.decimal_type
)
747 return new DecimalConstant ((decimal) Value
, Location
);
754 public class UShortConstant
: IntegralConstant
{
755 public readonly ushort Value
;
757 public UShortConstant (ushort v
, Location loc
):
760 type
= TypeManager
.ushort_type
;
761 eclass
= ExprClass
.Value
;
765 public override void Emit (EmitContext ec
)
767 IntLiteral
.EmitInt (ec
.ig
, Value
);
770 public override string AsString ()
772 return Value
.ToString ();
775 public override object GetValue ()
780 public override Constant
Increment ()
782 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
785 public override bool IsDefaultValue
{
791 public override bool IsNegative
{
797 public override bool IsZeroInteger
{
798 get { return Value == 0; }
801 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
803 if (target_type
== TypeManager
.byte_type
) {
804 if (in_checked_context
){
805 if (Value
> Byte
.MaxValue
)
806 throw new OverflowException ();
808 return new ByteConstant ((byte) Value
, Location
);
810 if (target_type
== TypeManager
.sbyte_type
) {
811 if (in_checked_context
){
812 if (Value
> SByte
.MaxValue
)
813 throw new OverflowException ();
815 return new SByteConstant ((sbyte) Value
, Location
);
817 if (target_type
== TypeManager
.short_type
) {
818 if (in_checked_context
){
819 if (Value
> Int16
.MaxValue
)
820 throw new OverflowException ();
822 return new ShortConstant ((short) Value
, Location
);
824 if (target_type
== TypeManager
.int32_type
)
825 return new IntConstant ((int) Value
, Location
);
826 if (target_type
== TypeManager
.uint32_type
)
827 return new UIntConstant ((uint) Value
, Location
);
828 if (target_type
== TypeManager
.int64_type
)
829 return new LongConstant ((long) Value
, Location
);
830 if (target_type
== TypeManager
.uint64_type
)
831 return new ULongConstant ((ulong) Value
, Location
);
832 if (target_type
== TypeManager
.float_type
)
833 return new FloatConstant ((float) Value
, Location
);
834 if (target_type
== TypeManager
.double_type
)
835 return new DoubleConstant ((double) Value
, Location
);
836 if (target_type
== TypeManager
.char_type
) {
837 if (in_checked_context
){
838 if (Value
> Char
.MaxValue
)
839 throw new OverflowException ();
841 return new CharConstant ((char) Value
, Location
);
843 if (target_type
== TypeManager
.decimal_type
)
844 return new DecimalConstant ((decimal) Value
, Location
);
850 public class IntConstant
: IntegralConstant
{
851 public readonly int Value
;
853 public IntConstant (int v
, Location loc
):
856 type
= TypeManager
.int32_type
;
857 eclass
= ExprClass
.Value
;
861 static public void EmitInt (ILGenerator ig
, int i
)
865 ig
.Emit (OpCodes
.Ldc_I4_M1
);
869 ig
.Emit (OpCodes
.Ldc_I4_0
);
873 ig
.Emit (OpCodes
.Ldc_I4_1
);
877 ig
.Emit (OpCodes
.Ldc_I4_2
);
881 ig
.Emit (OpCodes
.Ldc_I4_3
);
885 ig
.Emit (OpCodes
.Ldc_I4_4
);
889 ig
.Emit (OpCodes
.Ldc_I4_5
);
893 ig
.Emit (OpCodes
.Ldc_I4_6
);
897 ig
.Emit (OpCodes
.Ldc_I4_7
);
901 ig
.Emit (OpCodes
.Ldc_I4_8
);
905 if (i
>= -128 && i
<= 127){
906 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
908 ig
.Emit (OpCodes
.Ldc_I4
, i
);
913 public override void Emit (EmitContext ec
)
915 EmitInt (ec
.ig
, Value
);
918 public override string AsString ()
920 return Value
.ToString ();
923 public override object GetValue ()
928 public override Constant
Increment ()
930 return new IntConstant (checked(Value
+ 1), loc
);
933 public override bool IsDefaultValue
{
939 public override bool IsNegative
{
945 public override bool IsZeroInteger
{
946 get { return Value == 0; }
949 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
951 if (target_type
== TypeManager
.byte_type
) {
952 if (in_checked_context
){
953 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
954 throw new OverflowException ();
956 return new ByteConstant ((byte) Value
, Location
);
958 if (target_type
== TypeManager
.sbyte_type
) {
959 if (in_checked_context
){
960 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
961 throw new OverflowException ();
963 return new SByteConstant ((sbyte) Value
, Location
);
965 if (target_type
== TypeManager
.short_type
) {
966 if (in_checked_context
){
967 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
968 throw new OverflowException ();
970 return new ShortConstant ((short) Value
, Location
);
972 if (target_type
== TypeManager
.ushort_type
) {
973 if (in_checked_context
){
974 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
975 throw new OverflowException ();
977 return new UShortConstant ((ushort) Value
, Location
);
979 if (target_type
== TypeManager
.uint32_type
) {
980 if (in_checked_context
){
981 if (Value
< UInt32
.MinValue
)
982 throw new OverflowException ();
984 return new UIntConstant ((uint) Value
, Location
);
986 if (target_type
== TypeManager
.int64_type
)
987 return new LongConstant ((long) Value
, Location
);
988 if (target_type
== TypeManager
.uint64_type
) {
989 if (in_checked_context
&& Value
< 0)
990 throw new OverflowException ();
991 return new ULongConstant ((ulong) Value
, Location
);
993 if (target_type
== TypeManager
.float_type
)
994 return new FloatConstant ((float) Value
, Location
);
995 if (target_type
== TypeManager
.double_type
)
996 return new DoubleConstant ((double) Value
, Location
);
997 if (target_type
== TypeManager
.char_type
) {
998 if (in_checked_context
){
999 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1000 throw new OverflowException ();
1002 return new CharConstant ((char) Value
, Location
);
1004 if (target_type
== TypeManager
.decimal_type
)
1005 return new DecimalConstant ((decimal) Value
, Location
);
1010 public override Constant
ConvertImplicitly (Type type
)
1012 if (this.type
== type
)
1015 Constant c
= TryImplicitIntConversion (type
);
1019 return base.ConvertImplicitly (type
);
1023 /// Attempts to perform an implicit constant conversion of the IntConstant
1024 /// into a different data type using casts (See Implicit Constant
1025 /// Expression Conversions)
1027 Constant
TryImplicitIntConversion (Type target_type
)
1029 if (target_type
== TypeManager
.sbyte_type
) {
1030 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1031 return new SByteConstant ((sbyte) Value
, loc
);
1033 else if (target_type
== TypeManager
.byte_type
) {
1034 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1035 return new ByteConstant ((byte) Value
, loc
);
1037 else if (target_type
== TypeManager
.short_type
) {
1038 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1039 return new ShortConstant ((short) Value
, loc
);
1041 else if (target_type
== TypeManager
.ushort_type
) {
1042 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1043 return new UShortConstant ((ushort) Value
, loc
);
1045 else if (target_type
== TypeManager
.uint32_type
) {
1047 return new UIntConstant ((uint) Value
, loc
);
1049 else if (target_type
== TypeManager
.uint64_type
) {
1051 // we can optimize this case: a positive int32
1052 // always fits on a uint64. But we need an opcode
1056 return new ULongConstant ((ulong) Value
, loc
);
1058 else if (target_type
== TypeManager
.double_type
)
1059 return new DoubleConstant ((double) Value
, loc
);
1060 else if (target_type
== TypeManager
.float_type
)
1061 return new FloatConstant ((float) Value
, loc
);
1067 public class UIntConstant
: IntegralConstant
{
1068 public readonly uint Value
;
1070 public UIntConstant (uint v
, Location loc
):
1073 type
= TypeManager
.uint32_type
;
1074 eclass
= ExprClass
.Value
;
1078 public override void Emit (EmitContext ec
)
1080 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
1083 public override string AsString ()
1085 return Value
.ToString ();
1088 public override object GetValue ()
1093 public override Constant
Increment ()
1095 return new UIntConstant (checked(Value
+ 1), loc
);
1098 public override bool IsDefaultValue
{
1104 public override bool IsNegative
{
1110 public override bool IsZeroInteger
{
1111 get { return Value == 0; }
1114 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1116 if (target_type
== TypeManager
.byte_type
) {
1117 if (in_checked_context
){
1118 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1119 throw new OverflowException ();
1121 return new ByteConstant ((byte) Value
, Location
);
1123 if (target_type
== TypeManager
.sbyte_type
) {
1124 if (in_checked_context
){
1125 if (Value
> SByte
.MaxValue
)
1126 throw new OverflowException ();
1128 return new SByteConstant ((sbyte) Value
, Location
);
1130 if (target_type
== TypeManager
.short_type
) {
1131 if (in_checked_context
){
1132 if (Value
> Int16
.MaxValue
)
1133 throw new OverflowException ();
1135 return new ShortConstant ((short) Value
, Location
);
1137 if (target_type
== TypeManager
.ushort_type
) {
1138 if (in_checked_context
){
1139 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1140 throw new OverflowException ();
1142 return new UShortConstant ((ushort) Value
, Location
);
1144 if (target_type
== TypeManager
.int32_type
) {
1145 if (in_checked_context
){
1146 if (Value
> Int32
.MaxValue
)
1147 throw new OverflowException ();
1149 return new IntConstant ((int) Value
, Location
);
1151 if (target_type
== TypeManager
.int64_type
)
1152 return new LongConstant ((long) Value
, Location
);
1153 if (target_type
== TypeManager
.uint64_type
)
1154 return new ULongConstant ((ulong) Value
, Location
);
1155 if (target_type
== TypeManager
.float_type
)
1156 return new FloatConstant ((float) Value
, Location
);
1157 if (target_type
== TypeManager
.double_type
)
1158 return new DoubleConstant ((double) Value
, Location
);
1159 if (target_type
== TypeManager
.char_type
) {
1160 if (in_checked_context
){
1161 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1162 throw new OverflowException ();
1164 return new CharConstant ((char) Value
, Location
);
1166 if (target_type
== TypeManager
.decimal_type
)
1167 return new DecimalConstant ((decimal) Value
, Location
);
1174 public class LongConstant
: IntegralConstant
{
1175 public readonly long Value
;
1177 public LongConstant (long v
, Location loc
):
1180 type
= TypeManager
.int64_type
;
1181 eclass
= ExprClass
.Value
;
1185 public override void Emit (EmitContext ec
)
1187 EmitLong (ec
.ig
, Value
);
1190 static public void EmitLong (ILGenerator ig
, long l
)
1192 if (l
>= int.MinValue
&& l
<= int.MaxValue
) {
1193 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1194 ig
.Emit (OpCodes
.Conv_I8
);
1198 if (l
>= 0 && l
<= uint.MaxValue
) {
1199 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1200 ig
.Emit (OpCodes
.Conv_U8
);
1204 ig
.Emit (OpCodes
.Ldc_I8
, l
);
1207 public override string AsString ()
1209 return Value
.ToString ();
1212 public override object GetValue ()
1217 public override Constant
Increment ()
1219 return new LongConstant (checked(Value
+ 1), loc
);
1222 public override bool IsDefaultValue
{
1228 public override bool IsNegative
{
1234 public override bool IsZeroInteger
{
1235 get { return Value == 0; }
1238 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1240 if (target_type
== TypeManager
.byte_type
) {
1241 if (in_checked_context
){
1242 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1243 throw new OverflowException ();
1245 return new ByteConstant ((byte) Value
, Location
);
1247 if (target_type
== TypeManager
.sbyte_type
) {
1248 if (in_checked_context
){
1249 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1250 throw new OverflowException ();
1252 return new SByteConstant ((sbyte) Value
, Location
);
1254 if (target_type
== TypeManager
.short_type
) {
1255 if (in_checked_context
){
1256 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1257 throw new OverflowException ();
1259 return new ShortConstant ((short) Value
, Location
);
1261 if (target_type
== TypeManager
.ushort_type
) {
1262 if (in_checked_context
){
1263 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1264 throw new OverflowException ();
1266 return new UShortConstant ((ushort) Value
, Location
);
1268 if (target_type
== TypeManager
.int32_type
) {
1269 if (in_checked_context
){
1270 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1271 throw new OverflowException ();
1273 return new IntConstant ((int) Value
, Location
);
1275 if (target_type
== TypeManager
.uint32_type
) {
1276 if (in_checked_context
){
1277 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1278 throw new OverflowException ();
1280 return new UIntConstant ((uint) Value
, Location
);
1282 if (target_type
== TypeManager
.uint64_type
) {
1283 if (in_checked_context
&& Value
< 0)
1284 throw new OverflowException ();
1285 return new ULongConstant ((ulong) Value
, Location
);
1287 if (target_type
== TypeManager
.float_type
)
1288 return new FloatConstant ((float) Value
, Location
);
1289 if (target_type
== TypeManager
.double_type
)
1290 return new DoubleConstant ((double) Value
, Location
);
1291 if (target_type
== TypeManager
.char_type
) {
1292 if (in_checked_context
){
1293 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1294 throw new OverflowException ();
1296 return new CharConstant ((char) Value
, Location
);
1298 if (target_type
== TypeManager
.decimal_type
)
1299 return new DecimalConstant ((decimal) Value
, Location
);
1304 public override Constant
ConvertImplicitly (Type type
)
1306 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1307 return new ULongConstant ((ulong) Value
, loc
);
1310 return base.ConvertImplicitly (type
);
1314 public class ULongConstant
: IntegralConstant
{
1315 public readonly ulong Value
;
1317 public ULongConstant (ulong v
, Location loc
):
1320 type
= TypeManager
.uint64_type
;
1321 eclass
= ExprClass
.Value
;
1325 public override void Emit (EmitContext ec
)
1327 ILGenerator ig
= ec
.ig
;
1329 LongLiteral
.EmitLong (ig
, unchecked ((long) Value
));
1332 public override string AsString ()
1334 return Value
.ToString ();
1337 public override object GetValue ()
1342 public override Constant
Increment ()
1344 return new ULongConstant (checked(Value
+ 1), loc
);
1347 public override bool IsDefaultValue
{
1353 public override bool IsNegative
{
1359 public override bool IsZeroInteger
{
1360 get { return Value == 0; }
1363 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1365 if (target_type
== TypeManager
.byte_type
) {
1366 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1367 throw new OverflowException ();
1368 return new ByteConstant ((byte) Value
, Location
);
1370 if (target_type
== TypeManager
.sbyte_type
) {
1371 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1372 throw new OverflowException ();
1373 return new SByteConstant ((sbyte) Value
, Location
);
1375 if (target_type
== TypeManager
.short_type
) {
1376 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1377 throw new OverflowException ();
1378 return new ShortConstant ((short) Value
, Location
);
1380 if (target_type
== TypeManager
.ushort_type
) {
1381 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1382 throw new OverflowException ();
1383 return new UShortConstant ((ushort) Value
, Location
);
1385 if (target_type
== TypeManager
.int32_type
) {
1386 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1387 throw new OverflowException ();
1388 return new IntConstant ((int) Value
, Location
);
1390 if (target_type
== TypeManager
.uint32_type
) {
1391 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1392 throw new OverflowException ();
1393 return new UIntConstant ((uint) Value
, Location
);
1395 if (target_type
== TypeManager
.int64_type
) {
1396 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1397 throw new OverflowException ();
1398 return new LongConstant ((long) Value
, Location
);
1400 if (target_type
== TypeManager
.float_type
)
1401 return new FloatConstant ((float) Value
, Location
);
1402 if (target_type
== TypeManager
.double_type
)
1403 return new DoubleConstant ((double) Value
, Location
);
1404 if (target_type
== TypeManager
.char_type
) {
1405 if (in_checked_context
&& Value
> Char
.MaxValue
)
1406 throw new OverflowException ();
1407 return new CharConstant ((char) Value
, Location
);
1409 if (target_type
== TypeManager
.decimal_type
)
1410 return new DecimalConstant ((decimal) Value
, Location
);
1417 public class FloatConstant
: Constant
{
1420 public FloatConstant (float v
, Location loc
):
1423 type
= TypeManager
.float_type
;
1424 eclass
= ExprClass
.Value
;
1428 public override void Emit (EmitContext ec
)
1430 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
1433 public override string AsString ()
1435 return Value
.ToString ();
1438 public override object GetValue ()
1443 public override Constant
Increment ()
1445 return new FloatConstant (checked(Value
+ 1), loc
);
1448 public override bool IsDefaultValue
{
1454 public override bool IsNegative
{
1460 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1462 if (target_type
== TypeManager
.byte_type
) {
1463 if (in_checked_context
){
1464 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1465 throw new OverflowException ();
1467 return new ByteConstant ((byte) Value
, Location
);
1469 if (target_type
== TypeManager
.sbyte_type
) {
1470 if (in_checked_context
){
1471 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1472 throw new OverflowException ();
1474 return new SByteConstant ((sbyte) Value
, Location
);
1476 if (target_type
== TypeManager
.short_type
) {
1477 if (in_checked_context
){
1478 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1479 throw new OverflowException ();
1481 return new ShortConstant ((short) Value
, Location
);
1483 if (target_type
== TypeManager
.ushort_type
) {
1484 if (in_checked_context
){
1485 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1486 throw new OverflowException ();
1488 return new UShortConstant ((ushort) Value
, Location
);
1490 if (target_type
== TypeManager
.int32_type
) {
1491 if (in_checked_context
){
1492 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1493 throw new OverflowException ();
1495 return new IntConstant ((int) Value
, Location
);
1497 if (target_type
== TypeManager
.uint32_type
) {
1498 if (in_checked_context
){
1499 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1500 throw new OverflowException ();
1502 return new UIntConstant ((uint) Value
, Location
);
1504 if (target_type
== TypeManager
.int64_type
) {
1505 if (in_checked_context
){
1506 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1507 throw new OverflowException ();
1509 return new LongConstant ((long) Value
, Location
);
1511 if (target_type
== TypeManager
.uint64_type
) {
1512 if (in_checked_context
){
1513 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1514 throw new OverflowException ();
1516 return new ULongConstant ((ulong) Value
, Location
);
1518 if (target_type
== TypeManager
.double_type
)
1519 return new DoubleConstant ((double) Value
, Location
);
1520 if (target_type
== TypeManager
.char_type
) {
1521 if (in_checked_context
){
1522 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1523 throw new OverflowException ();
1525 return new CharConstant ((char) Value
, Location
);
1527 if (target_type
== TypeManager
.decimal_type
)
1528 return new DecimalConstant ((decimal) Value
, Location
);
1535 public class DoubleConstant
: Constant
{
1536 public double Value
;
1538 public DoubleConstant (double v
, Location loc
):
1541 type
= TypeManager
.double_type
;
1542 eclass
= ExprClass
.Value
;
1546 public override void Emit (EmitContext ec
)
1548 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
1551 public override string AsString ()
1553 return Value
.ToString ();
1556 public override object GetValue ()
1561 public override Constant
Increment ()
1563 return new DoubleConstant (checked(Value
+ 1), loc
);
1566 public override bool IsDefaultValue
{
1572 public override bool IsNegative
{
1578 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1580 if (target_type
== TypeManager
.byte_type
) {
1581 if (in_checked_context
){
1582 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1583 throw new OverflowException ();
1585 return new ByteConstant ((byte) Value
, Location
);
1587 if (target_type
== TypeManager
.sbyte_type
) {
1588 if (in_checked_context
){
1589 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1590 throw new OverflowException ();
1592 return new SByteConstant ((sbyte) Value
, Location
);
1594 if (target_type
== TypeManager
.short_type
) {
1595 if (in_checked_context
){
1596 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1597 throw new OverflowException ();
1599 return new ShortConstant ((short) Value
, Location
);
1601 if (target_type
== TypeManager
.ushort_type
) {
1602 if (in_checked_context
){
1603 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1604 throw new OverflowException ();
1606 return new UShortConstant ((ushort) Value
, Location
);
1608 if (target_type
== TypeManager
.int32_type
) {
1609 if (in_checked_context
){
1610 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1611 throw new OverflowException ();
1613 return new IntConstant ((int) Value
, Location
);
1615 if (target_type
== TypeManager
.uint32_type
) {
1616 if (in_checked_context
){
1617 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1618 throw new OverflowException ();
1620 return new UIntConstant ((uint) Value
, Location
);
1622 if (target_type
== TypeManager
.int64_type
) {
1623 if (in_checked_context
){
1624 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1625 throw new OverflowException ();
1627 return new LongConstant ((long) Value
, Location
);
1629 if (target_type
== TypeManager
.uint64_type
) {
1630 if (in_checked_context
){
1631 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1632 throw new OverflowException ();
1634 return new ULongConstant ((ulong) Value
, Location
);
1636 if (target_type
== TypeManager
.float_type
)
1637 return new FloatConstant ((float) Value
, Location
);
1638 if (target_type
== TypeManager
.char_type
) {
1639 if (in_checked_context
){
1640 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1641 throw new OverflowException ();
1643 return new CharConstant ((char) Value
, Location
);
1645 if (target_type
== TypeManager
.decimal_type
)
1646 return new DecimalConstant ((decimal) Value
, Location
);
1653 public class DecimalConstant
: Constant
{
1654 public readonly decimal Value
;
1656 public DecimalConstant (decimal d
, Location loc
):
1659 type
= TypeManager
.decimal_type
;
1660 eclass
= ExprClass
.Value
;
1664 override public string AsString ()
1666 return Value
.ToString () + "M";
1669 public override object GetValue ()
1671 return (object) Value
;
1674 public override void Emit (EmitContext ec
)
1676 ILGenerator ig
= ec
.ig
;
1678 int [] words
= decimal.GetBits (Value
);
1679 int power
= (words
[3] >> 16) & 0xff;
1682 if (Value
<= int.MaxValue
&& Value
>= int.MinValue
) {
1683 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1684 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1685 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1687 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1691 IntConstant
.EmitInt (ig
, (int) Value
);
1692 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1696 if (Value
<= long.MaxValue
&& Value
>= long.MinValue
) {
1697 if (TypeManager
.void_decimal_ctor_long_arg
== null) {
1698 TypeManager
.void_decimal_ctor_long_arg
= TypeManager
.GetPredefinedConstructor (
1699 TypeManager
.decimal_type
, loc
, TypeManager
.int64_type
);
1701 if (TypeManager
.void_decimal_ctor_long_arg
== null)
1705 LongConstant
.EmitLong (ig
, (long) Value
);
1706 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_long_arg
);
1711 IntConstant
.EmitInt (ig
, words
[0]);
1712 IntConstant
.EmitInt (ig
, words
[1]);
1713 IntConstant
.EmitInt (ig
, words
[2]);
1716 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1719 IntConstant
.EmitInt (ig
, power
);
1721 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1722 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1723 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1724 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1726 if (TypeManager
.void_decimal_ctor_five_args
== null)
1730 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1733 public override Constant
Increment ()
1735 return new DecimalConstant (checked (Value
+ 1), loc
);
1738 public override bool IsDefaultValue
{
1744 public override bool IsNegative
{
1750 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1752 if (target_type
== TypeManager
.sbyte_type
)
1753 return new SByteConstant ((sbyte)Value
, loc
);
1754 if (target_type
== TypeManager
.byte_type
)
1755 return new ByteConstant ((byte)Value
, loc
);
1756 if (target_type
== TypeManager
.short_type
)
1757 return new ShortConstant ((short)Value
, loc
);
1758 if (target_type
== TypeManager
.ushort_type
)
1759 return new UShortConstant ((ushort)Value
, loc
);
1760 if (target_type
== TypeManager
.int32_type
)
1761 return new IntConstant ((int)Value
, loc
);
1762 if (target_type
== TypeManager
.uint32_type
)
1763 return new UIntConstant ((uint)Value
, loc
);
1764 if (target_type
== TypeManager
.int64_type
)
1765 return new LongConstant ((long)Value
, loc
);
1766 if (target_type
== TypeManager
.uint64_type
)
1767 return new ULongConstant ((ulong)Value
, loc
);
1768 if (target_type
== TypeManager
.char_type
)
1769 return new CharConstant ((char)Value
, loc
);
1770 if (target_type
== TypeManager
.float_type
)
1771 return new FloatConstant ((float)Value
, loc
);
1772 if (target_type
== TypeManager
.double_type
)
1773 return new DoubleConstant ((double)Value
, loc
);
1780 public class StringConstant
: Constant
{
1781 public readonly string Value
;
1783 public StringConstant (string s
, Location loc
):
1786 type
= TypeManager
.string_type
;
1787 eclass
= ExprClass
.Value
;
1791 // FIXME: Escape the string.
1792 override public string AsString ()
1794 return "\"" + Value
+ "\"";
1797 public override object GetValue ()
1802 public override void Emit (EmitContext ec
)
1804 if (Value
== null) {
1805 ec
.ig
.Emit (OpCodes
.Ldnull
);
1810 // Use string.Empty for both literals and constants even if
1811 // it's not allowed at language level
1813 if (Value
.Length
== 0 && RootContext
.Optimize
&& !TypeManager
.IsEqual (ec
.CurrentType
, TypeManager
.string_type
)) {
1814 if (TypeManager
.string_empty
== null)
1815 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
);
1817 if (TypeManager
.string_empty
!= null) {
1818 ec
.ig
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1823 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1826 public override Constant
Increment ()
1828 throw new NotSupportedException ();
1831 public override bool IsDefaultValue
{
1833 return Value
== null;
1837 public override bool IsNegative
{
1843 public override bool IsNull
{
1845 return IsDefaultValue
;
1849 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1856 // Null constant can have its own type, think of `default (Foo)'
1858 public class NullConstant
: Constant
1860 public NullConstant (Type type
, Location loc
)
1863 eclass
= ExprClass
.Value
;
1867 public override string AsString ()
1869 return GetSignatureForError ();
1872 public override Expression
DoResolve (ResolveContext ec
)
1877 public override void Emit (EmitContext ec
)
1879 ec
.ig
.Emit (OpCodes
.Ldnull
);
1881 // Only to make verifier happy
1882 if (TypeManager
.IsGenericParameter (type
))
1883 ec
.ig
.Emit (OpCodes
.Unbox_Any
, type
);
1886 public override string ExprClassName
{
1888 return GetSignatureForError ();
1892 public override string GetSignatureForError ()
1897 public override Constant
ConvertExplicitly (bool inCheckedContext
, Type targetType
)
1899 if (targetType
.IsPointer
) {
1900 if (IsLiteral
|| this is NullPointer
)
1901 return new EmptyConstantCast (new NullPointer (loc
), targetType
);
1906 // Exlude internal compiler types
1907 if (targetType
== InternalType
.AnonymousMethod
)
1910 if (!IsLiteral
&& !Convert
.ImplicitStandardConversionExists (this, targetType
))
1913 if (TypeManager
.IsReferenceType (targetType
))
1914 return new NullConstant (targetType
, loc
);
1916 if (TypeManager
.IsNullableType (targetType
))
1917 return Nullable
.LiftedNull
.Create (targetType
, loc
);
1922 public override Constant
ConvertImplicitly (Type targetType
)
1924 return ConvertExplicitly (false, targetType
);
1927 public override object GetValue ()
1932 public override Constant
Increment ()
1934 throw new NotSupportedException ();
1937 public override bool IsDefaultValue
{
1938 get { return true; }
1941 public override bool IsNegative
{
1942 get { return false; }
1945 public override bool IsNull
{
1946 get { return true; }
1949 public override bool IsZeroInteger
{
1950 get { return true; }
1953 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
1955 type
= storey
.MutateType (type
);
1960 /// The value is constant, but when emitted has a side effect. This is
1961 /// used by BitwiseAnd to ensure that the second expression is invoked
1962 /// regardless of the value of the left side.
1964 public class SideEffectConstant
: Constant
{
1965 public Constant
value;
1966 Expression side_effect
;
1968 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
1971 while (side_effect
is SideEffectConstant
)
1972 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
1973 this.side_effect
= side_effect
;
1974 eclass
= ExprClass
.Value
;
1978 public override string AsString ()
1980 return value.AsString ();
1983 public override object GetValue ()
1985 return value.GetValue ();
1988 public override void Emit (EmitContext ec
)
1990 side_effect
.EmitSideEffect (ec
);
1994 public override void EmitSideEffect (EmitContext ec
)
1996 side_effect
.EmitSideEffect (ec
);
1997 value.EmitSideEffect (ec
);
2000 public override bool IsDefaultValue
{
2001 get { return value.IsDefaultValue; }
2004 public override Constant
Increment ()
2006 throw new NotSupportedException ();
2009 public override bool IsNegative
{
2010 get { return value.IsNegative; }
2013 public override bool IsZeroInteger
{
2014 get { return value.IsZeroInteger; }
2017 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
2019 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
2020 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);