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 Arguments args
= new Arguments (2);
167 args
.Add (new Argument (this));
168 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
170 return CreateExpressionFactoryCall ("Constant", args
);
175 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
176 /// It throws OverflowException
178 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
179 public abstract Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
);
182 /// Attempts to do a compile-time folding of a constant cast.
184 public Constant
TryReduce (EmitContext ec
, Type target_type
, Location loc
)
187 return TryReduce (ec
, target_type
);
189 catch (OverflowException
) {
190 if (ec
.ConstantCheckState
) {
191 Report
.Error (221, loc
, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
192 GetValue ().ToString (), TypeManager
.CSharpName (target_type
));
194 Error_ValueCannotBeConverted (ec
, loc
, target_type
, false);
197 return New
.Constantify (target_type
);
201 Constant
TryReduce (EmitContext ec
, Type target_type
)
203 if (Type
== target_type
)
206 if (TypeManager
.IsEnumType (target_type
)) {
207 Constant c
= TryReduce (ec
, TypeManager
.GetEnumUnderlyingType (target_type
));
211 return new EnumConstant (c
, target_type
);
214 return ConvertExplicitly (ec
.ConstantCheckState
, target_type
);
217 public abstract Constant
Increment ();
220 /// Need to pass type as the constant can require a boxing
221 /// and in such case no optimization is possible
223 public bool IsDefaultInitializer (Type type
)
226 return IsDefaultValue
;
228 return this is NullLiteral
;
231 public abstract bool IsDefaultValue
{
235 public abstract bool IsNegative
{
240 // When constant is declared as literal
242 public virtual bool IsLiteral
{
243 get { return false; }
247 // Returns true iff 1) the stack type of this is one of Object,
248 // int32, int64 and 2) this == 0 or this == null.
250 public virtual bool IsZeroInteger
{
251 get { return false; }
254 public override void EmitSideEffect (EmitContext ec
)
259 protected override void CloneTo (CloneContext clonectx
, Expression target
)
261 // CloneTo: Nothing, we do not keep any state on this expression
264 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
266 // A constant cannot be of generic type
270 public abstract class IntegralConstant
: Constant
{
271 protected IntegralConstant (Location loc
) :
276 public override void Error_ValueCannotBeConverted (EmitContext ec
, Location loc
, Type target
, bool expl
)
279 ConvertExplicitly (true, target
);
280 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
284 Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
285 GetValue ().ToString (), TypeManager
.CSharpName (target
));
290 public class BoolConstant
: Constant
{
291 public readonly bool Value
;
293 public BoolConstant (bool val
, Location loc
):
296 type
= TypeManager
.bool_type
;
297 eclass
= ExprClass
.Value
;
302 override public string AsString ()
304 return Value
? "true" : "false";
307 public override object GetValue ()
309 return (object) Value
;
313 public override void Emit (EmitContext ec
)
316 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
318 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
321 public override Constant
Increment ()
323 throw new NotSupportedException ();
326 public override bool IsDefaultValue
{
332 public override bool IsNegative
{
338 public override bool IsZeroInteger
{
339 get { return Value == false; }
342 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
349 public class ByteConstant
: IntegralConstant
{
350 public readonly byte Value
;
352 public ByteConstant (byte v
, Location loc
):
355 type
= TypeManager
.byte_type
;
356 eclass
= ExprClass
.Value
;
360 public override void Emit (EmitContext ec
)
362 IntLiteral
.EmitInt (ec
.ig
, Value
);
365 public override string AsString ()
367 return Value
.ToString ();
370 public override object GetValue ()
375 public override Constant
Increment ()
377 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
380 public override bool IsDefaultValue
{
386 public override bool IsNegative
{
392 public override bool IsZeroInteger
{
393 get { return Value == 0; }
396 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
398 if (target_type
== TypeManager
.sbyte_type
) {
399 if (in_checked_context
){
400 if (Value
> SByte
.MaxValue
)
401 throw new OverflowException ();
403 return new SByteConstant ((sbyte) Value
, Location
);
405 if (target_type
== TypeManager
.short_type
)
406 return new ShortConstant ((short) Value
, Location
);
407 if (target_type
== TypeManager
.ushort_type
)
408 return new UShortConstant ((ushort) Value
, Location
);
409 if (target_type
== TypeManager
.int32_type
)
410 return new IntConstant ((int) Value
, Location
);
411 if (target_type
== TypeManager
.uint32_type
)
412 return new UIntConstant ((uint) Value
, Location
);
413 if (target_type
== TypeManager
.int64_type
)
414 return new LongConstant ((long) Value
, Location
);
415 if (target_type
== TypeManager
.uint64_type
)
416 return new ULongConstant ((ulong) Value
, Location
);
417 if (target_type
== TypeManager
.float_type
)
418 return new FloatConstant ((float) Value
, Location
);
419 if (target_type
== TypeManager
.double_type
)
420 return new DoubleConstant ((double) Value
, Location
);
421 if (target_type
== TypeManager
.char_type
)
422 return new CharConstant ((char) Value
, Location
);
423 if (target_type
== TypeManager
.decimal_type
)
424 return new DecimalConstant ((decimal) Value
, Location
);
431 public class CharConstant
: Constant
{
432 public readonly char Value
;
434 public CharConstant (char v
, Location loc
):
437 type
= TypeManager
.char_type
;
438 eclass
= ExprClass
.Value
;
442 public override void Emit (EmitContext ec
)
444 IntLiteral
.EmitInt (ec
.ig
, Value
);
447 static public string descape (char c
)
473 return c
.ToString ();
476 public override string AsString ()
478 return "\"" + descape (Value
) + "\"";
481 public override object GetValue ()
486 public override Constant
Increment ()
488 return new CharConstant (checked ((char)(Value
+ 1)), loc
);
491 public override bool IsDefaultValue
{
497 public override bool IsNegative
{
503 public override bool IsZeroInteger
{
504 get { return Value == '\0'; }
507 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
509 if (target_type
== TypeManager
.byte_type
) {
510 if (in_checked_context
){
511 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
512 throw new OverflowException ();
514 return new ByteConstant ((byte) Value
, Location
);
516 if (target_type
== TypeManager
.sbyte_type
) {
517 if (in_checked_context
){
518 if (Value
> SByte
.MaxValue
)
519 throw new OverflowException ();
521 return new SByteConstant ((sbyte) Value
, Location
);
523 if (target_type
== TypeManager
.short_type
) {
524 if (in_checked_context
){
525 if (Value
> Int16
.MaxValue
)
526 throw new OverflowException ();
528 return new ShortConstant ((short) Value
, Location
);
530 if (target_type
== TypeManager
.int32_type
)
531 return new IntConstant ((int) Value
, Location
);
532 if (target_type
== TypeManager
.uint32_type
)
533 return new UIntConstant ((uint) Value
, Location
);
534 if (target_type
== TypeManager
.int64_type
)
535 return new LongConstant ((long) Value
, Location
);
536 if (target_type
== TypeManager
.uint64_type
)
537 return new ULongConstant ((ulong) Value
, Location
);
538 if (target_type
== TypeManager
.float_type
)
539 return new FloatConstant ((float) Value
, Location
);
540 if (target_type
== TypeManager
.double_type
)
541 return new DoubleConstant ((double) Value
, Location
);
542 if (target_type
== TypeManager
.decimal_type
)
543 return new DecimalConstant ((decimal) Value
, Location
);
550 public class SByteConstant
: IntegralConstant
{
551 public readonly sbyte Value
;
553 public SByteConstant (sbyte v
, Location loc
):
556 type
= TypeManager
.sbyte_type
;
557 eclass
= ExprClass
.Value
;
561 public override void Emit (EmitContext ec
)
563 IntLiteral
.EmitInt (ec
.ig
, Value
);
566 public override string AsString ()
568 return Value
.ToString ();
571 public override object GetValue ()
576 public override Constant
Increment ()
578 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
581 public override bool IsDefaultValue
{
587 public override bool IsNegative
{
593 public override bool IsZeroInteger
{
594 get { return Value == 0; }
597 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
599 if (target_type
== TypeManager
.byte_type
) {
600 if (in_checked_context
&& Value
< 0)
601 throw new OverflowException ();
602 return new ByteConstant ((byte) Value
, Location
);
604 if (target_type
== TypeManager
.short_type
)
605 return new ShortConstant ((short) Value
, Location
);
606 if (target_type
== TypeManager
.ushort_type
) {
607 if (in_checked_context
&& Value
< 0)
608 throw new OverflowException ();
609 return new UShortConstant ((ushort) Value
, Location
);
610 } if (target_type
== TypeManager
.int32_type
)
611 return new IntConstant ((int) Value
, Location
);
612 if (target_type
== TypeManager
.uint32_type
) {
613 if (in_checked_context
&& Value
< 0)
614 throw new OverflowException ();
615 return new UIntConstant ((uint) Value
, Location
);
616 } if (target_type
== TypeManager
.int64_type
)
617 return new LongConstant ((long) Value
, Location
);
618 if (target_type
== TypeManager
.uint64_type
) {
619 if (in_checked_context
&& Value
< 0)
620 throw new OverflowException ();
621 return new ULongConstant ((ulong) Value
, Location
);
623 if (target_type
== TypeManager
.float_type
)
624 return new FloatConstant ((float) Value
, Location
);
625 if (target_type
== TypeManager
.double_type
)
626 return new DoubleConstant ((double) Value
, Location
);
627 if (target_type
== TypeManager
.char_type
) {
628 if (in_checked_context
&& Value
< 0)
629 throw new OverflowException ();
630 return new CharConstant ((char) Value
, Location
);
632 if (target_type
== TypeManager
.decimal_type
)
633 return new DecimalConstant ((decimal) Value
, Location
);
640 public class ShortConstant
: IntegralConstant
{
641 public readonly short Value
;
643 public ShortConstant (short v
, Location loc
):
646 type
= TypeManager
.short_type
;
647 eclass
= ExprClass
.Value
;
651 public override void Emit (EmitContext ec
)
653 IntLiteral
.EmitInt (ec
.ig
, Value
);
656 public override string AsString ()
658 return Value
.ToString ();
661 public override object GetValue ()
666 public override Constant
Increment ()
668 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
671 public override bool IsDefaultValue
{
677 public override bool IsZeroInteger
{
678 get { return Value == 0; }
681 public override bool IsNegative
{
687 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
689 if (target_type
== TypeManager
.byte_type
) {
690 if (in_checked_context
){
691 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
692 throw new OverflowException ();
694 return new ByteConstant ((byte) Value
, Location
);
696 if (target_type
== TypeManager
.sbyte_type
) {
697 if (in_checked_context
){
698 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
699 throw new OverflowException ();
701 return new SByteConstant ((sbyte) Value
, Location
);
703 if (target_type
== TypeManager
.ushort_type
) {
704 if (in_checked_context
&& Value
< 0)
705 throw new OverflowException ();
707 return new UShortConstant ((ushort) Value
, Location
);
709 if (target_type
== TypeManager
.int32_type
)
710 return new IntConstant ((int) Value
, Location
);
711 if (target_type
== TypeManager
.uint32_type
) {
712 if (in_checked_context
&& Value
< 0)
713 throw new OverflowException ();
714 return new UIntConstant ((uint) Value
, Location
);
716 if (target_type
== TypeManager
.int64_type
)
717 return new LongConstant ((long) Value
, Location
);
718 if (target_type
== TypeManager
.uint64_type
) {
719 if (in_checked_context
&& Value
< 0)
720 throw new OverflowException ();
721 return new ULongConstant ((ulong) Value
, Location
);
723 if (target_type
== TypeManager
.float_type
)
724 return new FloatConstant ((float) Value
, Location
);
725 if (target_type
== TypeManager
.double_type
)
726 return new DoubleConstant ((double) Value
, Location
);
727 if (target_type
== TypeManager
.char_type
) {
728 if (in_checked_context
){
729 if (Value
< Char
.MinValue
)
730 throw new OverflowException ();
732 return new CharConstant ((char) Value
, Location
);
734 if (target_type
== TypeManager
.decimal_type
)
735 return new DecimalConstant ((decimal) Value
, Location
);
742 public class UShortConstant
: IntegralConstant
{
743 public readonly ushort Value
;
745 public UShortConstant (ushort v
, Location loc
):
748 type
= TypeManager
.ushort_type
;
749 eclass
= ExprClass
.Value
;
753 public override void Emit (EmitContext ec
)
755 IntLiteral
.EmitInt (ec
.ig
, Value
);
758 public override string AsString ()
760 return Value
.ToString ();
763 public override object GetValue ()
768 public override Constant
Increment ()
770 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
773 public override bool IsDefaultValue
{
779 public override bool IsNegative
{
785 public override bool IsZeroInteger
{
786 get { return Value == 0; }
789 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
791 if (target_type
== TypeManager
.byte_type
) {
792 if (in_checked_context
){
793 if (Value
> Byte
.MaxValue
)
794 throw new OverflowException ();
796 return new ByteConstant ((byte) Value
, Location
);
798 if (target_type
== TypeManager
.sbyte_type
) {
799 if (in_checked_context
){
800 if (Value
> SByte
.MaxValue
)
801 throw new OverflowException ();
803 return new SByteConstant ((sbyte) Value
, Location
);
805 if (target_type
== TypeManager
.short_type
) {
806 if (in_checked_context
){
807 if (Value
> Int16
.MaxValue
)
808 throw new OverflowException ();
810 return new ShortConstant ((short) Value
, Location
);
812 if (target_type
== TypeManager
.int32_type
)
813 return new IntConstant ((int) Value
, Location
);
814 if (target_type
== TypeManager
.uint32_type
)
815 return new UIntConstant ((uint) Value
, Location
);
816 if (target_type
== TypeManager
.int64_type
)
817 return new LongConstant ((long) Value
, Location
);
818 if (target_type
== TypeManager
.uint64_type
)
819 return new ULongConstant ((ulong) Value
, Location
);
820 if (target_type
== TypeManager
.float_type
)
821 return new FloatConstant ((float) Value
, Location
);
822 if (target_type
== TypeManager
.double_type
)
823 return new DoubleConstant ((double) Value
, Location
);
824 if (target_type
== TypeManager
.char_type
) {
825 if (in_checked_context
){
826 if (Value
> Char
.MaxValue
)
827 throw new OverflowException ();
829 return new CharConstant ((char) Value
, Location
);
831 if (target_type
== TypeManager
.decimal_type
)
832 return new DecimalConstant ((decimal) Value
, Location
);
838 public class IntConstant
: IntegralConstant
{
839 public readonly int Value
;
841 public IntConstant (int v
, Location loc
):
844 type
= TypeManager
.int32_type
;
845 eclass
= ExprClass
.Value
;
849 static public void EmitInt (ILGenerator ig
, int i
)
853 ig
.Emit (OpCodes
.Ldc_I4_M1
);
857 ig
.Emit (OpCodes
.Ldc_I4_0
);
861 ig
.Emit (OpCodes
.Ldc_I4_1
);
865 ig
.Emit (OpCodes
.Ldc_I4_2
);
869 ig
.Emit (OpCodes
.Ldc_I4_3
);
873 ig
.Emit (OpCodes
.Ldc_I4_4
);
877 ig
.Emit (OpCodes
.Ldc_I4_5
);
881 ig
.Emit (OpCodes
.Ldc_I4_6
);
885 ig
.Emit (OpCodes
.Ldc_I4_7
);
889 ig
.Emit (OpCodes
.Ldc_I4_8
);
893 if (i
>= -128 && i
<= 127){
894 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
896 ig
.Emit (OpCodes
.Ldc_I4
, i
);
901 public override void Emit (EmitContext ec
)
903 EmitInt (ec
.ig
, Value
);
906 public override string AsString ()
908 return Value
.ToString ();
911 public override object GetValue ()
916 public override Constant
Increment ()
918 return new IntConstant (checked(Value
+ 1), loc
);
921 public override bool IsDefaultValue
{
927 public override bool IsNegative
{
933 public override bool IsZeroInteger
{
934 get { return Value == 0; }
937 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
939 if (target_type
== TypeManager
.byte_type
) {
940 if (in_checked_context
){
941 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
942 throw new OverflowException ();
944 return new ByteConstant ((byte) Value
, Location
);
946 if (target_type
== TypeManager
.sbyte_type
) {
947 if (in_checked_context
){
948 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
949 throw new OverflowException ();
951 return new SByteConstant ((sbyte) Value
, Location
);
953 if (target_type
== TypeManager
.short_type
) {
954 if (in_checked_context
){
955 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
956 throw new OverflowException ();
958 return new ShortConstant ((short) Value
, Location
);
960 if (target_type
== TypeManager
.ushort_type
) {
961 if (in_checked_context
){
962 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
963 throw new OverflowException ();
965 return new UShortConstant ((ushort) Value
, Location
);
967 if (target_type
== TypeManager
.uint32_type
) {
968 if (in_checked_context
){
969 if (Value
< UInt32
.MinValue
)
970 throw new OverflowException ();
972 return new UIntConstant ((uint) Value
, Location
);
974 if (target_type
== TypeManager
.int64_type
)
975 return new LongConstant ((long) Value
, Location
);
976 if (target_type
== TypeManager
.uint64_type
) {
977 if (in_checked_context
&& Value
< 0)
978 throw new OverflowException ();
979 return new ULongConstant ((ulong) Value
, Location
);
981 if (target_type
== TypeManager
.float_type
)
982 return new FloatConstant ((float) Value
, Location
);
983 if (target_type
== TypeManager
.double_type
)
984 return new DoubleConstant ((double) Value
, Location
);
985 if (target_type
== TypeManager
.char_type
) {
986 if (in_checked_context
){
987 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
988 throw new OverflowException ();
990 return new CharConstant ((char) Value
, Location
);
992 if (target_type
== TypeManager
.decimal_type
)
993 return new DecimalConstant ((decimal) Value
, Location
);
998 public override Constant
ConvertImplicitly (Type type
)
1000 if (this.type
== type
)
1003 Constant c
= TryImplicitIntConversion (type
);
1007 return base.ConvertImplicitly (type
);
1011 /// Attempts to perform an implicit constant conversion of the IntConstant
1012 /// into a different data type using casts (See Implicit Constant
1013 /// Expression Conversions)
1015 Constant
TryImplicitIntConversion (Type target_type
)
1017 if (target_type
== TypeManager
.sbyte_type
) {
1018 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1019 return new SByteConstant ((sbyte) Value
, loc
);
1021 else if (target_type
== TypeManager
.byte_type
) {
1022 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1023 return new ByteConstant ((byte) Value
, loc
);
1025 else if (target_type
== TypeManager
.short_type
) {
1026 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1027 return new ShortConstant ((short) Value
, loc
);
1029 else if (target_type
== TypeManager
.ushort_type
) {
1030 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1031 return new UShortConstant ((ushort) Value
, loc
);
1033 else if (target_type
== TypeManager
.uint32_type
) {
1035 return new UIntConstant ((uint) Value
, loc
);
1037 else if (target_type
== TypeManager
.uint64_type
) {
1039 // we can optimize this case: a positive int32
1040 // always fits on a uint64. But we need an opcode
1044 return new ULongConstant ((ulong) Value
, loc
);
1046 else if (target_type
== TypeManager
.double_type
)
1047 return new DoubleConstant ((double) Value
, loc
);
1048 else if (target_type
== TypeManager
.float_type
)
1049 return new FloatConstant ((float) Value
, loc
);
1055 public class UIntConstant
: IntegralConstant
{
1056 public readonly uint Value
;
1058 public UIntConstant (uint v
, Location loc
):
1061 type
= TypeManager
.uint32_type
;
1062 eclass
= ExprClass
.Value
;
1066 public override void Emit (EmitContext ec
)
1068 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
1071 public override string AsString ()
1073 return Value
.ToString ();
1076 public override object GetValue ()
1081 public override Constant
Increment ()
1083 return new UIntConstant (checked(Value
+ 1), loc
);
1086 public override bool IsDefaultValue
{
1092 public override bool IsNegative
{
1098 public override bool IsZeroInteger
{
1099 get { return Value == 0; }
1102 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1104 if (target_type
== TypeManager
.byte_type
) {
1105 if (in_checked_context
){
1106 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1107 throw new OverflowException ();
1109 return new ByteConstant ((byte) Value
, Location
);
1111 if (target_type
== TypeManager
.sbyte_type
) {
1112 if (in_checked_context
){
1113 if (Value
> SByte
.MaxValue
)
1114 throw new OverflowException ();
1116 return new SByteConstant ((sbyte) Value
, Location
);
1118 if (target_type
== TypeManager
.short_type
) {
1119 if (in_checked_context
){
1120 if (Value
> Int16
.MaxValue
)
1121 throw new OverflowException ();
1123 return new ShortConstant ((short) Value
, Location
);
1125 if (target_type
== TypeManager
.ushort_type
) {
1126 if (in_checked_context
){
1127 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1128 throw new OverflowException ();
1130 return new UShortConstant ((ushort) Value
, Location
);
1132 if (target_type
== TypeManager
.int32_type
) {
1133 if (in_checked_context
){
1134 if (Value
> Int32
.MaxValue
)
1135 throw new OverflowException ();
1137 return new IntConstant ((int) Value
, Location
);
1139 if (target_type
== TypeManager
.int64_type
)
1140 return new LongConstant ((long) Value
, Location
);
1141 if (target_type
== TypeManager
.uint64_type
)
1142 return new ULongConstant ((ulong) Value
, Location
);
1143 if (target_type
== TypeManager
.float_type
)
1144 return new FloatConstant ((float) Value
, Location
);
1145 if (target_type
== TypeManager
.double_type
)
1146 return new DoubleConstant ((double) Value
, Location
);
1147 if (target_type
== TypeManager
.char_type
) {
1148 if (in_checked_context
){
1149 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1150 throw new OverflowException ();
1152 return new CharConstant ((char) Value
, Location
);
1154 if (target_type
== TypeManager
.decimal_type
)
1155 return new DecimalConstant ((decimal) Value
, Location
);
1162 public class LongConstant
: IntegralConstant
{
1163 public readonly long Value
;
1165 public LongConstant (long v
, Location loc
):
1168 type
= TypeManager
.int64_type
;
1169 eclass
= ExprClass
.Value
;
1173 public override void Emit (EmitContext ec
)
1175 EmitLong (ec
.ig
, Value
);
1178 static public void EmitLong (ILGenerator ig
, long l
)
1180 if (l
>= int.MinValue
&& l
<= int.MaxValue
) {
1181 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1182 ig
.Emit (OpCodes
.Conv_I8
);
1186 if (l
>= 0 && l
<= uint.MaxValue
) {
1187 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1188 ig
.Emit (OpCodes
.Conv_U8
);
1192 ig
.Emit (OpCodes
.Ldc_I8
, l
);
1195 public override string AsString ()
1197 return Value
.ToString ();
1200 public override object GetValue ()
1205 public override Constant
Increment ()
1207 return new LongConstant (checked(Value
+ 1), loc
);
1210 public override bool IsDefaultValue
{
1216 public override bool IsNegative
{
1222 public override bool IsZeroInteger
{
1223 get { return Value == 0; }
1226 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1228 if (target_type
== TypeManager
.byte_type
) {
1229 if (in_checked_context
){
1230 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1231 throw new OverflowException ();
1233 return new ByteConstant ((byte) Value
, Location
);
1235 if (target_type
== TypeManager
.sbyte_type
) {
1236 if (in_checked_context
){
1237 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1238 throw new OverflowException ();
1240 return new SByteConstant ((sbyte) Value
, Location
);
1242 if (target_type
== TypeManager
.short_type
) {
1243 if (in_checked_context
){
1244 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1245 throw new OverflowException ();
1247 return new ShortConstant ((short) Value
, Location
);
1249 if (target_type
== TypeManager
.ushort_type
) {
1250 if (in_checked_context
){
1251 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1252 throw new OverflowException ();
1254 return new UShortConstant ((ushort) Value
, Location
);
1256 if (target_type
== TypeManager
.int32_type
) {
1257 if (in_checked_context
){
1258 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1259 throw new OverflowException ();
1261 return new IntConstant ((int) Value
, Location
);
1263 if (target_type
== TypeManager
.uint32_type
) {
1264 if (in_checked_context
){
1265 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1266 throw new OverflowException ();
1268 return new UIntConstant ((uint) Value
, Location
);
1270 if (target_type
== TypeManager
.uint64_type
) {
1271 if (in_checked_context
&& Value
< 0)
1272 throw new OverflowException ();
1273 return new ULongConstant ((ulong) Value
, Location
);
1275 if (target_type
== TypeManager
.float_type
)
1276 return new FloatConstant ((float) Value
, Location
);
1277 if (target_type
== TypeManager
.double_type
)
1278 return new DoubleConstant ((double) Value
, Location
);
1279 if (target_type
== TypeManager
.char_type
) {
1280 if (in_checked_context
){
1281 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1282 throw new OverflowException ();
1284 return new CharConstant ((char) Value
, Location
);
1286 if (target_type
== TypeManager
.decimal_type
)
1287 return new DecimalConstant ((decimal) Value
, Location
);
1292 public override Constant
ConvertImplicitly (Type type
)
1294 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1295 return new ULongConstant ((ulong) Value
, loc
);
1298 return base.ConvertImplicitly (type
);
1302 public class ULongConstant
: IntegralConstant
{
1303 public readonly ulong Value
;
1305 public ULongConstant (ulong v
, Location loc
):
1308 type
= TypeManager
.uint64_type
;
1309 eclass
= ExprClass
.Value
;
1313 public override void Emit (EmitContext ec
)
1315 ILGenerator ig
= ec
.ig
;
1317 LongLiteral
.EmitLong (ig
, unchecked ((long) Value
));
1320 public override string AsString ()
1322 return Value
.ToString ();
1325 public override object GetValue ()
1330 public override Constant
Increment ()
1332 return new ULongConstant (checked(Value
+ 1), loc
);
1335 public override bool IsDefaultValue
{
1341 public override bool IsNegative
{
1347 public override bool IsZeroInteger
{
1348 get { return Value == 0; }
1351 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1353 if (target_type
== TypeManager
.byte_type
) {
1354 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1355 throw new OverflowException ();
1356 return new ByteConstant ((byte) Value
, Location
);
1358 if (target_type
== TypeManager
.sbyte_type
) {
1359 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1360 throw new OverflowException ();
1361 return new SByteConstant ((sbyte) Value
, Location
);
1363 if (target_type
== TypeManager
.short_type
) {
1364 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1365 throw new OverflowException ();
1366 return new ShortConstant ((short) Value
, Location
);
1368 if (target_type
== TypeManager
.ushort_type
) {
1369 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1370 throw new OverflowException ();
1371 return new UShortConstant ((ushort) Value
, Location
);
1373 if (target_type
== TypeManager
.int32_type
) {
1374 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1375 throw new OverflowException ();
1376 return new IntConstant ((int) Value
, Location
);
1378 if (target_type
== TypeManager
.uint32_type
) {
1379 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1380 throw new OverflowException ();
1381 return new UIntConstant ((uint) Value
, Location
);
1383 if (target_type
== TypeManager
.int64_type
) {
1384 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1385 throw new OverflowException ();
1386 return new LongConstant ((long) Value
, Location
);
1388 if (target_type
== TypeManager
.float_type
)
1389 return new FloatConstant ((float) Value
, Location
);
1390 if (target_type
== TypeManager
.double_type
)
1391 return new DoubleConstant ((double) Value
, Location
);
1392 if (target_type
== TypeManager
.char_type
) {
1393 if (in_checked_context
&& Value
> Char
.MaxValue
)
1394 throw new OverflowException ();
1395 return new CharConstant ((char) Value
, Location
);
1397 if (target_type
== TypeManager
.decimal_type
)
1398 return new DecimalConstant ((decimal) Value
, Location
);
1405 public class FloatConstant
: Constant
{
1408 public FloatConstant (float v
, Location loc
):
1411 type
= TypeManager
.float_type
;
1412 eclass
= ExprClass
.Value
;
1416 public override void Emit (EmitContext ec
)
1418 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
1421 public override string AsString ()
1423 return Value
.ToString ();
1426 public override object GetValue ()
1431 public override Constant
Increment ()
1433 return new FloatConstant (checked(Value
+ 1), loc
);
1436 public override bool IsDefaultValue
{
1442 public override bool IsNegative
{
1448 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1450 if (target_type
== TypeManager
.byte_type
) {
1451 if (in_checked_context
){
1452 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1453 throw new OverflowException ();
1455 return new ByteConstant ((byte) Value
, Location
);
1457 if (target_type
== TypeManager
.sbyte_type
) {
1458 if (in_checked_context
){
1459 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1460 throw new OverflowException ();
1462 return new SByteConstant ((sbyte) Value
, Location
);
1464 if (target_type
== TypeManager
.short_type
) {
1465 if (in_checked_context
){
1466 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1467 throw new OverflowException ();
1469 return new ShortConstant ((short) Value
, Location
);
1471 if (target_type
== TypeManager
.ushort_type
) {
1472 if (in_checked_context
){
1473 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1474 throw new OverflowException ();
1476 return new UShortConstant ((ushort) Value
, Location
);
1478 if (target_type
== TypeManager
.int32_type
) {
1479 if (in_checked_context
){
1480 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1481 throw new OverflowException ();
1483 return new IntConstant ((int) Value
, Location
);
1485 if (target_type
== TypeManager
.uint32_type
) {
1486 if (in_checked_context
){
1487 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1488 throw new OverflowException ();
1490 return new UIntConstant ((uint) Value
, Location
);
1492 if (target_type
== TypeManager
.int64_type
) {
1493 if (in_checked_context
){
1494 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1495 throw new OverflowException ();
1497 return new LongConstant ((long) Value
, Location
);
1499 if (target_type
== TypeManager
.uint64_type
) {
1500 if (in_checked_context
){
1501 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1502 throw new OverflowException ();
1504 return new ULongConstant ((ulong) Value
, Location
);
1506 if (target_type
== TypeManager
.double_type
)
1507 return new DoubleConstant ((double) Value
, Location
);
1508 if (target_type
== TypeManager
.char_type
) {
1509 if (in_checked_context
){
1510 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1511 throw new OverflowException ();
1513 return new CharConstant ((char) Value
, Location
);
1515 if (target_type
== TypeManager
.decimal_type
)
1516 return new DecimalConstant ((decimal) Value
, Location
);
1523 public class DoubleConstant
: Constant
{
1524 public double Value
;
1526 public DoubleConstant (double v
, Location loc
):
1529 type
= TypeManager
.double_type
;
1530 eclass
= ExprClass
.Value
;
1534 public override void Emit (EmitContext ec
)
1536 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
1539 public override string AsString ()
1541 return Value
.ToString ();
1544 public override object GetValue ()
1549 public override Constant
Increment ()
1551 return new DoubleConstant (checked(Value
+ 1), loc
);
1554 public override bool IsDefaultValue
{
1560 public override bool IsNegative
{
1566 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1568 if (target_type
== TypeManager
.byte_type
) {
1569 if (in_checked_context
){
1570 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1571 throw new OverflowException ();
1573 return new ByteConstant ((byte) Value
, Location
);
1575 if (target_type
== TypeManager
.sbyte_type
) {
1576 if (in_checked_context
){
1577 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1578 throw new OverflowException ();
1580 return new SByteConstant ((sbyte) Value
, Location
);
1582 if (target_type
== TypeManager
.short_type
) {
1583 if (in_checked_context
){
1584 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1585 throw new OverflowException ();
1587 return new ShortConstant ((short) Value
, Location
);
1589 if (target_type
== TypeManager
.ushort_type
) {
1590 if (in_checked_context
){
1591 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1592 throw new OverflowException ();
1594 return new UShortConstant ((ushort) Value
, Location
);
1596 if (target_type
== TypeManager
.int32_type
) {
1597 if (in_checked_context
){
1598 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1599 throw new OverflowException ();
1601 return new IntConstant ((int) Value
, Location
);
1603 if (target_type
== TypeManager
.uint32_type
) {
1604 if (in_checked_context
){
1605 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1606 throw new OverflowException ();
1608 return new UIntConstant ((uint) Value
, Location
);
1610 if (target_type
== TypeManager
.int64_type
) {
1611 if (in_checked_context
){
1612 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1613 throw new OverflowException ();
1615 return new LongConstant ((long) Value
, Location
);
1617 if (target_type
== TypeManager
.uint64_type
) {
1618 if (in_checked_context
){
1619 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1620 throw new OverflowException ();
1622 return new ULongConstant ((ulong) Value
, Location
);
1624 if (target_type
== TypeManager
.float_type
)
1625 return new FloatConstant ((float) Value
, Location
);
1626 if (target_type
== TypeManager
.char_type
) {
1627 if (in_checked_context
){
1628 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1629 throw new OverflowException ();
1631 return new CharConstant ((char) Value
, Location
);
1633 if (target_type
== TypeManager
.decimal_type
)
1634 return new DecimalConstant ((decimal) Value
, Location
);
1641 public class DecimalConstant
: Constant
{
1642 public readonly decimal Value
;
1644 public DecimalConstant (decimal d
, Location loc
):
1647 type
= TypeManager
.decimal_type
;
1648 eclass
= ExprClass
.Value
;
1652 override public string AsString ()
1654 return Value
.ToString () + "M";
1657 public override object GetValue ()
1659 return (object) Value
;
1662 public override void Emit (EmitContext ec
)
1664 ILGenerator ig
= ec
.ig
;
1666 int [] words
= Decimal
.GetBits (Value
);
1667 int power
= (words
[3] >> 16) & 0xff;
1669 if (power
== 0 && Value
<= int.MaxValue
&& Value
>= int.MinValue
)
1671 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1672 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1673 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1675 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1679 IntConstant
.EmitInt (ig
, (int)Value
);
1680 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1686 // FIXME: we could optimize this, and call a better
1690 IntConstant
.EmitInt (ig
, words
[0]);
1691 IntConstant
.EmitInt (ig
, words
[1]);
1692 IntConstant
.EmitInt (ig
, words
[2]);
1695 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1698 IntConstant
.EmitInt (ig
, power
);
1700 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1701 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1702 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1703 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1705 if (TypeManager
.void_decimal_ctor_five_args
== null)
1709 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1712 public override Constant
Increment ()
1714 return new DecimalConstant (checked (Value
+ 1), loc
);
1717 public override bool IsDefaultValue
{
1723 public override bool IsNegative
{
1729 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1731 if (target_type
== TypeManager
.sbyte_type
)
1732 return new SByteConstant ((sbyte)Value
, loc
);
1733 if (target_type
== TypeManager
.byte_type
)
1734 return new ByteConstant ((byte)Value
, loc
);
1735 if (target_type
== TypeManager
.short_type
)
1736 return new ShortConstant ((short)Value
, loc
);
1737 if (target_type
== TypeManager
.ushort_type
)
1738 return new UShortConstant ((ushort)Value
, loc
);
1739 if (target_type
== TypeManager
.int32_type
)
1740 return new IntConstant ((int)Value
, loc
);
1741 if (target_type
== TypeManager
.uint32_type
)
1742 return new UIntConstant ((uint)Value
, loc
);
1743 if (target_type
== TypeManager
.int64_type
)
1744 return new LongConstant ((long)Value
, loc
);
1745 if (target_type
== TypeManager
.uint64_type
)
1746 return new ULongConstant ((ulong)Value
, loc
);
1747 if (target_type
== TypeManager
.char_type
)
1748 return new CharConstant ((char)Value
, loc
);
1749 if (target_type
== TypeManager
.float_type
)
1750 return new FloatConstant ((float)Value
, loc
);
1751 if (target_type
== TypeManager
.double_type
)
1752 return new DoubleConstant ((double)Value
, loc
);
1759 public class StringConstant
: Constant
{
1760 public readonly string Value
;
1762 public StringConstant (string s
, Location loc
):
1765 type
= TypeManager
.string_type
;
1766 eclass
= ExprClass
.Value
;
1770 // FIXME: Escape the string.
1771 override public string AsString ()
1773 return "\"" + Value
+ "\"";
1776 public override object GetValue ()
1781 public override void Emit (EmitContext ec
)
1783 if (Value
== null) {
1784 ec
.ig
.Emit (OpCodes
.Ldnull
);
1789 // Use string.Empty for both literals and constants even if
1790 // it's not allowed at language level
1792 if (Value
.Length
== 0 && RootContext
.Optimize
&& ec
.TypeContainer
.TypeBuilder
!= TypeManager
.string_type
) {
1793 if (TypeManager
.string_empty
== null)
1794 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
);
1796 if (TypeManager
.string_empty
!= null) {
1797 ec
.ig
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1802 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1805 public override Constant
Increment ()
1807 throw new NotSupportedException ();
1810 public override bool IsDefaultValue
{
1812 return Value
== null;
1816 public override bool IsNegative
{
1822 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1829 /// The value is constant, but when emitted has a side effect. This is
1830 /// used by BitwiseAnd to ensure that the second expression is invoked
1831 /// regardless of the value of the left side.
1834 public class SideEffectConstant
: Constant
{
1835 public Constant
value;
1836 Expression side_effect
;
1838 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
1841 while (side_effect
is SideEffectConstant
)
1842 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
1843 this.side_effect
= side_effect
;
1844 eclass
= ExprClass
.Value
;
1848 public override string AsString ()
1850 return value.AsString ();
1853 public override object GetValue ()
1855 return value.GetValue ();
1858 public override void Emit (EmitContext ec
)
1860 side_effect
.EmitSideEffect (ec
);
1864 public override void EmitSideEffect (EmitContext ec
)
1866 side_effect
.EmitSideEffect (ec
);
1867 value.EmitSideEffect (ec
);
1870 public override bool IsDefaultValue
{
1871 get { return value.IsDefaultValue; }
1874 public override Constant
Increment ()
1876 throw new NotSupportedException ();
1879 public override bool IsNegative
{
1880 get { return value.IsNegative; }
1883 public override bool IsZeroInteger
{
1884 get { return value.IsZeroInteger; }
1887 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1889 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
1890 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);