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.
13 using System
.Reflection
.Emit
;
15 namespace Mono
.CSharp
{
18 /// Base class for constants and literals.
20 public abstract class Constant
: Expression
{
22 protected Constant (Location loc
)
28 /// This is different from ToString in that ToString
29 /// is supposed to be there for debugging purposes,
30 /// and is not guaranteed to be useful for anything else,
31 /// AsString() will provide something that can be used
32 /// for round-tripping C# code. Maybe it can be used
33 /// for IL assembly as well.
35 public abstract string AsString ();
37 override public string ToString ()
39 return this.GetType ().Name
+ " (" + AsString () + ")";
42 public override bool GetAttributableValue (ResolveContext ec
, Type value_type
, out object value)
44 if (value_type
== TypeManager
.object_type
) {
45 value = GetTypedValue ();
49 Constant c
= ImplicitConversionRequired (ec
, value_type
, loc
);
55 value = c
.GetTypedValue ();
60 /// This is used to obtain the actual value of the literal
61 /// cast into an object.
63 public abstract object GetValue ();
65 public virtual object GetTypedValue ()
70 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
72 if (!expl
&& IsLiteral
&&
73 (TypeManager
.IsPrimitiveType (target
) || type
== TypeManager
.decimal_type
) &&
74 (TypeManager
.IsPrimitiveType (type
) || type
== TypeManager
.decimal_type
)) {
75 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
76 AsString (), TypeManager
.CSharpName (target
));
78 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
82 public Constant
ImplicitConversionRequired (ResolveContext ec
, Type type
, Location loc
)
84 Constant c
= ConvertImplicitly (ec
, type
);
86 Error_ValueCannotBeConverted (ec
, loc
, type
, false);
91 public virtual Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
93 if (this.type
== type
)
96 if (Convert
.ImplicitNumericConversion (this, type
) == null)
100 object constant_value
= TypeManager
.ChangeType (GetValue (), type
, out fail
);
103 // We should always catch the error before this is ever
104 // reached, by calling Convert.ImplicitStandardConversionExists
106 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
107 TypeManager
.CSharpName (Type
), TypeManager
.CSharpName (type
));
110 return CreateConstant (rc
, type
, constant_value
, loc
);
114 // Returns a constant instance based on Type
116 public static Constant
CreateConstant (ResolveContext rc
, Type t
, object v
, Location loc
)
118 return CreateConstantFromValue (t
, v
, loc
).Resolve (rc
);
121 public static Constant
CreateConstantFromValue (Type t
, object v
, Location loc
)
123 if (t
== TypeManager
.int32_type
)
124 return new IntConstant ((int) v
, loc
);
125 if (t
== TypeManager
.string_type
)
126 return new StringConstant ((string) v
, loc
);
127 if (t
== TypeManager
.uint32_type
)
128 return new UIntConstant ((uint) v
, loc
);
129 if (t
== TypeManager
.int64_type
)
130 return new LongConstant ((long) v
, loc
);
131 if (t
== TypeManager
.uint64_type
)
132 return new ULongConstant ((ulong) v
, loc
);
133 if (t
== TypeManager
.float_type
)
134 return new FloatConstant ((float) v
, loc
);
135 if (t
== TypeManager
.double_type
)
136 return new DoubleConstant ((double) v
, loc
);
137 if (t
== TypeManager
.short_type
)
138 return new ShortConstant ((short)v
, loc
);
139 if (t
== TypeManager
.ushort_type
)
140 return new UShortConstant ((ushort)v
, loc
);
141 if (t
== TypeManager
.sbyte_type
)
142 return new SByteConstant ((sbyte)v
, loc
);
143 if (t
== TypeManager
.byte_type
)
144 return new ByteConstant ((byte)v
, loc
);
145 if (t
== TypeManager
.char_type
)
146 return new CharConstant ((char)v
, loc
);
147 if (t
== TypeManager
.bool_type
)
148 return new BoolConstant ((bool) v
, loc
);
149 if (t
== TypeManager
.decimal_type
)
150 return new DecimalConstant ((decimal) v
, loc
);
151 if (TypeManager
.IsEnumType (t
)) {
152 Type real_type
= TypeManager
.GetEnumUnderlyingType (t
);
153 return new EnumConstant (CreateConstantFromValue (real_type
, v
, loc
).Resolve (null), t
);
156 if (TypeManager
.IsNullableType (t
))
157 return Nullable
.LiftedNull
.Create (t
, loc
);
159 if (TypeManager
.IsReferenceType (t
))
160 return new NullConstant (t
, loc
);
163 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
164 v
, TypeManager
.CSharpName (t
));
167 public override Expression
CreateExpressionTree (ResolveContext ec
)
169 Arguments args
= new Arguments (2);
170 args
.Add (new Argument (this));
171 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
173 return CreateExpressionFactoryCall (ec
, "Constant", args
);
178 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
179 /// It throws OverflowException
181 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
182 public abstract Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
);
185 /// Attempts to do a compile-time folding of a constant cast.
187 public Constant
TryReduce (ResolveContext ec
, Type target_type
, Location loc
)
190 return TryReduce (ec
, target_type
);
192 catch (OverflowException
) {
193 if (ec
.ConstantCheckState
) {
194 ec
.Report
.Error (221, loc
, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
195 GetValue ().ToString (), TypeManager
.CSharpName (target_type
));
197 Error_ValueCannotBeConverted (ec
, loc
, target_type
, false);
200 return New
.Constantify (target_type
).Resolve (ec
);
204 Constant
TryReduce (ResolveContext ec
, Type target_type
)
206 if (Type
== target_type
)
210 if (TypeManager
.IsEnumType (target_type
)) {
211 c
= TryReduce (ec
, TypeManager
.GetEnumUnderlyingType (target_type
));
215 return new EnumConstant (c
, target_type
).Resolve (ec
);
218 c
= ConvertExplicitly (ec
.ConstantCheckState
, target_type
);
226 /// Need to pass type as the constant can require a boxing
227 /// and in such case no optimization is possible
229 public bool IsDefaultInitializer (Type type
)
232 return IsDefaultValue
;
234 return this is NullLiteral
;
237 public abstract bool IsDefaultValue
{
241 public abstract bool IsNegative
{
246 // When constant is declared as literal
248 public virtual bool IsLiteral
{
249 get { return false; }
252 public virtual bool IsOneInteger
{
253 get { return false; }
257 // Returns true iff 1) the stack type of this is one of Object,
258 // int32, int64 and 2) this == 0 or this == null.
260 public virtual bool IsZeroInteger
{
261 get { return false; }
264 public override void EmitSideEffect (EmitContext ec
)
269 protected override void CloneTo (CloneContext clonectx
, Expression target
)
271 // CloneTo: Nothing, we do not keep any state on this expression
274 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
276 return System
.Linq
.Expressions
.Expression
.Constant (GetTypedValue (), type
);
279 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
281 // A constant cannot be of generic type
284 public new Constant
Resolve (ResolveContext rc
)
286 if (eclass
!= ExprClass
.Unresolved
)
289 // Resolved constant has to be still a constant
290 Constant c
= (Constant
) DoResolve (rc
);
294 if ((c
.eclass
& ExprClass
.Value
) == 0) {
295 c
.Error_UnexpectedKind (rc
, ResolveFlags
.VariableOrValue
, loc
);
300 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c
.GetType ());
306 public abstract class IntegralConstant
: Constant
{
307 protected IntegralConstant (Location loc
) :
312 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
315 ConvertExplicitly (true, target
);
316 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
320 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
321 GetValue ().ToString (), TypeManager
.CSharpName (target
));
325 public abstract Constant
Increment ();
328 public class BoolConstant
: Constant
{
329 public readonly bool Value
;
331 public BoolConstant (bool val
, Location loc
):
337 override public string AsString ()
339 return Value
? "true" : "false";
342 protected override Expression
DoResolve (ResolveContext ec
)
344 type
= TypeManager
.bool_type
;
345 eclass
= ExprClass
.Value
;
349 public override object GetValue ()
351 return (object) Value
;
354 public override void Emit (EmitContext ec
)
357 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
359 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
362 public override bool IsDefaultValue
{
368 public override bool IsNegative
{
374 public override bool IsZeroInteger
{
375 get { return Value == false; }
378 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
385 public class ByteConstant
: IntegralConstant
{
386 public readonly byte Value
;
388 public ByteConstant (byte v
, Location loc
):
394 public override void Emit (EmitContext ec
)
396 IntLiteral
.EmitInt (ec
.ig
, Value
);
399 public override string AsString ()
401 return Value
.ToString ();
404 protected override Expression
DoResolve (ResolveContext ec
)
406 type
= TypeManager
.byte_type
;
407 eclass
= ExprClass
.Value
;
411 public override object GetValue ()
416 public override Constant
Increment ()
418 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
421 public override bool IsDefaultValue
{
427 public override bool IsOneInteger
{
433 public override bool IsNegative
{
439 public override bool IsZeroInteger
{
440 get { return Value == 0; }
443 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
445 if (target_type
== TypeManager
.sbyte_type
) {
446 if (in_checked_context
){
447 if (Value
> SByte
.MaxValue
)
448 throw new OverflowException ();
450 return new SByteConstant ((sbyte) Value
, Location
);
452 if (target_type
== TypeManager
.short_type
)
453 return new ShortConstant ((short) Value
, Location
);
454 if (target_type
== TypeManager
.ushort_type
)
455 return new UShortConstant ((ushort) Value
, Location
);
456 if (target_type
== TypeManager
.int32_type
)
457 return new IntConstant ((int) Value
, Location
);
458 if (target_type
== TypeManager
.uint32_type
)
459 return new UIntConstant ((uint) Value
, Location
);
460 if (target_type
== TypeManager
.int64_type
)
461 return new LongConstant ((long) Value
, Location
);
462 if (target_type
== TypeManager
.uint64_type
)
463 return new ULongConstant ((ulong) Value
, Location
);
464 if (target_type
== TypeManager
.float_type
)
465 return new FloatConstant ((float) Value
, Location
);
466 if (target_type
== TypeManager
.double_type
)
467 return new DoubleConstant ((double) Value
, Location
);
468 if (target_type
== TypeManager
.char_type
)
469 return new CharConstant ((char) Value
, Location
);
470 if (target_type
== TypeManager
.decimal_type
)
471 return new DecimalConstant ((decimal) Value
, Location
);
478 public class CharConstant
: Constant
{
479 public readonly char Value
;
481 public CharConstant (char v
, Location loc
):
487 protected override Expression
DoResolve (ResolveContext rc
)
489 type
= TypeManager
.char_type
;
490 eclass
= ExprClass
.Value
;
494 public override void Emit (EmitContext ec
)
496 IntLiteral
.EmitInt (ec
.ig
, Value
);
499 static string descape (char c
)
525 return c
.ToString ();
528 public override string AsString ()
530 return "\"" + descape (Value
) + "\"";
533 public override object GetValue ()
538 public override bool IsDefaultValue
{
544 public override bool IsNegative
{
550 public override bool IsZeroInteger
{
551 get { return Value == '\0'; }
554 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
556 if (target_type
== TypeManager
.byte_type
) {
557 if (in_checked_context
){
558 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
559 throw new OverflowException ();
561 return new ByteConstant ((byte) Value
, Location
);
563 if (target_type
== TypeManager
.sbyte_type
) {
564 if (in_checked_context
){
565 if (Value
> SByte
.MaxValue
)
566 throw new OverflowException ();
568 return new SByteConstant ((sbyte) Value
, Location
);
570 if (target_type
== TypeManager
.short_type
) {
571 if (in_checked_context
){
572 if (Value
> Int16
.MaxValue
)
573 throw new OverflowException ();
575 return new ShortConstant ((short) Value
, Location
);
577 if (target_type
== TypeManager
.int32_type
)
578 return new IntConstant ((int) Value
, Location
);
579 if (target_type
== TypeManager
.uint32_type
)
580 return new UIntConstant ((uint) Value
, Location
);
581 if (target_type
== TypeManager
.int64_type
)
582 return new LongConstant ((long) Value
, Location
);
583 if (target_type
== TypeManager
.uint64_type
)
584 return new ULongConstant ((ulong) Value
, Location
);
585 if (target_type
== TypeManager
.float_type
)
586 return new FloatConstant ((float) Value
, Location
);
587 if (target_type
== TypeManager
.double_type
)
588 return new DoubleConstant ((double) Value
, Location
);
589 if (target_type
== TypeManager
.decimal_type
)
590 return new DecimalConstant ((decimal) Value
, Location
);
597 public class SByteConstant
: IntegralConstant
{
598 public readonly sbyte Value
;
600 public SByteConstant (sbyte v
, Location loc
):
606 protected override Expression
DoResolve (ResolveContext rc
)
608 type
= TypeManager
.sbyte_type
;
609 eclass
= ExprClass
.Value
;
613 public override void Emit (EmitContext ec
)
615 IntLiteral
.EmitInt (ec
.ig
, Value
);
618 public override string AsString ()
620 return Value
.ToString ();
623 public override object GetValue ()
628 public override Constant
Increment ()
630 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
633 public override bool IsDefaultValue
{
639 public override bool IsNegative
{
645 public override bool IsOneInteger
{
651 public override bool IsZeroInteger
{
652 get { return Value == 0; }
655 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
657 if (target_type
== TypeManager
.byte_type
) {
658 if (in_checked_context
&& Value
< 0)
659 throw new OverflowException ();
660 return new ByteConstant ((byte) Value
, Location
);
662 if (target_type
== TypeManager
.short_type
)
663 return new ShortConstant ((short) Value
, Location
);
664 if (target_type
== TypeManager
.ushort_type
) {
665 if (in_checked_context
&& Value
< 0)
666 throw new OverflowException ();
667 return new UShortConstant ((ushort) Value
, Location
);
668 } if (target_type
== TypeManager
.int32_type
)
669 return new IntConstant ((int) Value
, Location
);
670 if (target_type
== TypeManager
.uint32_type
) {
671 if (in_checked_context
&& Value
< 0)
672 throw new OverflowException ();
673 return new UIntConstant ((uint) Value
, Location
);
674 } if (target_type
== TypeManager
.int64_type
)
675 return new LongConstant ((long) Value
, Location
);
676 if (target_type
== TypeManager
.uint64_type
) {
677 if (in_checked_context
&& Value
< 0)
678 throw new OverflowException ();
679 return new ULongConstant ((ulong) Value
, Location
);
681 if (target_type
== TypeManager
.float_type
)
682 return new FloatConstant ((float) Value
, Location
);
683 if (target_type
== TypeManager
.double_type
)
684 return new DoubleConstant ((double) Value
, Location
);
685 if (target_type
== TypeManager
.char_type
) {
686 if (in_checked_context
&& Value
< 0)
687 throw new OverflowException ();
688 return new CharConstant ((char) Value
, Location
);
690 if (target_type
== TypeManager
.decimal_type
)
691 return new DecimalConstant ((decimal) Value
, Location
);
698 public class ShortConstant
: IntegralConstant
{
699 public readonly short Value
;
701 public ShortConstant (short v
, Location loc
):
707 protected override Expression
DoResolve (ResolveContext rc
)
709 type
= TypeManager
.short_type
;
710 eclass
= ExprClass
.Value
;
714 public override void Emit (EmitContext ec
)
716 IntLiteral
.EmitInt (ec
.ig
, Value
);
719 public override string AsString ()
721 return Value
.ToString ();
724 public override object GetValue ()
729 public override Constant
Increment ()
731 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
734 public override bool IsDefaultValue
{
740 public override bool IsZeroInteger
{
741 get { return Value == 0; }
744 public override bool IsNegative
{
750 public override bool IsOneInteger
{
756 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
758 if (target_type
== TypeManager
.byte_type
) {
759 if (in_checked_context
){
760 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
761 throw new OverflowException ();
763 return new ByteConstant ((byte) Value
, Location
);
765 if (target_type
== TypeManager
.sbyte_type
) {
766 if (in_checked_context
){
767 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
768 throw new OverflowException ();
770 return new SByteConstant ((sbyte) Value
, Location
);
772 if (target_type
== TypeManager
.ushort_type
) {
773 if (in_checked_context
&& Value
< 0)
774 throw new OverflowException ();
776 return new UShortConstant ((ushort) Value
, Location
);
778 if (target_type
== TypeManager
.int32_type
)
779 return new IntConstant ((int) Value
, Location
);
780 if (target_type
== TypeManager
.uint32_type
) {
781 if (in_checked_context
&& Value
< 0)
782 throw new OverflowException ();
783 return new UIntConstant ((uint) Value
, Location
);
785 if (target_type
== TypeManager
.int64_type
)
786 return new LongConstant ((long) Value
, Location
);
787 if (target_type
== TypeManager
.uint64_type
) {
788 if (in_checked_context
&& Value
< 0)
789 throw new OverflowException ();
790 return new ULongConstant ((ulong) Value
, Location
);
792 if (target_type
== TypeManager
.float_type
)
793 return new FloatConstant ((float) Value
, Location
);
794 if (target_type
== TypeManager
.double_type
)
795 return new DoubleConstant ((double) Value
, Location
);
796 if (target_type
== TypeManager
.char_type
) {
797 if (in_checked_context
){
798 if (Value
< Char
.MinValue
)
799 throw new OverflowException ();
801 return new CharConstant ((char) Value
, Location
);
803 if (target_type
== TypeManager
.decimal_type
)
804 return new DecimalConstant ((decimal) Value
, Location
);
811 public class UShortConstant
: IntegralConstant
{
812 public readonly ushort Value
;
814 public UShortConstant (ushort v
, Location loc
):
820 protected override Expression
DoResolve (ResolveContext rc
)
822 type
= TypeManager
.ushort_type
;
823 eclass
= ExprClass
.Value
;
827 public override void Emit (EmitContext ec
)
829 IntLiteral
.EmitInt (ec
.ig
, Value
);
832 public override string AsString ()
834 return Value
.ToString ();
837 public override object GetValue ()
842 public override Constant
Increment ()
844 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
847 public override bool IsDefaultValue
{
853 public override bool IsNegative
{
859 public override bool IsOneInteger
{
865 public override bool IsZeroInteger
{
866 get { return Value == 0; }
869 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
871 if (target_type
== TypeManager
.byte_type
) {
872 if (in_checked_context
){
873 if (Value
> Byte
.MaxValue
)
874 throw new OverflowException ();
876 return new ByteConstant ((byte) Value
, Location
);
878 if (target_type
== TypeManager
.sbyte_type
) {
879 if (in_checked_context
){
880 if (Value
> SByte
.MaxValue
)
881 throw new OverflowException ();
883 return new SByteConstant ((sbyte) Value
, Location
);
885 if (target_type
== TypeManager
.short_type
) {
886 if (in_checked_context
){
887 if (Value
> Int16
.MaxValue
)
888 throw new OverflowException ();
890 return new ShortConstant ((short) Value
, Location
);
892 if (target_type
== TypeManager
.int32_type
)
893 return new IntConstant ((int) Value
, Location
);
894 if (target_type
== TypeManager
.uint32_type
)
895 return new UIntConstant ((uint) Value
, Location
);
896 if (target_type
== TypeManager
.int64_type
)
897 return new LongConstant ((long) Value
, Location
);
898 if (target_type
== TypeManager
.uint64_type
)
899 return new ULongConstant ((ulong) Value
, Location
);
900 if (target_type
== TypeManager
.float_type
)
901 return new FloatConstant ((float) Value
, Location
);
902 if (target_type
== TypeManager
.double_type
)
903 return new DoubleConstant ((double) Value
, Location
);
904 if (target_type
== TypeManager
.char_type
) {
905 if (in_checked_context
){
906 if (Value
> Char
.MaxValue
)
907 throw new OverflowException ();
909 return new CharConstant ((char) Value
, Location
);
911 if (target_type
== TypeManager
.decimal_type
)
912 return new DecimalConstant ((decimal) Value
, Location
);
918 public class IntConstant
: IntegralConstant
{
919 public readonly int Value
;
921 public IntConstant (int v
, Location loc
):
927 protected override Expression
DoResolve (ResolveContext rc
)
929 type
= TypeManager
.int32_type
;
930 eclass
= ExprClass
.Value
;
934 static public void EmitInt (ILGenerator ig
, int i
)
938 ig
.Emit (OpCodes
.Ldc_I4_M1
);
942 ig
.Emit (OpCodes
.Ldc_I4_0
);
946 ig
.Emit (OpCodes
.Ldc_I4_1
);
950 ig
.Emit (OpCodes
.Ldc_I4_2
);
954 ig
.Emit (OpCodes
.Ldc_I4_3
);
958 ig
.Emit (OpCodes
.Ldc_I4_4
);
962 ig
.Emit (OpCodes
.Ldc_I4_5
);
966 ig
.Emit (OpCodes
.Ldc_I4_6
);
970 ig
.Emit (OpCodes
.Ldc_I4_7
);
974 ig
.Emit (OpCodes
.Ldc_I4_8
);
978 if (i
>= -128 && i
<= 127){
979 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
981 ig
.Emit (OpCodes
.Ldc_I4
, i
);
986 public override void Emit (EmitContext ec
)
988 EmitInt (ec
.ig
, Value
);
991 public override string AsString ()
993 return Value
.ToString ();
996 public override object GetValue ()
1001 public override Constant
Increment ()
1003 return new IntConstant (checked(Value
+ 1), loc
);
1006 public override bool IsDefaultValue
{
1012 public override bool IsNegative
{
1018 public override bool IsOneInteger
{
1024 public override bool IsZeroInteger
{
1025 get { return Value == 0; }
1028 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1030 if (target_type
== TypeManager
.byte_type
) {
1031 if (in_checked_context
){
1032 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1033 throw new OverflowException ();
1035 return new ByteConstant ((byte) Value
, Location
);
1037 if (target_type
== TypeManager
.sbyte_type
) {
1038 if (in_checked_context
){
1039 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1040 throw new OverflowException ();
1042 return new SByteConstant ((sbyte) Value
, Location
);
1044 if (target_type
== TypeManager
.short_type
) {
1045 if (in_checked_context
){
1046 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1047 throw new OverflowException ();
1049 return new ShortConstant ((short) Value
, Location
);
1051 if (target_type
== TypeManager
.ushort_type
) {
1052 if (in_checked_context
){
1053 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1054 throw new OverflowException ();
1056 return new UShortConstant ((ushort) Value
, Location
);
1058 if (target_type
== TypeManager
.uint32_type
) {
1059 if (in_checked_context
){
1060 if (Value
< UInt32
.MinValue
)
1061 throw new OverflowException ();
1063 return new UIntConstant ((uint) Value
, Location
);
1065 if (target_type
== TypeManager
.int64_type
)
1066 return new LongConstant ((long) Value
, Location
);
1067 if (target_type
== TypeManager
.uint64_type
) {
1068 if (in_checked_context
&& Value
< 0)
1069 throw new OverflowException ();
1070 return new ULongConstant ((ulong) Value
, Location
);
1072 if (target_type
== TypeManager
.float_type
)
1073 return new FloatConstant ((float) Value
, Location
);
1074 if (target_type
== TypeManager
.double_type
)
1075 return new DoubleConstant ((double) Value
, Location
);
1076 if (target_type
== TypeManager
.char_type
) {
1077 if (in_checked_context
){
1078 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1079 throw new OverflowException ();
1081 return new CharConstant ((char) Value
, Location
);
1083 if (target_type
== TypeManager
.decimal_type
)
1084 return new DecimalConstant ((decimal) Value
, Location
);
1089 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
1091 if (this.type
== type
)
1094 Constant c
= TryImplicitIntConversion (type
);
1096 return c
.Resolve (rc
);
1098 return base.ConvertImplicitly (rc
, type
);
1102 /// Attempts to perform an implicit constant conversion of the IntConstant
1103 /// into a different data type using casts (See Implicit Constant
1104 /// Expression Conversions)
1106 Constant
TryImplicitIntConversion (Type target_type
)
1108 if (target_type
== TypeManager
.sbyte_type
) {
1109 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1110 return new SByteConstant ((sbyte) Value
, loc
);
1112 else if (target_type
== TypeManager
.byte_type
) {
1113 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1114 return new ByteConstant ((byte) Value
, loc
);
1116 else if (target_type
== TypeManager
.short_type
) {
1117 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1118 return new ShortConstant ((short) Value
, loc
);
1120 else if (target_type
== TypeManager
.ushort_type
) {
1121 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1122 return new UShortConstant ((ushort) Value
, loc
);
1124 else if (target_type
== TypeManager
.uint32_type
) {
1126 return new UIntConstant ((uint) Value
, loc
);
1128 else if (target_type
== TypeManager
.uint64_type
) {
1130 // we can optimize this case: a positive int32
1131 // always fits on a uint64. But we need an opcode
1135 return new ULongConstant ((ulong) Value
, loc
);
1137 else if (target_type
== TypeManager
.double_type
)
1138 return new DoubleConstant ((double) Value
, loc
);
1139 else if (target_type
== TypeManager
.float_type
)
1140 return new FloatConstant ((float) Value
, loc
);
1146 public class UIntConstant
: IntegralConstant
{
1147 public readonly uint Value
;
1149 public UIntConstant (uint v
, Location loc
):
1155 protected override Expression
DoResolve (ResolveContext rc
)
1157 type
= TypeManager
.uint32_type
;
1158 eclass
= ExprClass
.Value
;
1162 public override void Emit (EmitContext ec
)
1164 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
1167 public override string AsString ()
1169 return Value
.ToString ();
1172 public override object GetValue ()
1177 public override Constant
Increment ()
1179 return new UIntConstant (checked(Value
+ 1), loc
);
1182 public override bool IsDefaultValue
{
1188 public override bool IsNegative
{
1194 public override bool IsOneInteger
{
1200 public override bool IsZeroInteger
{
1201 get { return Value == 0; }
1204 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1206 if (target_type
== TypeManager
.byte_type
) {
1207 if (in_checked_context
){
1208 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1209 throw new OverflowException ();
1211 return new ByteConstant ((byte) Value
, Location
);
1213 if (target_type
== TypeManager
.sbyte_type
) {
1214 if (in_checked_context
){
1215 if (Value
> SByte
.MaxValue
)
1216 throw new OverflowException ();
1218 return new SByteConstant ((sbyte) Value
, Location
);
1220 if (target_type
== TypeManager
.short_type
) {
1221 if (in_checked_context
){
1222 if (Value
> Int16
.MaxValue
)
1223 throw new OverflowException ();
1225 return new ShortConstant ((short) Value
, Location
);
1227 if (target_type
== TypeManager
.ushort_type
) {
1228 if (in_checked_context
){
1229 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1230 throw new OverflowException ();
1232 return new UShortConstant ((ushort) Value
, Location
);
1234 if (target_type
== TypeManager
.int32_type
) {
1235 if (in_checked_context
){
1236 if (Value
> Int32
.MaxValue
)
1237 throw new OverflowException ();
1239 return new IntConstant ((int) Value
, Location
);
1241 if (target_type
== TypeManager
.int64_type
)
1242 return new LongConstant ((long) Value
, Location
);
1243 if (target_type
== TypeManager
.uint64_type
)
1244 return new ULongConstant ((ulong) Value
, Location
);
1245 if (target_type
== TypeManager
.float_type
)
1246 return new FloatConstant ((float) Value
, Location
);
1247 if (target_type
== TypeManager
.double_type
)
1248 return new DoubleConstant ((double) Value
, Location
);
1249 if (target_type
== TypeManager
.char_type
) {
1250 if (in_checked_context
){
1251 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1252 throw new OverflowException ();
1254 return new CharConstant ((char) Value
, Location
);
1256 if (target_type
== TypeManager
.decimal_type
)
1257 return new DecimalConstant ((decimal) Value
, Location
);
1264 public class LongConstant
: IntegralConstant
{
1265 public readonly long Value
;
1267 public LongConstant (long v
, Location loc
):
1273 protected override Expression
DoResolve (ResolveContext rc
)
1275 type
= TypeManager
.int64_type
;
1276 eclass
= ExprClass
.Value
;
1280 public override void Emit (EmitContext ec
)
1282 EmitLong (ec
.ig
, Value
);
1285 static public void EmitLong (ILGenerator ig
, long l
)
1287 if (l
>= int.MinValue
&& l
<= int.MaxValue
) {
1288 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1289 ig
.Emit (OpCodes
.Conv_I8
);
1293 if (l
>= 0 && l
<= uint.MaxValue
) {
1294 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1295 ig
.Emit (OpCodes
.Conv_U8
);
1299 ig
.Emit (OpCodes
.Ldc_I8
, l
);
1302 public override string AsString ()
1304 return Value
.ToString ();
1307 public override object GetValue ()
1312 public override Constant
Increment ()
1314 return new LongConstant (checked(Value
+ 1), loc
);
1317 public override bool IsDefaultValue
{
1323 public override bool IsNegative
{
1329 public override bool IsOneInteger
{
1335 public override bool IsZeroInteger
{
1336 get { return Value == 0; }
1339 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1341 if (target_type
== TypeManager
.byte_type
) {
1342 if (in_checked_context
){
1343 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1344 throw new OverflowException ();
1346 return new ByteConstant ((byte) Value
, Location
);
1348 if (target_type
== TypeManager
.sbyte_type
) {
1349 if (in_checked_context
){
1350 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1351 throw new OverflowException ();
1353 return new SByteConstant ((sbyte) Value
, Location
);
1355 if (target_type
== TypeManager
.short_type
) {
1356 if (in_checked_context
){
1357 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1358 throw new OverflowException ();
1360 return new ShortConstant ((short) Value
, Location
);
1362 if (target_type
== TypeManager
.ushort_type
) {
1363 if (in_checked_context
){
1364 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1365 throw new OverflowException ();
1367 return new UShortConstant ((ushort) Value
, Location
);
1369 if (target_type
== TypeManager
.int32_type
) {
1370 if (in_checked_context
){
1371 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1372 throw new OverflowException ();
1374 return new IntConstant ((int) Value
, Location
);
1376 if (target_type
== TypeManager
.uint32_type
) {
1377 if (in_checked_context
){
1378 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1379 throw new OverflowException ();
1381 return new UIntConstant ((uint) Value
, Location
);
1383 if (target_type
== TypeManager
.uint64_type
) {
1384 if (in_checked_context
&& Value
< 0)
1385 throw new OverflowException ();
1386 return new ULongConstant ((ulong) 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
){
1394 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1395 throw new OverflowException ();
1397 return new CharConstant ((char) Value
, Location
);
1399 if (target_type
== TypeManager
.decimal_type
)
1400 return new DecimalConstant ((decimal) Value
, Location
);
1405 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
1407 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1408 return new ULongConstant ((ulong) Value
, loc
).Resolve (rc
);
1411 return base.ConvertImplicitly (rc
, type
);
1415 public class ULongConstant
: IntegralConstant
{
1416 public readonly ulong Value
;
1418 public ULongConstant (ulong v
, Location loc
):
1424 protected override Expression
DoResolve (ResolveContext rc
)
1426 type
= TypeManager
.uint64_type
;
1427 eclass
= ExprClass
.Value
;
1431 public override void Emit (EmitContext ec
)
1433 ILGenerator ig
= ec
.ig
;
1435 LongLiteral
.EmitLong (ig
, unchecked ((long) Value
));
1438 public override string AsString ()
1440 return Value
.ToString ();
1443 public override object GetValue ()
1448 public override Constant
Increment ()
1450 return new ULongConstant (checked(Value
+ 1), loc
);
1453 public override bool IsDefaultValue
{
1459 public override bool IsNegative
{
1465 public override bool IsOneInteger
{
1471 public override bool IsZeroInteger
{
1472 get { return Value == 0; }
1475 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1477 if (target_type
== TypeManager
.byte_type
) {
1478 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1479 throw new OverflowException ();
1480 return new ByteConstant ((byte) Value
, Location
);
1482 if (target_type
== TypeManager
.sbyte_type
) {
1483 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1484 throw new OverflowException ();
1485 return new SByteConstant ((sbyte) Value
, Location
);
1487 if (target_type
== TypeManager
.short_type
) {
1488 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1489 throw new OverflowException ();
1490 return new ShortConstant ((short) Value
, Location
);
1492 if (target_type
== TypeManager
.ushort_type
) {
1493 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1494 throw new OverflowException ();
1495 return new UShortConstant ((ushort) Value
, Location
);
1497 if (target_type
== TypeManager
.int32_type
) {
1498 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1499 throw new OverflowException ();
1500 return new IntConstant ((int) Value
, Location
);
1502 if (target_type
== TypeManager
.uint32_type
) {
1503 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1504 throw new OverflowException ();
1505 return new UIntConstant ((uint) Value
, Location
);
1507 if (target_type
== TypeManager
.int64_type
) {
1508 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1509 throw new OverflowException ();
1510 return new LongConstant ((long) Value
, Location
);
1512 if (target_type
== TypeManager
.float_type
)
1513 return new FloatConstant ((float) Value
, Location
);
1514 if (target_type
== TypeManager
.double_type
)
1515 return new DoubleConstant ((double) Value
, Location
);
1516 if (target_type
== TypeManager
.char_type
) {
1517 if (in_checked_context
&& Value
> Char
.MaxValue
)
1518 throw new OverflowException ();
1519 return new CharConstant ((char) Value
, Location
);
1521 if (target_type
== TypeManager
.decimal_type
)
1522 return new DecimalConstant ((decimal) Value
, Location
);
1529 public class FloatConstant
: Constant
{
1532 public FloatConstant (float v
, Location loc
):
1538 protected override Expression
DoResolve (ResolveContext rc
)
1540 type
= TypeManager
.float_type
;
1541 eclass
= ExprClass
.Value
;
1545 public override void Emit (EmitContext ec
)
1547 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
1550 public override string AsString ()
1552 return Value
.ToString ();
1555 public override object GetValue ()
1560 public override bool IsDefaultValue
{
1566 public override bool IsNegative
{
1572 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1574 if (target_type
== TypeManager
.byte_type
) {
1575 if (in_checked_context
){
1576 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1577 throw new OverflowException ();
1579 return new ByteConstant ((byte) Value
, Location
);
1581 if (target_type
== TypeManager
.sbyte_type
) {
1582 if (in_checked_context
){
1583 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1584 throw new OverflowException ();
1586 return new SByteConstant ((sbyte) Value
, Location
);
1588 if (target_type
== TypeManager
.short_type
) {
1589 if (in_checked_context
){
1590 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1591 throw new OverflowException ();
1593 return new ShortConstant ((short) Value
, Location
);
1595 if (target_type
== TypeManager
.ushort_type
) {
1596 if (in_checked_context
){
1597 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1598 throw new OverflowException ();
1600 return new UShortConstant ((ushort) Value
, Location
);
1602 if (target_type
== TypeManager
.int32_type
) {
1603 if (in_checked_context
){
1604 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1605 throw new OverflowException ();
1607 return new IntConstant ((int) Value
, Location
);
1609 if (target_type
== TypeManager
.uint32_type
) {
1610 if (in_checked_context
){
1611 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1612 throw new OverflowException ();
1614 return new UIntConstant ((uint) Value
, Location
);
1616 if (target_type
== TypeManager
.int64_type
) {
1617 if (in_checked_context
){
1618 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1619 throw new OverflowException ();
1621 return new LongConstant ((long) Value
, Location
);
1623 if (target_type
== TypeManager
.uint64_type
) {
1624 if (in_checked_context
){
1625 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1626 throw new OverflowException ();
1628 return new ULongConstant ((ulong) Value
, Location
);
1630 if (target_type
== TypeManager
.double_type
)
1631 return new DoubleConstant ((double) Value
, Location
);
1632 if (target_type
== TypeManager
.char_type
) {
1633 if (in_checked_context
){
1634 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1635 throw new OverflowException ();
1637 return new CharConstant ((char) Value
, Location
);
1639 if (target_type
== TypeManager
.decimal_type
)
1640 return new DecimalConstant ((decimal) Value
, Location
);
1647 public class DoubleConstant
: Constant
{
1648 public double Value
;
1650 public DoubleConstant (double v
, Location loc
):
1656 protected override Expression
DoResolve (ResolveContext rc
)
1658 type
= TypeManager
.double_type
;
1659 eclass
= ExprClass
.Value
;
1663 public override void Emit (EmitContext ec
)
1665 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
1668 public override string AsString ()
1670 return Value
.ToString ();
1673 public override object GetValue ()
1678 public override bool IsDefaultValue
{
1684 public override bool IsNegative
{
1690 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1692 if (target_type
== TypeManager
.byte_type
) {
1693 if (in_checked_context
){
1694 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1695 throw new OverflowException ();
1697 return new ByteConstant ((byte) Value
, Location
);
1699 if (target_type
== TypeManager
.sbyte_type
) {
1700 if (in_checked_context
){
1701 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1702 throw new OverflowException ();
1704 return new SByteConstant ((sbyte) Value
, Location
);
1706 if (target_type
== TypeManager
.short_type
) {
1707 if (in_checked_context
){
1708 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1709 throw new OverflowException ();
1711 return new ShortConstant ((short) Value
, Location
);
1713 if (target_type
== TypeManager
.ushort_type
) {
1714 if (in_checked_context
){
1715 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1716 throw new OverflowException ();
1718 return new UShortConstant ((ushort) Value
, Location
);
1720 if (target_type
== TypeManager
.int32_type
) {
1721 if (in_checked_context
){
1722 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1723 throw new OverflowException ();
1725 return new IntConstant ((int) Value
, Location
);
1727 if (target_type
== TypeManager
.uint32_type
) {
1728 if (in_checked_context
){
1729 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1730 throw new OverflowException ();
1732 return new UIntConstant ((uint) Value
, Location
);
1734 if (target_type
== TypeManager
.int64_type
) {
1735 if (in_checked_context
){
1736 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1737 throw new OverflowException ();
1739 return new LongConstant ((long) Value
, Location
);
1741 if (target_type
== TypeManager
.uint64_type
) {
1742 if (in_checked_context
){
1743 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1744 throw new OverflowException ();
1746 return new ULongConstant ((ulong) Value
, Location
);
1748 if (target_type
== TypeManager
.float_type
)
1749 return new FloatConstant ((float) Value
, Location
);
1750 if (target_type
== TypeManager
.char_type
) {
1751 if (in_checked_context
){
1752 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1753 throw new OverflowException ();
1755 return new CharConstant ((char) Value
, Location
);
1757 if (target_type
== TypeManager
.decimal_type
)
1758 return new DecimalConstant ((decimal) Value
, Location
);
1765 public class DecimalConstant
: Constant
{
1766 public readonly decimal Value
;
1768 public DecimalConstant (decimal d
, Location loc
):
1774 override public string AsString ()
1776 return Value
.ToString () + "M";
1779 protected override Expression
DoResolve (ResolveContext rc
)
1781 type
= TypeManager
.decimal_type
;
1782 eclass
= ExprClass
.Value
;
1786 public override object GetValue ()
1788 return (object) Value
;
1791 public override void Emit (EmitContext ec
)
1793 ILGenerator ig
= ec
.ig
;
1795 int [] words
= decimal.GetBits (Value
);
1796 int power
= (words
[3] >> 16) & 0xff;
1799 if (Value
<= int.MaxValue
&& Value
>= int.MinValue
) {
1800 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1801 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1802 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1804 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1808 IntConstant
.EmitInt (ig
, (int) Value
);
1809 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1813 if (Value
<= long.MaxValue
&& Value
>= long.MinValue
) {
1814 if (TypeManager
.void_decimal_ctor_long_arg
== null) {
1815 TypeManager
.void_decimal_ctor_long_arg
= TypeManager
.GetPredefinedConstructor (
1816 TypeManager
.decimal_type
, loc
, TypeManager
.int64_type
);
1818 if (TypeManager
.void_decimal_ctor_long_arg
== null)
1822 LongConstant
.EmitLong (ig
, (long) Value
);
1823 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_long_arg
);
1828 IntConstant
.EmitInt (ig
, words
[0]);
1829 IntConstant
.EmitInt (ig
, words
[1]);
1830 IntConstant
.EmitInt (ig
, words
[2]);
1833 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1836 IntConstant
.EmitInt (ig
, power
);
1838 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1839 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1840 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1841 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1843 if (TypeManager
.void_decimal_ctor_five_args
== null)
1847 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1850 public override bool IsDefaultValue
{
1856 public override bool IsNegative
{
1862 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1864 if (target_type
== TypeManager
.sbyte_type
)
1865 return new SByteConstant ((sbyte)Value
, loc
);
1866 if (target_type
== TypeManager
.byte_type
)
1867 return new ByteConstant ((byte)Value
, loc
);
1868 if (target_type
== TypeManager
.short_type
)
1869 return new ShortConstant ((short)Value
, loc
);
1870 if (target_type
== TypeManager
.ushort_type
)
1871 return new UShortConstant ((ushort)Value
, loc
);
1872 if (target_type
== TypeManager
.int32_type
)
1873 return new IntConstant ((int)Value
, loc
);
1874 if (target_type
== TypeManager
.uint32_type
)
1875 return new UIntConstant ((uint)Value
, loc
);
1876 if (target_type
== TypeManager
.int64_type
)
1877 return new LongConstant ((long)Value
, loc
);
1878 if (target_type
== TypeManager
.uint64_type
)
1879 return new ULongConstant ((ulong)Value
, loc
);
1880 if (target_type
== TypeManager
.char_type
)
1881 return new CharConstant ((char)Value
, loc
);
1882 if (target_type
== TypeManager
.float_type
)
1883 return new FloatConstant ((float)Value
, loc
);
1884 if (target_type
== TypeManager
.double_type
)
1885 return new DoubleConstant ((double)Value
, loc
);
1892 public class StringConstant
: Constant
{
1893 public readonly string Value
;
1895 public StringConstant (string s
, Location loc
):
1901 // FIXME: Escape the string.
1902 override public string AsString ()
1904 return "\"" + Value
+ "\"";
1907 protected override Expression
DoResolve (ResolveContext rc
)
1909 type
= TypeManager
.string_type
;
1910 eclass
= ExprClass
.Value
;
1914 public override object GetValue ()
1919 public override void Emit (EmitContext ec
)
1921 if (Value
== null) {
1922 ec
.ig
.Emit (OpCodes
.Ldnull
);
1927 // Use string.Empty for both literals and constants even if
1928 // it's not allowed at language level
1930 if (Value
.Length
== 0 && RootContext
.Optimize
&& !TypeManager
.IsEqual (ec
.CurrentType
, TypeManager
.string_type
)) {
1931 if (TypeManager
.string_empty
== null)
1932 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
);
1934 if (TypeManager
.string_empty
!= null) {
1935 ec
.ig
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1940 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1943 public override bool IsDefaultValue
{
1945 return Value
== null;
1949 public override bool IsNegative
{
1955 public override bool IsNull
{
1957 return IsDefaultValue
;
1961 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1968 // Null constant can have its own type, think of `default (Foo)'
1970 public class NullConstant
: Constant
1972 public NullConstant (Type type
, Location loc
)
1975 eclass
= ExprClass
.Value
;
1979 public override string AsString ()
1981 return GetSignatureForError ();
1984 protected override Expression
DoResolve (ResolveContext ec
)
1989 public override void Emit (EmitContext ec
)
1991 ec
.ig
.Emit (OpCodes
.Ldnull
);
1993 // Only to make verifier happy
1994 if (TypeManager
.IsGenericParameter (type
))
1995 ec
.ig
.Emit (OpCodes
.Unbox_Any
, type
);
1998 public override string ExprClassName
{
2000 return GetSignatureForError ();
2004 public override string GetSignatureForError ()
2009 public override Constant
ConvertExplicitly (bool inCheckedContext
, Type targetType
)
2011 if (targetType
.IsPointer
) {
2012 if (IsLiteral
|| this is NullPointer
)
2013 return new EmptyConstantCast (new NullPointer (loc
), targetType
);
2018 // Exlude internal compiler types
2019 if (targetType
== InternalType
.AnonymousMethod
)
2022 if (!IsLiteral
&& !Convert
.ImplicitStandardConversionExists (this, targetType
))
2025 if (TypeManager
.IsReferenceType (targetType
))
2026 return new NullConstant (targetType
, loc
);
2028 if (TypeManager
.IsNullableType (targetType
))
2029 return Nullable
.LiftedNull
.Create (targetType
, loc
);
2034 public override Constant
ConvertImplicitly (ResolveContext rc
, Type targetType
)
2036 return ConvertExplicitly (false, targetType
);
2039 public override object GetValue ()
2044 public override bool IsDefaultValue
{
2045 get { return true; }
2048 public override bool IsNegative
{
2049 get { return false; }
2052 public override bool IsNull
{
2053 get { return true; }
2056 public override bool IsZeroInteger
{
2057 get { return true; }
2060 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
2062 type
= storey
.MutateType (type
);
2067 /// The value is constant, but when emitted has a side effect. This is
2068 /// used by BitwiseAnd to ensure that the second expression is invoked
2069 /// regardless of the value of the left side.
2071 public class SideEffectConstant
: Constant
{
2072 public Constant
value;
2073 Expression side_effect
;
2075 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
2078 while (side_effect
is SideEffectConstant
)
2079 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
2080 this.side_effect
= side_effect
;
2083 public override string AsString ()
2085 return value.AsString ();
2088 protected override Expression
DoResolve (ResolveContext rc
)
2090 value = value.Resolve (rc
);
2093 eclass
= ExprClass
.Value
;
2097 public override object GetValue ()
2099 return value.GetValue ();
2102 public override void Emit (EmitContext ec
)
2104 side_effect
.EmitSideEffect (ec
);
2108 public override void EmitSideEffect (EmitContext ec
)
2110 side_effect
.EmitSideEffect (ec
);
2111 value.EmitSideEffect (ec
);
2114 public override bool IsDefaultValue
{
2115 get { return value.IsDefaultValue; }
2118 public override bool IsNegative
{
2119 get { return value.IsNegative; }
2122 public override bool IsZeroInteger
{
2123 get { return value.IsZeroInteger; }
2126 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
2128 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
2129 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);