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 (EmitContext 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 (EmitContext ec
)
79 public override void Error_ValueCannotBeConverted (EmitContext 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 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 (EmitContext 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
);
157 if (v
== null && !TypeManager
.IsValueType (t
))
158 return new EmptyConstantCast (new NullLiteral (loc
), t
);
160 throw new Exception ("Unknown type for constant (" + t
+
164 public override Expression
CreateExpressionTree (EmitContext ec
)
166 ArrayList args
= new ArrayList (2);
167 args
.Add (new Argument (this));
168 args
.Add (new Argument (
169 new TypeOf (new TypeExpression (type
, loc
), loc
)));
171 return CreateExpressionFactoryCall ("Constant", args
);
176 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
177 /// It throws OverflowException
179 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
180 public abstract Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
);
183 /// Attempts to do a compile-time folding of a constant cast.
185 public Constant
TryReduce (EmitContext ec
, Type target_type
, Location loc
)
188 return TryReduce (ec
, target_type
);
190 catch (OverflowException
) {
191 if (ec
.ConstantCheckState
) {
192 Report
.Error (221, loc
, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
193 GetValue ().ToString (), TypeManager
.CSharpName (target_type
));
195 Error_ValueCannotBeConverted (ec
, loc
, target_type
, false);
198 return New
.Constantify (target_type
);
202 Constant
TryReduce (EmitContext ec
, Type target_type
)
204 if (Type
== target_type
)
207 if (TypeManager
.IsEnumType (target_type
)) {
208 Constant c
= TryReduce (ec
, TypeManager
.GetEnumUnderlyingType (target_type
));
212 return new EnumConstant (c
, target_type
);
215 return ConvertExplicitly (ec
.ConstantCheckState
, target_type
);
218 public abstract Constant
Increment ();
221 /// Need to pass type as the constant can require a boxing
222 /// and in such case no optimization is possible
224 public bool IsDefaultInitializer (Type type
)
227 return IsDefaultValue
;
229 return this is NullLiteral
;
232 public abstract bool IsDefaultValue
{
236 public abstract bool IsNegative
{
241 // When constant is declared as literal
243 public virtual bool IsLiteral
{
244 get { return false; }
248 // Returns true iff 1) the stack type of this is one of Object,
249 // int32, int64 and 2) this == 0 or this == null.
251 public virtual bool IsZeroInteger
{
252 get { return false; }
255 public override void EmitSideEffect (EmitContext ec
)
260 protected override void CloneTo (CloneContext clonectx
, Expression target
)
262 // CloneTo: Nothing, we do not keep any state on this expression
265 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
267 // A constant cannot be of generic type
271 public abstract class IntegralConstant
: Constant
{
272 protected IntegralConstant (Location loc
) :
277 public override void Error_ValueCannotBeConverted (EmitContext ec
, Location loc
, Type target
, bool expl
)
280 ConvertExplicitly (true, target
);
281 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
285 Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
286 GetValue ().ToString (), TypeManager
.CSharpName (target
));
291 public class BoolConstant
: Constant
{
292 public readonly bool Value
;
294 public BoolConstant (bool val
, Location loc
):
297 type
= TypeManager
.bool_type
;
298 eclass
= ExprClass
.Value
;
303 override public string AsString ()
305 return Value
? "true" : "false";
308 public override object GetValue ()
310 return (object) Value
;
314 public override void Emit (EmitContext ec
)
317 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
319 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
322 public override Constant
Increment ()
324 throw new NotSupportedException ();
327 public override bool IsDefaultValue
{
333 public override bool IsNegative
{
339 public override bool IsZeroInteger
{
340 get { return Value == false; }
343 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
350 public class ByteConstant
: IntegralConstant
{
351 public readonly byte Value
;
353 public ByteConstant (byte v
, Location loc
):
356 type
= TypeManager
.byte_type
;
357 eclass
= ExprClass
.Value
;
361 public override void Emit (EmitContext ec
)
363 IntLiteral
.EmitInt (ec
.ig
, Value
);
366 public override string AsString ()
368 return Value
.ToString ();
371 public override object GetValue ()
376 public override Constant
Increment ()
378 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
381 public override bool IsDefaultValue
{
387 public override bool IsNegative
{
393 public override bool IsZeroInteger
{
394 get { return Value == 0; }
397 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
399 if (target_type
== TypeManager
.sbyte_type
) {
400 if (in_checked_context
){
401 if (Value
> SByte
.MaxValue
)
402 throw new OverflowException ();
404 return new SByteConstant ((sbyte) Value
, Location
);
406 if (target_type
== TypeManager
.short_type
)
407 return new ShortConstant ((short) Value
, Location
);
408 if (target_type
== TypeManager
.ushort_type
)
409 return new UShortConstant ((ushort) Value
, Location
);
410 if (target_type
== TypeManager
.int32_type
)
411 return new IntConstant ((int) Value
, Location
);
412 if (target_type
== TypeManager
.uint32_type
)
413 return new UIntConstant ((uint) Value
, Location
);
414 if (target_type
== TypeManager
.int64_type
)
415 return new LongConstant ((long) Value
, Location
);
416 if (target_type
== TypeManager
.uint64_type
)
417 return new ULongConstant ((ulong) Value
, Location
);
418 if (target_type
== TypeManager
.float_type
)
419 return new FloatConstant ((float) Value
, Location
);
420 if (target_type
== TypeManager
.double_type
)
421 return new DoubleConstant ((double) Value
, Location
);
422 if (target_type
== TypeManager
.char_type
)
423 return new CharConstant ((char) Value
, Location
);
424 if (target_type
== TypeManager
.decimal_type
)
425 return new DecimalConstant ((decimal) Value
, Location
);
432 public class CharConstant
: Constant
{
433 public readonly char Value
;
435 public CharConstant (char v
, Location loc
):
438 type
= TypeManager
.char_type
;
439 eclass
= ExprClass
.Value
;
443 public override void Emit (EmitContext ec
)
445 IntLiteral
.EmitInt (ec
.ig
, Value
);
448 static public string descape (char c
)
474 return c
.ToString ();
477 public override string AsString ()
479 return "\"" + descape (Value
) + "\"";
482 public override object GetValue ()
487 public override Constant
Increment ()
489 return new CharConstant (checked ((char)(Value
+ 1)), loc
);
492 public override bool IsDefaultValue
{
498 public override bool IsNegative
{
504 public override bool IsZeroInteger
{
505 get { return Value == '\0'; }
508 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
510 if (target_type
== TypeManager
.byte_type
) {
511 if (in_checked_context
){
512 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
513 throw new OverflowException ();
515 return new ByteConstant ((byte) Value
, Location
);
517 if (target_type
== TypeManager
.sbyte_type
) {
518 if (in_checked_context
){
519 if (Value
> SByte
.MaxValue
)
520 throw new OverflowException ();
522 return new SByteConstant ((sbyte) Value
, Location
);
524 if (target_type
== TypeManager
.short_type
) {
525 if (in_checked_context
){
526 if (Value
> Int16
.MaxValue
)
527 throw new OverflowException ();
529 return new ShortConstant ((short) Value
, Location
);
531 if (target_type
== TypeManager
.int32_type
)
532 return new IntConstant ((int) Value
, Location
);
533 if (target_type
== TypeManager
.uint32_type
)
534 return new UIntConstant ((uint) Value
, Location
);
535 if (target_type
== TypeManager
.int64_type
)
536 return new LongConstant ((long) Value
, Location
);
537 if (target_type
== TypeManager
.uint64_type
)
538 return new ULongConstant ((ulong) Value
, Location
);
539 if (target_type
== TypeManager
.float_type
)
540 return new FloatConstant ((float) Value
, Location
);
541 if (target_type
== TypeManager
.double_type
)
542 return new DoubleConstant ((double) Value
, Location
);
543 if (target_type
== TypeManager
.decimal_type
)
544 return new DecimalConstant ((decimal) Value
, Location
);
551 public class SByteConstant
: IntegralConstant
{
552 public readonly sbyte Value
;
554 public SByteConstant (sbyte v
, Location loc
):
557 type
= TypeManager
.sbyte_type
;
558 eclass
= ExprClass
.Value
;
562 public override void Emit (EmitContext ec
)
564 IntLiteral
.EmitInt (ec
.ig
, Value
);
567 public override string AsString ()
569 return Value
.ToString ();
572 public override object GetValue ()
577 public override Constant
Increment ()
579 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
582 public override bool IsDefaultValue
{
588 public override bool IsNegative
{
594 public override bool IsZeroInteger
{
595 get { return Value == 0; }
598 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
600 if (target_type
== TypeManager
.byte_type
) {
601 if (in_checked_context
&& Value
< 0)
602 throw new OverflowException ();
603 return new ByteConstant ((byte) Value
, Location
);
605 if (target_type
== TypeManager
.short_type
)
606 return new ShortConstant ((short) Value
, Location
);
607 if (target_type
== TypeManager
.ushort_type
) {
608 if (in_checked_context
&& Value
< 0)
609 throw new OverflowException ();
610 return new UShortConstant ((ushort) Value
, Location
);
611 } if (target_type
== TypeManager
.int32_type
)
612 return new IntConstant ((int) Value
, Location
);
613 if (target_type
== TypeManager
.uint32_type
) {
614 if (in_checked_context
&& Value
< 0)
615 throw new OverflowException ();
616 return new UIntConstant ((uint) Value
, Location
);
617 } if (target_type
== TypeManager
.int64_type
)
618 return new LongConstant ((long) Value
, Location
);
619 if (target_type
== TypeManager
.uint64_type
) {
620 if (in_checked_context
&& Value
< 0)
621 throw new OverflowException ();
622 return new ULongConstant ((ulong) Value
, Location
);
624 if (target_type
== TypeManager
.float_type
)
625 return new FloatConstant ((float) Value
, Location
);
626 if (target_type
== TypeManager
.double_type
)
627 return new DoubleConstant ((double) Value
, Location
);
628 if (target_type
== TypeManager
.char_type
) {
629 if (in_checked_context
&& Value
< 0)
630 throw new OverflowException ();
631 return new CharConstant ((char) Value
, Location
);
633 if (target_type
== TypeManager
.decimal_type
)
634 return new DecimalConstant ((decimal) Value
, Location
);
641 public class ShortConstant
: IntegralConstant
{
642 public readonly short Value
;
644 public ShortConstant (short v
, Location loc
):
647 type
= TypeManager
.short_type
;
648 eclass
= ExprClass
.Value
;
652 public override void Emit (EmitContext ec
)
654 IntLiteral
.EmitInt (ec
.ig
, Value
);
657 public override string AsString ()
659 return Value
.ToString ();
662 public override object GetValue ()
667 public override Constant
Increment ()
669 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
672 public override bool IsDefaultValue
{
678 public override bool IsZeroInteger
{
679 get { return Value == 0; }
682 public override bool IsNegative
{
688 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
690 if (target_type
== TypeManager
.byte_type
) {
691 if (in_checked_context
){
692 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
693 throw new OverflowException ();
695 return new ByteConstant ((byte) Value
, Location
);
697 if (target_type
== TypeManager
.sbyte_type
) {
698 if (in_checked_context
){
699 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
700 throw new OverflowException ();
702 return new SByteConstant ((sbyte) Value
, Location
);
704 if (target_type
== TypeManager
.ushort_type
) {
705 if (in_checked_context
&& Value
< 0)
706 throw new OverflowException ();
708 return new UShortConstant ((ushort) Value
, Location
);
710 if (target_type
== TypeManager
.int32_type
)
711 return new IntConstant ((int) Value
, Location
);
712 if (target_type
== TypeManager
.uint32_type
) {
713 if (in_checked_context
&& Value
< 0)
714 throw new OverflowException ();
715 return new UIntConstant ((uint) Value
, Location
);
717 if (target_type
== TypeManager
.int64_type
)
718 return new LongConstant ((long) Value
, Location
);
719 if (target_type
== TypeManager
.uint64_type
) {
720 if (in_checked_context
&& Value
< 0)
721 throw new OverflowException ();
722 return new ULongConstant ((ulong) Value
, Location
);
724 if (target_type
== TypeManager
.float_type
)
725 return new FloatConstant ((float) Value
, Location
);
726 if (target_type
== TypeManager
.double_type
)
727 return new DoubleConstant ((double) Value
, Location
);
728 if (target_type
== TypeManager
.char_type
) {
729 if (in_checked_context
){
730 if (Value
< Char
.MinValue
)
731 throw new OverflowException ();
733 return new CharConstant ((char) Value
, Location
);
735 if (target_type
== TypeManager
.decimal_type
)
736 return new DecimalConstant ((decimal) Value
, Location
);
743 public class UShortConstant
: IntegralConstant
{
744 public readonly ushort Value
;
746 public UShortConstant (ushort v
, Location loc
):
749 type
= TypeManager
.ushort_type
;
750 eclass
= ExprClass
.Value
;
754 public override void Emit (EmitContext ec
)
756 IntLiteral
.EmitInt (ec
.ig
, Value
);
759 public override string AsString ()
761 return Value
.ToString ();
764 public override object GetValue ()
769 public override Constant
Increment ()
771 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
774 public override bool IsDefaultValue
{
780 public override bool IsNegative
{
786 public override bool IsZeroInteger
{
787 get { return Value == 0; }
790 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
792 if (target_type
== TypeManager
.byte_type
) {
793 if (in_checked_context
){
794 if (Value
> Byte
.MaxValue
)
795 throw new OverflowException ();
797 return new ByteConstant ((byte) Value
, Location
);
799 if (target_type
== TypeManager
.sbyte_type
) {
800 if (in_checked_context
){
801 if (Value
> SByte
.MaxValue
)
802 throw new OverflowException ();
804 return new SByteConstant ((sbyte) Value
, Location
);
806 if (target_type
== TypeManager
.short_type
) {
807 if (in_checked_context
){
808 if (Value
> Int16
.MaxValue
)
809 throw new OverflowException ();
811 return new ShortConstant ((short) Value
, Location
);
813 if (target_type
== TypeManager
.int32_type
)
814 return new IntConstant ((int) Value
, Location
);
815 if (target_type
== TypeManager
.uint32_type
)
816 return new UIntConstant ((uint) Value
, Location
);
817 if (target_type
== TypeManager
.int64_type
)
818 return new LongConstant ((long) Value
, Location
);
819 if (target_type
== TypeManager
.uint64_type
)
820 return new ULongConstant ((ulong) Value
, Location
);
821 if (target_type
== TypeManager
.float_type
)
822 return new FloatConstant ((float) Value
, Location
);
823 if (target_type
== TypeManager
.double_type
)
824 return new DoubleConstant ((double) Value
, Location
);
825 if (target_type
== TypeManager
.char_type
) {
826 if (in_checked_context
){
827 if (Value
> Char
.MaxValue
)
828 throw new OverflowException ();
830 return new CharConstant ((char) Value
, Location
);
832 if (target_type
== TypeManager
.decimal_type
)
833 return new DecimalConstant ((decimal) Value
, Location
);
839 public class IntConstant
: IntegralConstant
{
840 public readonly int Value
;
842 public IntConstant (int v
, Location loc
):
845 type
= TypeManager
.int32_type
;
846 eclass
= ExprClass
.Value
;
850 static public void EmitInt (ILGenerator ig
, int i
)
854 ig
.Emit (OpCodes
.Ldc_I4_M1
);
858 ig
.Emit (OpCodes
.Ldc_I4_0
);
862 ig
.Emit (OpCodes
.Ldc_I4_1
);
866 ig
.Emit (OpCodes
.Ldc_I4_2
);
870 ig
.Emit (OpCodes
.Ldc_I4_3
);
874 ig
.Emit (OpCodes
.Ldc_I4_4
);
878 ig
.Emit (OpCodes
.Ldc_I4_5
);
882 ig
.Emit (OpCodes
.Ldc_I4_6
);
886 ig
.Emit (OpCodes
.Ldc_I4_7
);
890 ig
.Emit (OpCodes
.Ldc_I4_8
);
894 if (i
>= -128 && i
<= 127){
895 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
897 ig
.Emit (OpCodes
.Ldc_I4
, i
);
902 public override void Emit (EmitContext ec
)
904 EmitInt (ec
.ig
, Value
);
907 public override string AsString ()
909 return Value
.ToString ();
912 public override object GetValue ()
917 public override Constant
Increment ()
919 return new IntConstant (checked(Value
+ 1), loc
);
922 public override bool IsDefaultValue
{
928 public override bool IsNegative
{
934 public override bool IsZeroInteger
{
935 get { return Value == 0; }
938 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
940 if (target_type
== TypeManager
.byte_type
) {
941 if (in_checked_context
){
942 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
943 throw new OverflowException ();
945 return new ByteConstant ((byte) Value
, Location
);
947 if (target_type
== TypeManager
.sbyte_type
) {
948 if (in_checked_context
){
949 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
950 throw new OverflowException ();
952 return new SByteConstant ((sbyte) Value
, Location
);
954 if (target_type
== TypeManager
.short_type
) {
955 if (in_checked_context
){
956 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
957 throw new OverflowException ();
959 return new ShortConstant ((short) Value
, Location
);
961 if (target_type
== TypeManager
.ushort_type
) {
962 if (in_checked_context
){
963 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
964 throw new OverflowException ();
966 return new UShortConstant ((ushort) Value
, Location
);
968 if (target_type
== TypeManager
.uint32_type
) {
969 if (in_checked_context
){
970 if (Value
< UInt32
.MinValue
)
971 throw new OverflowException ();
973 return new UIntConstant ((uint) Value
, Location
);
975 if (target_type
== TypeManager
.int64_type
)
976 return new LongConstant ((long) Value
, Location
);
977 if (target_type
== TypeManager
.uint64_type
) {
978 if (in_checked_context
&& Value
< 0)
979 throw new OverflowException ();
980 return new ULongConstant ((ulong) Value
, Location
);
982 if (target_type
== TypeManager
.float_type
)
983 return new FloatConstant ((float) Value
, Location
);
984 if (target_type
== TypeManager
.double_type
)
985 return new DoubleConstant ((double) Value
, Location
);
986 if (target_type
== TypeManager
.char_type
) {
987 if (in_checked_context
){
988 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
989 throw new OverflowException ();
991 return new CharConstant ((char) Value
, Location
);
993 if (target_type
== TypeManager
.decimal_type
)
994 return new DecimalConstant ((decimal) Value
, Location
);
999 public override Constant
ConvertImplicitly (Type type
)
1001 if (this.type
== type
)
1004 Constant c
= TryImplicitIntConversion (type
);
1008 return base.ConvertImplicitly (type
);
1012 /// Attempts to perform an implicit constant conversion of the IntConstant
1013 /// into a different data type using casts (See Implicit Constant
1014 /// Expression Conversions)
1016 Constant
TryImplicitIntConversion (Type target_type
)
1018 if (target_type
== TypeManager
.sbyte_type
) {
1019 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1020 return new SByteConstant ((sbyte) Value
, loc
);
1022 else if (target_type
== TypeManager
.byte_type
) {
1023 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1024 return new ByteConstant ((byte) Value
, loc
);
1026 else if (target_type
== TypeManager
.short_type
) {
1027 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1028 return new ShortConstant ((short) Value
, loc
);
1030 else if (target_type
== TypeManager
.ushort_type
) {
1031 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1032 return new UShortConstant ((ushort) Value
, loc
);
1034 else if (target_type
== TypeManager
.uint32_type
) {
1036 return new UIntConstant ((uint) Value
, loc
);
1038 else if (target_type
== TypeManager
.uint64_type
) {
1040 // we can optimize this case: a positive int32
1041 // always fits on a uint64. But we need an opcode
1045 return new ULongConstant ((ulong) Value
, loc
);
1047 else if (target_type
== TypeManager
.double_type
)
1048 return new DoubleConstant ((double) Value
, loc
);
1049 else if (target_type
== TypeManager
.float_type
)
1050 return new FloatConstant ((float) Value
, loc
);
1056 public class UIntConstant
: IntegralConstant
{
1057 public readonly uint Value
;
1059 public UIntConstant (uint v
, Location loc
):
1062 type
= TypeManager
.uint32_type
;
1063 eclass
= ExprClass
.Value
;
1067 public override void Emit (EmitContext ec
)
1069 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
1072 public override string AsString ()
1074 return Value
.ToString ();
1077 public override object GetValue ()
1082 public override Constant
Increment ()
1084 return new UIntConstant (checked(Value
+ 1), loc
);
1087 public override bool IsDefaultValue
{
1093 public override bool IsNegative
{
1099 public override bool IsZeroInteger
{
1100 get { return Value == 0; }
1103 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1105 if (target_type
== TypeManager
.byte_type
) {
1106 if (in_checked_context
){
1107 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1108 throw new OverflowException ();
1110 return new ByteConstant ((byte) Value
, Location
);
1112 if (target_type
== TypeManager
.sbyte_type
) {
1113 if (in_checked_context
){
1114 if (Value
> SByte
.MaxValue
)
1115 throw new OverflowException ();
1117 return new SByteConstant ((sbyte) Value
, Location
);
1119 if (target_type
== TypeManager
.short_type
) {
1120 if (in_checked_context
){
1121 if (Value
> Int16
.MaxValue
)
1122 throw new OverflowException ();
1124 return new ShortConstant ((short) Value
, Location
);
1126 if (target_type
== TypeManager
.ushort_type
) {
1127 if (in_checked_context
){
1128 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1129 throw new OverflowException ();
1131 return new UShortConstant ((ushort) Value
, Location
);
1133 if (target_type
== TypeManager
.int32_type
) {
1134 if (in_checked_context
){
1135 if (Value
> Int32
.MaxValue
)
1136 throw new OverflowException ();
1138 return new IntConstant ((int) Value
, Location
);
1140 if (target_type
== TypeManager
.int64_type
)
1141 return new LongConstant ((long) Value
, Location
);
1142 if (target_type
== TypeManager
.uint64_type
)
1143 return new ULongConstant ((ulong) Value
, Location
);
1144 if (target_type
== TypeManager
.float_type
)
1145 return new FloatConstant ((float) Value
, Location
);
1146 if (target_type
== TypeManager
.double_type
)
1147 return new DoubleConstant ((double) Value
, Location
);
1148 if (target_type
== TypeManager
.char_type
) {
1149 if (in_checked_context
){
1150 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1151 throw new OverflowException ();
1153 return new CharConstant ((char) Value
, Location
);
1155 if (target_type
== TypeManager
.decimal_type
)
1156 return new DecimalConstant ((decimal) Value
, Location
);
1163 public class LongConstant
: IntegralConstant
{
1164 public readonly long Value
;
1166 public LongConstant (long v
, Location loc
):
1169 type
= TypeManager
.int64_type
;
1170 eclass
= ExprClass
.Value
;
1174 public override void Emit (EmitContext ec
)
1176 EmitLong (ec
.ig
, Value
);
1179 static public void EmitLong (ILGenerator ig
, long l
)
1181 if (l
>= int.MinValue
&& l
<= int.MaxValue
) {
1182 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1183 ig
.Emit (OpCodes
.Conv_I8
);
1187 if (l
>= 0 && l
<= uint.MaxValue
) {
1188 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1189 ig
.Emit (OpCodes
.Conv_U8
);
1193 ig
.Emit (OpCodes
.Ldc_I8
, l
);
1196 public override string AsString ()
1198 return Value
.ToString ();
1201 public override object GetValue ()
1206 public override Constant
Increment ()
1208 return new LongConstant (checked(Value
+ 1), loc
);
1211 public override bool IsDefaultValue
{
1217 public override bool IsNegative
{
1223 public override bool IsZeroInteger
{
1224 get { return Value == 0; }
1227 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1229 if (target_type
== TypeManager
.byte_type
) {
1230 if (in_checked_context
){
1231 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1232 throw new OverflowException ();
1234 return new ByteConstant ((byte) Value
, Location
);
1236 if (target_type
== TypeManager
.sbyte_type
) {
1237 if (in_checked_context
){
1238 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1239 throw new OverflowException ();
1241 return new SByteConstant ((sbyte) Value
, Location
);
1243 if (target_type
== TypeManager
.short_type
) {
1244 if (in_checked_context
){
1245 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1246 throw new OverflowException ();
1248 return new ShortConstant ((short) Value
, Location
);
1250 if (target_type
== TypeManager
.ushort_type
) {
1251 if (in_checked_context
){
1252 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1253 throw new OverflowException ();
1255 return new UShortConstant ((ushort) Value
, Location
);
1257 if (target_type
== TypeManager
.int32_type
) {
1258 if (in_checked_context
){
1259 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1260 throw new OverflowException ();
1262 return new IntConstant ((int) Value
, Location
);
1264 if (target_type
== TypeManager
.uint32_type
) {
1265 if (in_checked_context
){
1266 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1267 throw new OverflowException ();
1269 return new UIntConstant ((uint) Value
, Location
);
1271 if (target_type
== TypeManager
.uint64_type
) {
1272 if (in_checked_context
&& Value
< 0)
1273 throw new OverflowException ();
1274 return new ULongConstant ((ulong) Value
, Location
);
1276 if (target_type
== TypeManager
.float_type
)
1277 return new FloatConstant ((float) Value
, Location
);
1278 if (target_type
== TypeManager
.double_type
)
1279 return new DoubleConstant ((double) Value
, Location
);
1280 if (target_type
== TypeManager
.char_type
) {
1281 if (in_checked_context
){
1282 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1283 throw new OverflowException ();
1285 return new CharConstant ((char) Value
, Location
);
1287 if (target_type
== TypeManager
.decimal_type
)
1288 return new DecimalConstant ((decimal) Value
, Location
);
1293 public override Constant
ConvertImplicitly (Type type
)
1295 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1296 return new ULongConstant ((ulong) Value
, loc
);
1299 return base.ConvertImplicitly (type
);
1303 public class ULongConstant
: IntegralConstant
{
1304 public readonly ulong Value
;
1306 public ULongConstant (ulong v
, Location loc
):
1309 type
= TypeManager
.uint64_type
;
1310 eclass
= ExprClass
.Value
;
1314 public override void Emit (EmitContext ec
)
1316 ILGenerator ig
= ec
.ig
;
1318 LongLiteral
.EmitLong (ig
, unchecked ((long) Value
));
1321 public override string AsString ()
1323 return Value
.ToString ();
1326 public override object GetValue ()
1331 public override Constant
Increment ()
1333 return new ULongConstant (checked(Value
+ 1), loc
);
1336 public override bool IsDefaultValue
{
1342 public override bool IsNegative
{
1348 public override bool IsZeroInteger
{
1349 get { return Value == 0; }
1352 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1354 if (target_type
== TypeManager
.byte_type
) {
1355 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1356 throw new OverflowException ();
1357 return new ByteConstant ((byte) Value
, Location
);
1359 if (target_type
== TypeManager
.sbyte_type
) {
1360 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1361 throw new OverflowException ();
1362 return new SByteConstant ((sbyte) Value
, Location
);
1364 if (target_type
== TypeManager
.short_type
) {
1365 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1366 throw new OverflowException ();
1367 return new ShortConstant ((short) Value
, Location
);
1369 if (target_type
== TypeManager
.ushort_type
) {
1370 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1371 throw new OverflowException ();
1372 return new UShortConstant ((ushort) Value
, Location
);
1374 if (target_type
== TypeManager
.int32_type
) {
1375 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1376 throw new OverflowException ();
1377 return new IntConstant ((int) Value
, Location
);
1379 if (target_type
== TypeManager
.uint32_type
) {
1380 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1381 throw new OverflowException ();
1382 return new UIntConstant ((uint) Value
, Location
);
1384 if (target_type
== TypeManager
.int64_type
) {
1385 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1386 throw new OverflowException ();
1387 return new LongConstant ((long) Value
, Location
);
1389 if (target_type
== TypeManager
.float_type
)
1390 return new FloatConstant ((float) Value
, Location
);
1391 if (target_type
== TypeManager
.double_type
)
1392 return new DoubleConstant ((double) Value
, Location
);
1393 if (target_type
== TypeManager
.char_type
) {
1394 if (in_checked_context
&& Value
> Char
.MaxValue
)
1395 throw new OverflowException ();
1396 return new CharConstant ((char) Value
, Location
);
1398 if (target_type
== TypeManager
.decimal_type
)
1399 return new DecimalConstant ((decimal) Value
, Location
);
1406 public class FloatConstant
: Constant
{
1409 public FloatConstant (float v
, Location loc
):
1412 type
= TypeManager
.float_type
;
1413 eclass
= ExprClass
.Value
;
1417 public override void Emit (EmitContext ec
)
1419 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
1422 public override string AsString ()
1424 return Value
.ToString ();
1427 public override object GetValue ()
1432 public override Constant
Increment ()
1434 return new FloatConstant (checked(Value
+ 1), loc
);
1437 public override bool IsDefaultValue
{
1443 public override bool IsNegative
{
1449 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1451 if (target_type
== TypeManager
.byte_type
) {
1452 if (in_checked_context
){
1453 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1454 throw new OverflowException ();
1456 return new ByteConstant ((byte) Value
, Location
);
1458 if (target_type
== TypeManager
.sbyte_type
) {
1459 if (in_checked_context
){
1460 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1461 throw new OverflowException ();
1463 return new SByteConstant ((sbyte) Value
, Location
);
1465 if (target_type
== TypeManager
.short_type
) {
1466 if (in_checked_context
){
1467 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1468 throw new OverflowException ();
1470 return new ShortConstant ((short) Value
, Location
);
1472 if (target_type
== TypeManager
.ushort_type
) {
1473 if (in_checked_context
){
1474 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1475 throw new OverflowException ();
1477 return new UShortConstant ((ushort) Value
, Location
);
1479 if (target_type
== TypeManager
.int32_type
) {
1480 if (in_checked_context
){
1481 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1482 throw new OverflowException ();
1484 return new IntConstant ((int) Value
, Location
);
1486 if (target_type
== TypeManager
.uint32_type
) {
1487 if (in_checked_context
){
1488 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1489 throw new OverflowException ();
1491 return new UIntConstant ((uint) Value
, Location
);
1493 if (target_type
== TypeManager
.int64_type
) {
1494 if (in_checked_context
){
1495 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1496 throw new OverflowException ();
1498 return new LongConstant ((long) Value
, Location
);
1500 if (target_type
== TypeManager
.uint64_type
) {
1501 if (in_checked_context
){
1502 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1503 throw new OverflowException ();
1505 return new ULongConstant ((ulong) Value
, Location
);
1507 if (target_type
== TypeManager
.double_type
)
1508 return new DoubleConstant ((double) Value
, Location
);
1509 if (target_type
== TypeManager
.char_type
) {
1510 if (in_checked_context
){
1511 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1512 throw new OverflowException ();
1514 return new CharConstant ((char) Value
, Location
);
1516 if (target_type
== TypeManager
.decimal_type
)
1517 return new DecimalConstant ((decimal) Value
, Location
);
1524 public class DoubleConstant
: Constant
{
1525 public double Value
;
1527 public DoubleConstant (double v
, Location loc
):
1530 type
= TypeManager
.double_type
;
1531 eclass
= ExprClass
.Value
;
1535 public override void Emit (EmitContext ec
)
1537 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
1540 public override string AsString ()
1542 return Value
.ToString ();
1545 public override object GetValue ()
1550 public override Constant
Increment ()
1552 return new DoubleConstant (checked(Value
+ 1), loc
);
1555 public override bool IsDefaultValue
{
1561 public override bool IsNegative
{
1567 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1569 if (target_type
== TypeManager
.byte_type
) {
1570 if (in_checked_context
){
1571 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1572 throw new OverflowException ();
1574 return new ByteConstant ((byte) Value
, Location
);
1576 if (target_type
== TypeManager
.sbyte_type
) {
1577 if (in_checked_context
){
1578 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1579 throw new OverflowException ();
1581 return new SByteConstant ((sbyte) Value
, Location
);
1583 if (target_type
== TypeManager
.short_type
) {
1584 if (in_checked_context
){
1585 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1586 throw new OverflowException ();
1588 return new ShortConstant ((short) Value
, Location
);
1590 if (target_type
== TypeManager
.ushort_type
) {
1591 if (in_checked_context
){
1592 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1593 throw new OverflowException ();
1595 return new UShortConstant ((ushort) Value
, Location
);
1597 if (target_type
== TypeManager
.int32_type
) {
1598 if (in_checked_context
){
1599 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1600 throw new OverflowException ();
1602 return new IntConstant ((int) Value
, Location
);
1604 if (target_type
== TypeManager
.uint32_type
) {
1605 if (in_checked_context
){
1606 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1607 throw new OverflowException ();
1609 return new UIntConstant ((uint) Value
, Location
);
1611 if (target_type
== TypeManager
.int64_type
) {
1612 if (in_checked_context
){
1613 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1614 throw new OverflowException ();
1616 return new LongConstant ((long) Value
, Location
);
1618 if (target_type
== TypeManager
.uint64_type
) {
1619 if (in_checked_context
){
1620 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1621 throw new OverflowException ();
1623 return new ULongConstant ((ulong) Value
, Location
);
1625 if (target_type
== TypeManager
.float_type
)
1626 return new FloatConstant ((float) Value
, Location
);
1627 if (target_type
== TypeManager
.char_type
) {
1628 if (in_checked_context
){
1629 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1630 throw new OverflowException ();
1632 return new CharConstant ((char) Value
, Location
);
1634 if (target_type
== TypeManager
.decimal_type
)
1635 return new DecimalConstant ((decimal) Value
, Location
);
1642 public class DecimalConstant
: Constant
{
1643 public readonly decimal Value
;
1645 public DecimalConstant (decimal d
, Location loc
):
1648 type
= TypeManager
.decimal_type
;
1649 eclass
= ExprClass
.Value
;
1653 override public string AsString ()
1655 return Value
.ToString () + "M";
1658 public override object GetValue ()
1660 return (object) Value
;
1663 public override void Emit (EmitContext ec
)
1665 ILGenerator ig
= ec
.ig
;
1667 int [] words
= Decimal
.GetBits (Value
);
1668 int power
= (words
[3] >> 16) & 0xff;
1670 if (power
== 0 && Value
<= int.MaxValue
&& Value
>= int.MinValue
)
1672 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1673 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1674 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1676 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1680 IntConstant
.EmitInt (ig
, (int)Value
);
1681 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1687 // FIXME: we could optimize this, and call a better
1691 IntConstant
.EmitInt (ig
, words
[0]);
1692 IntConstant
.EmitInt (ig
, words
[1]);
1693 IntConstant
.EmitInt (ig
, words
[2]);
1696 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1699 IntConstant
.EmitInt (ig
, power
);
1701 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1702 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1703 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1704 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1706 if (TypeManager
.void_decimal_ctor_five_args
== null)
1710 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1713 public override Constant
Increment ()
1715 return new DecimalConstant (checked (Value
+ 1), loc
);
1718 public override bool IsDefaultValue
{
1724 public override bool IsNegative
{
1730 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1732 if (target_type
== TypeManager
.sbyte_type
)
1733 return new SByteConstant ((sbyte)Value
, loc
);
1734 if (target_type
== TypeManager
.byte_type
)
1735 return new ByteConstant ((byte)Value
, loc
);
1736 if (target_type
== TypeManager
.short_type
)
1737 return new ShortConstant ((short)Value
, loc
);
1738 if (target_type
== TypeManager
.ushort_type
)
1739 return new UShortConstant ((ushort)Value
, loc
);
1740 if (target_type
== TypeManager
.int32_type
)
1741 return new IntConstant ((int)Value
, loc
);
1742 if (target_type
== TypeManager
.uint32_type
)
1743 return new UIntConstant ((uint)Value
, loc
);
1744 if (target_type
== TypeManager
.int64_type
)
1745 return new LongConstant ((long)Value
, loc
);
1746 if (target_type
== TypeManager
.uint64_type
)
1747 return new ULongConstant ((ulong)Value
, loc
);
1748 if (target_type
== TypeManager
.char_type
)
1749 return new CharConstant ((char)Value
, loc
);
1750 if (target_type
== TypeManager
.float_type
)
1751 return new FloatConstant ((float)Value
, loc
);
1752 if (target_type
== TypeManager
.double_type
)
1753 return new DoubleConstant ((double)Value
, loc
);
1760 public class StringConstant
: Constant
{
1761 public readonly string Value
;
1763 public StringConstant (string s
, Location loc
):
1766 type
= TypeManager
.string_type
;
1767 eclass
= ExprClass
.Value
;
1771 // FIXME: Escape the string.
1772 override public string AsString ()
1774 return "\"" + Value
+ "\"";
1777 public override object GetValue ()
1782 public override void Emit (EmitContext ec
)
1784 if (Value
== null) {
1785 ec
.ig
.Emit (OpCodes
.Ldnull
);
1790 // Use string.Empty for both literals and constants even if
1791 // it's not allowed at language level
1793 if (Value
.Length
== 0 && RootContext
.Optimize
&& ec
.TypeContainer
.TypeBuilder
!= TypeManager
.string_type
) {
1794 if (TypeManager
.string_empty
== null)
1795 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
);
1797 if (TypeManager
.string_empty
!= null) {
1798 ec
.ig
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1803 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1806 public override Constant
Increment ()
1808 throw new NotSupportedException ();
1811 public override bool IsDefaultValue
{
1813 return Value
== null;
1817 public override bool IsNegative
{
1823 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1830 /// The value is constant, but when emitted has a side effect. This is
1831 /// used by BitwiseAnd to ensure that the second expression is invoked
1832 /// regardless of the value of the left side.
1835 public class SideEffectConstant
: Constant
{
1836 public Constant
value;
1837 Expression side_effect
;
1839 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
1842 while (side_effect
is SideEffectConstant
)
1843 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
1844 this.side_effect
= side_effect
;
1845 eclass
= ExprClass
.Value
;
1849 public override string AsString ()
1851 return value.AsString ();
1854 public override object GetValue ()
1856 return value.GetValue ();
1859 public override void Emit (EmitContext ec
)
1861 side_effect
.EmitSideEffect (ec
);
1865 public override void EmitSideEffect (EmitContext ec
)
1867 side_effect
.EmitSideEffect (ec
);
1868 value.EmitSideEffect (ec
);
1871 public override bool IsDefaultValue
{
1872 get { return value.IsDefaultValue; }
1875 public override Constant
Increment ()
1877 throw new NotSupportedException ();
1880 public override bool IsNegative
{
1881 get { return value.IsNegative; }
1884 public override bool IsZeroInteger
{
1885 get { return value.IsZeroInteger; }
1888 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1890 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
1891 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);