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 () + ")";
43 /// This is used to obtain the actual value of the literal
44 /// cast into an object.
46 public abstract object GetValue ();
48 public virtual object GetTypedValue ()
53 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, TypeSpec target
, bool expl
)
55 if (!expl
&& IsLiteral
&&
56 (TypeManager
.IsPrimitiveType (target
) || type
== TypeManager
.decimal_type
) &&
57 (TypeManager
.IsPrimitiveType (type
) || type
== TypeManager
.decimal_type
)) {
58 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
59 AsString (), TypeManager
.CSharpName (target
));
61 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
65 public Constant
ImplicitConversionRequired (ResolveContext ec
, TypeSpec type
, Location loc
)
67 Constant c
= ConvertImplicitly (ec
, type
);
69 Error_ValueCannotBeConverted (ec
, loc
, type
, false);
74 public virtual Constant
ConvertImplicitly (ResolveContext rc
, TypeSpec type
)
76 if (this.type
== type
)
79 if (Convert
.ImplicitNumericConversion (this, type
) == null)
83 object constant_value
= TypeManager
.ChangeType (GetValue (), type
, out fail
);
86 // We should always catch the error before this is ever
87 // reached, by calling Convert.ImplicitStandardConversionExists
89 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
90 TypeManager
.CSharpName (Type
), TypeManager
.CSharpName (type
));
93 return CreateConstant (rc
, type
, constant_value
, loc
);
97 // Returns a constant instance based on Type
99 public static Constant
CreateConstant (ResolveContext rc
, TypeSpec t
, object v
, Location loc
)
101 return CreateConstantFromValue (t
, v
, loc
).Resolve (rc
);
104 public static Constant
CreateConstantFromValue (TypeSpec t
, object v
, Location loc
)
106 if (t
== TypeManager
.int32_type
)
107 return new IntConstant ((int) v
, loc
);
108 if (t
== TypeManager
.string_type
)
109 return new StringConstant ((string) v
, loc
);
110 if (t
== TypeManager
.uint32_type
)
111 return new UIntConstant ((uint) v
, loc
);
112 if (t
== TypeManager
.int64_type
)
113 return new LongConstant ((long) v
, loc
);
114 if (t
== TypeManager
.uint64_type
)
115 return new ULongConstant ((ulong) v
, loc
);
116 if (t
== TypeManager
.float_type
)
117 return new FloatConstant ((float) v
, loc
);
118 if (t
== TypeManager
.double_type
)
119 return new DoubleConstant ((double) v
, loc
);
120 if (t
== TypeManager
.short_type
)
121 return new ShortConstant ((short)v
, loc
);
122 if (t
== TypeManager
.ushort_type
)
123 return new UShortConstant ((ushort)v
, loc
);
124 if (t
== TypeManager
.sbyte_type
)
125 return new SByteConstant ((sbyte)v
, loc
);
126 if (t
== TypeManager
.byte_type
)
127 return new ByteConstant ((byte)v
, loc
);
128 if (t
== TypeManager
.char_type
)
129 return new CharConstant ((char)v
, loc
);
130 if (t
== TypeManager
.bool_type
)
131 return new BoolConstant ((bool) v
, loc
);
132 if (t
== TypeManager
.decimal_type
)
133 return new DecimalConstant ((decimal) v
, loc
);
134 if (TypeManager
.IsEnumType (t
)) {
135 var real_type
= EnumSpec
.GetUnderlyingType (t
);
136 return new EnumConstant (CreateConstantFromValue (real_type
, v
, loc
).Resolve (null), t
);
139 if (TypeManager
.IsNullableType (t
))
140 return Nullable
.LiftedNull
.Create (t
, loc
);
142 if (TypeManager
.IsReferenceType (t
))
143 return new NullConstant (t
, loc
);
146 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
147 v
, TypeManager
.CSharpName (t
));
150 public override Expression
CreateExpressionTree (ResolveContext ec
)
152 Arguments args
= new Arguments (2);
153 args
.Add (new Argument (this));
154 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
156 return CreateExpressionFactoryCall (ec
, "Constant", args
);
161 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
162 /// It throws OverflowException
164 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
165 public abstract Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
);
168 /// Attempts to do a compile-time folding of a constant cast.
170 public Constant
TryReduce (ResolveContext ec
, TypeSpec target_type
, Location loc
)
173 return TryReduce (ec
, target_type
);
175 catch (OverflowException
) {
176 if (ec
.ConstantCheckState
) {
177 ec
.Report
.Error (221, loc
, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
178 GetValue ().ToString (), TypeManager
.CSharpName (target_type
));
180 Error_ValueCannotBeConverted (ec
, loc
, target_type
, false);
183 return New
.Constantify (target_type
).Resolve (ec
);
187 Constant
TryReduce (ResolveContext ec
, TypeSpec target_type
)
189 if (Type
== target_type
)
193 if (TypeManager
.IsEnumType (target_type
)) {
194 c
= TryReduce (ec
, EnumSpec
.GetUnderlyingType (target_type
));
198 return new EnumConstant (c
, target_type
).Resolve (ec
);
201 c
= ConvertExplicitly (ec
.ConstantCheckState
, target_type
);
209 /// Need to pass type as the constant can require a boxing
210 /// and in such case no optimization is possible
212 public bool IsDefaultInitializer (TypeSpec type
)
215 return IsDefaultValue
;
217 return this is NullLiteral
;
220 public abstract bool IsDefaultValue
{
224 public abstract bool IsNegative
{
229 // When constant is declared as literal
231 public virtual bool IsLiteral
{
232 get { return false; }
235 public virtual bool IsOneInteger
{
236 get { return false; }
240 // Returns true iff 1) the stack type of this is one of Object,
241 // int32, int64 and 2) this == 0 or this == null.
243 public virtual bool IsZeroInteger
{
244 get { return false; }
247 public override void EmitSideEffect (EmitContext ec
)
252 protected override void CloneTo (CloneContext clonectx
, Expression target
)
254 // CloneTo: Nothing, we do not keep any state on this expression
257 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
259 return System
.Linq
.Expressions
.Expression
.Constant (GetTypedValue (), type
.GetMetaInfo ());
262 public new Constant
Resolve (ResolveContext rc
)
264 if (eclass
!= ExprClass
.Unresolved
)
267 // Resolved constant has to be still a constant
268 Constant c
= (Constant
) DoResolve (rc
);
272 if ((c
.eclass
& ExprClass
.Value
) == 0) {
273 c
.Error_UnexpectedKind (rc
, ResolveFlags
.VariableOrValue
, loc
);
278 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c
.GetType ());
284 public abstract class IntegralConstant
: Constant
{
285 protected IntegralConstant (Location loc
) :
290 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, TypeSpec target
, bool expl
)
293 ConvertExplicitly (true, target
);
294 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
298 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
299 GetValue ().ToString (), TypeManager
.CSharpName (target
));
303 public abstract Constant
Increment ();
306 public class BoolConstant
: Constant
{
307 public readonly bool Value
;
309 public BoolConstant (bool val
, Location loc
):
315 override public string AsString ()
317 return Value
? "true" : "false";
320 protected override Expression
DoResolve (ResolveContext ec
)
322 type
= TypeManager
.bool_type
;
323 eclass
= ExprClass
.Value
;
327 public override object GetValue ()
329 return (object) Value
;
332 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
334 enc
.Stream
.Write (Value
);
337 public override void Emit (EmitContext ec
)
340 ec
.Emit (OpCodes
.Ldc_I4_1
);
342 ec
.Emit (OpCodes
.Ldc_I4_0
);
345 public override bool IsDefaultValue
{
351 public override bool IsNegative
{
357 public override bool IsZeroInteger
{
358 get { return Value == false; }
361 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
368 public class ByteConstant
: IntegralConstant
{
369 public readonly byte Value
;
371 public ByteConstant (byte v
, Location loc
):
377 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
379 enc
.Stream
.Write (Value
);
382 public override void Emit (EmitContext ec
)
387 public override string AsString ()
389 return Value
.ToString ();
392 protected override Expression
DoResolve (ResolveContext ec
)
394 type
= TypeManager
.byte_type
;
395 eclass
= ExprClass
.Value
;
399 public override object GetValue ()
404 public override Constant
Increment ()
406 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
409 public override bool IsDefaultValue
{
415 public override bool IsOneInteger
{
421 public override bool IsNegative
{
427 public override bool IsZeroInteger
{
428 get { return Value == 0; }
431 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
433 if (target_type
== TypeManager
.sbyte_type
) {
434 if (in_checked_context
){
435 if (Value
> SByte
.MaxValue
)
436 throw new OverflowException ();
438 return new SByteConstant ((sbyte) Value
, Location
);
440 if (target_type
== TypeManager
.short_type
)
441 return new ShortConstant ((short) Value
, Location
);
442 if (target_type
== TypeManager
.ushort_type
)
443 return new UShortConstant ((ushort) Value
, Location
);
444 if (target_type
== TypeManager
.int32_type
)
445 return new IntConstant ((int) Value
, Location
);
446 if (target_type
== TypeManager
.uint32_type
)
447 return new UIntConstant ((uint) Value
, Location
);
448 if (target_type
== TypeManager
.int64_type
)
449 return new LongConstant ((long) Value
, Location
);
450 if (target_type
== TypeManager
.uint64_type
)
451 return new ULongConstant ((ulong) Value
, Location
);
452 if (target_type
== TypeManager
.float_type
)
453 return new FloatConstant ((float) Value
, Location
);
454 if (target_type
== TypeManager
.double_type
)
455 return new DoubleConstant ((double) Value
, Location
);
456 if (target_type
== TypeManager
.char_type
)
457 return new CharConstant ((char) Value
, Location
);
458 if (target_type
== TypeManager
.decimal_type
)
459 return new DecimalConstant ((decimal) Value
, Location
);
466 public class CharConstant
: Constant
{
467 public readonly char Value
;
469 public CharConstant (char v
, Location loc
):
475 protected override Expression
DoResolve (ResolveContext rc
)
477 type
= TypeManager
.char_type
;
478 eclass
= ExprClass
.Value
;
482 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
484 enc
.Stream
.Write ((ushort) Value
);
487 public override void Emit (EmitContext ec
)
492 static string descape (char c
)
518 return c
.ToString ();
521 public override string AsString ()
523 return "\"" + descape (Value
) + "\"";
526 public override object GetValue ()
531 public override bool IsDefaultValue
{
537 public override bool IsNegative
{
543 public override bool IsZeroInteger
{
544 get { return Value == '\0'; }
547 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
549 if (target_type
== TypeManager
.byte_type
) {
550 if (in_checked_context
){
551 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
552 throw new OverflowException ();
554 return new ByteConstant ((byte) Value
, Location
);
556 if (target_type
== TypeManager
.sbyte_type
) {
557 if (in_checked_context
){
558 if (Value
> SByte
.MaxValue
)
559 throw new OverflowException ();
561 return new SByteConstant ((sbyte) Value
, Location
);
563 if (target_type
== TypeManager
.short_type
) {
564 if (in_checked_context
){
565 if (Value
> Int16
.MaxValue
)
566 throw new OverflowException ();
568 return new ShortConstant ((short) Value
, Location
);
570 if (target_type
== TypeManager
.int32_type
)
571 return new IntConstant ((int) Value
, Location
);
572 if (target_type
== TypeManager
.uint32_type
)
573 return new UIntConstant ((uint) Value
, Location
);
574 if (target_type
== TypeManager
.int64_type
)
575 return new LongConstant ((long) Value
, Location
);
576 if (target_type
== TypeManager
.uint64_type
)
577 return new ULongConstant ((ulong) Value
, Location
);
578 if (target_type
== TypeManager
.float_type
)
579 return new FloatConstant ((float) Value
, Location
);
580 if (target_type
== TypeManager
.double_type
)
581 return new DoubleConstant ((double) Value
, Location
);
582 if (target_type
== TypeManager
.decimal_type
)
583 return new DecimalConstant ((decimal) Value
, Location
);
590 public class SByteConstant
: IntegralConstant
{
591 public readonly sbyte Value
;
593 public SByteConstant (sbyte v
, Location loc
):
599 protected override Expression
DoResolve (ResolveContext rc
)
601 type
= TypeManager
.sbyte_type
;
602 eclass
= ExprClass
.Value
;
606 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
608 enc
.Stream
.Write (Value
);
611 public override void Emit (EmitContext ec
)
616 public override string AsString ()
618 return Value
.ToString ();
621 public override object GetValue ()
626 public override Constant
Increment ()
628 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
631 public override bool IsDefaultValue
{
637 public override bool IsNegative
{
643 public override bool IsOneInteger
{
649 public override bool IsZeroInteger
{
650 get { return Value == 0; }
653 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
655 if (target_type
== TypeManager
.byte_type
) {
656 if (in_checked_context
&& Value
< 0)
657 throw new OverflowException ();
658 return new ByteConstant ((byte) Value
, Location
);
660 if (target_type
== TypeManager
.short_type
)
661 return new ShortConstant ((short) Value
, Location
);
662 if (target_type
== TypeManager
.ushort_type
) {
663 if (in_checked_context
&& Value
< 0)
664 throw new OverflowException ();
665 return new UShortConstant ((ushort) Value
, Location
);
666 } if (target_type
== TypeManager
.int32_type
)
667 return new IntConstant ((int) Value
, Location
);
668 if (target_type
== TypeManager
.uint32_type
) {
669 if (in_checked_context
&& Value
< 0)
670 throw new OverflowException ();
671 return new UIntConstant ((uint) Value
, Location
);
672 } if (target_type
== TypeManager
.int64_type
)
673 return new LongConstant ((long) Value
, Location
);
674 if (target_type
== TypeManager
.uint64_type
) {
675 if (in_checked_context
&& Value
< 0)
676 throw new OverflowException ();
677 return new ULongConstant ((ulong) Value
, Location
);
679 if (target_type
== TypeManager
.float_type
)
680 return new FloatConstant ((float) Value
, Location
);
681 if (target_type
== TypeManager
.double_type
)
682 return new DoubleConstant ((double) Value
, Location
);
683 if (target_type
== TypeManager
.char_type
) {
684 if (in_checked_context
&& Value
< 0)
685 throw new OverflowException ();
686 return new CharConstant ((char) Value
, Location
);
688 if (target_type
== TypeManager
.decimal_type
)
689 return new DecimalConstant ((decimal) Value
, Location
);
696 public class ShortConstant
: IntegralConstant
{
697 public readonly short Value
;
699 public ShortConstant (short v
, Location loc
):
705 protected override Expression
DoResolve (ResolveContext rc
)
707 type
= TypeManager
.short_type
;
708 eclass
= ExprClass
.Value
;
712 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
714 enc
.Stream
.Write (Value
);
717 public override void Emit (EmitContext ec
)
722 public override string AsString ()
724 return Value
.ToString ();
727 public override object GetValue ()
732 public override Constant
Increment ()
734 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
737 public override bool IsDefaultValue
{
743 public override bool IsZeroInteger
{
744 get { return Value == 0; }
747 public override bool IsNegative
{
753 public override bool IsOneInteger
{
759 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
761 if (target_type
== TypeManager
.byte_type
) {
762 if (in_checked_context
){
763 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
764 throw new OverflowException ();
766 return new ByteConstant ((byte) Value
, Location
);
768 if (target_type
== TypeManager
.sbyte_type
) {
769 if (in_checked_context
){
770 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
771 throw new OverflowException ();
773 return new SByteConstant ((sbyte) Value
, Location
);
775 if (target_type
== TypeManager
.ushort_type
) {
776 if (in_checked_context
&& Value
< 0)
777 throw new OverflowException ();
779 return new UShortConstant ((ushort) Value
, Location
);
781 if (target_type
== TypeManager
.int32_type
)
782 return new IntConstant ((int) Value
, Location
);
783 if (target_type
== TypeManager
.uint32_type
) {
784 if (in_checked_context
&& Value
< 0)
785 throw new OverflowException ();
786 return new UIntConstant ((uint) Value
, Location
);
788 if (target_type
== TypeManager
.int64_type
)
789 return new LongConstant ((long) Value
, Location
);
790 if (target_type
== TypeManager
.uint64_type
) {
791 if (in_checked_context
&& Value
< 0)
792 throw new OverflowException ();
793 return new ULongConstant ((ulong) Value
, Location
);
795 if (target_type
== TypeManager
.float_type
)
796 return new FloatConstant ((float) Value
, Location
);
797 if (target_type
== TypeManager
.double_type
)
798 return new DoubleConstant ((double) Value
, Location
);
799 if (target_type
== TypeManager
.char_type
) {
800 if (in_checked_context
){
801 if (Value
< Char
.MinValue
)
802 throw new OverflowException ();
804 return new CharConstant ((char) Value
, Location
);
806 if (target_type
== TypeManager
.decimal_type
)
807 return new DecimalConstant ((decimal) Value
, Location
);
814 public class UShortConstant
: IntegralConstant
{
815 public readonly ushort Value
;
817 public UShortConstant (ushort v
, Location loc
):
823 protected override Expression
DoResolve (ResolveContext rc
)
825 type
= TypeManager
.ushort_type
;
826 eclass
= ExprClass
.Value
;
830 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
832 enc
.Stream
.Write (Value
);
835 public override void Emit (EmitContext ec
)
840 public override string AsString ()
842 return Value
.ToString ();
845 public override object GetValue ()
850 public override Constant
Increment ()
852 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
855 public override bool IsDefaultValue
{
861 public override bool IsNegative
{
867 public override bool IsOneInteger
{
873 public override bool IsZeroInteger
{
874 get { return Value == 0; }
877 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
879 if (target_type
== TypeManager
.byte_type
) {
880 if (in_checked_context
){
881 if (Value
> Byte
.MaxValue
)
882 throw new OverflowException ();
884 return new ByteConstant ((byte) Value
, Location
);
886 if (target_type
== TypeManager
.sbyte_type
) {
887 if (in_checked_context
){
888 if (Value
> SByte
.MaxValue
)
889 throw new OverflowException ();
891 return new SByteConstant ((sbyte) Value
, Location
);
893 if (target_type
== TypeManager
.short_type
) {
894 if (in_checked_context
){
895 if (Value
> Int16
.MaxValue
)
896 throw new OverflowException ();
898 return new ShortConstant ((short) Value
, Location
);
900 if (target_type
== TypeManager
.int32_type
)
901 return new IntConstant ((int) Value
, Location
);
902 if (target_type
== TypeManager
.uint32_type
)
903 return new UIntConstant ((uint) Value
, Location
);
904 if (target_type
== TypeManager
.int64_type
)
905 return new LongConstant ((long) Value
, Location
);
906 if (target_type
== TypeManager
.uint64_type
)
907 return new ULongConstant ((ulong) Value
, Location
);
908 if (target_type
== TypeManager
.float_type
)
909 return new FloatConstant ((float) Value
, Location
);
910 if (target_type
== TypeManager
.double_type
)
911 return new DoubleConstant ((double) Value
, Location
);
912 if (target_type
== TypeManager
.char_type
) {
913 if (in_checked_context
){
914 if (Value
> Char
.MaxValue
)
915 throw new OverflowException ();
917 return new CharConstant ((char) Value
, Location
);
919 if (target_type
== TypeManager
.decimal_type
)
920 return new DecimalConstant ((decimal) Value
, Location
);
926 public class IntConstant
: IntegralConstant
{
927 public readonly int Value
;
929 public IntConstant (int v
, Location loc
):
935 protected override Expression
DoResolve (ResolveContext rc
)
937 type
= TypeManager
.int32_type
;
938 eclass
= ExprClass
.Value
;
942 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
944 enc
.Stream
.Write (Value
);
947 public override void Emit (EmitContext ec
)
952 public override string AsString ()
954 return Value
.ToString ();
957 public override object GetValue ()
962 public override Constant
Increment ()
964 return new IntConstant (checked(Value
+ 1), loc
);
967 public override bool IsDefaultValue
{
973 public override bool IsNegative
{
979 public override bool IsOneInteger
{
985 public override bool IsZeroInteger
{
986 get { return Value == 0; }
989 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
991 if (target_type
== TypeManager
.byte_type
) {
992 if (in_checked_context
){
993 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
994 throw new OverflowException ();
996 return new ByteConstant ((byte) Value
, Location
);
998 if (target_type
== TypeManager
.sbyte_type
) {
999 if (in_checked_context
){
1000 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1001 throw new OverflowException ();
1003 return new SByteConstant ((sbyte) Value
, Location
);
1005 if (target_type
== TypeManager
.short_type
) {
1006 if (in_checked_context
){
1007 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1008 throw new OverflowException ();
1010 return new ShortConstant ((short) Value
, Location
);
1012 if (target_type
== TypeManager
.ushort_type
) {
1013 if (in_checked_context
){
1014 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1015 throw new OverflowException ();
1017 return new UShortConstant ((ushort) Value
, Location
);
1019 if (target_type
== TypeManager
.uint32_type
) {
1020 if (in_checked_context
){
1021 if (Value
< UInt32
.MinValue
)
1022 throw new OverflowException ();
1024 return new UIntConstant ((uint) Value
, Location
);
1026 if (target_type
== TypeManager
.int64_type
)
1027 return new LongConstant ((long) Value
, Location
);
1028 if (target_type
== TypeManager
.uint64_type
) {
1029 if (in_checked_context
&& Value
< 0)
1030 throw new OverflowException ();
1031 return new ULongConstant ((ulong) Value
, Location
);
1033 if (target_type
== TypeManager
.float_type
)
1034 return new FloatConstant ((float) Value
, Location
);
1035 if (target_type
== TypeManager
.double_type
)
1036 return new DoubleConstant ((double) Value
, Location
);
1037 if (target_type
== TypeManager
.char_type
) {
1038 if (in_checked_context
){
1039 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1040 throw new OverflowException ();
1042 return new CharConstant ((char) Value
, Location
);
1044 if (target_type
== TypeManager
.decimal_type
)
1045 return new DecimalConstant ((decimal) Value
, Location
);
1050 public override Constant
ConvertImplicitly (ResolveContext rc
, TypeSpec type
)
1052 if (this.type
== type
)
1055 Constant c
= TryImplicitIntConversion (type
);
1057 return c
.Resolve (rc
);
1059 return base.ConvertImplicitly (rc
, type
);
1063 /// Attempts to perform an implicit constant conversion of the IntConstant
1064 /// into a different data type using casts (See Implicit Constant
1065 /// Expression Conversions)
1067 Constant
TryImplicitIntConversion (TypeSpec target_type
)
1069 if (target_type
== TypeManager
.sbyte_type
) {
1070 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1071 return new SByteConstant ((sbyte) Value
, loc
);
1073 else if (target_type
== TypeManager
.byte_type
) {
1074 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1075 return new ByteConstant ((byte) Value
, loc
);
1077 else if (target_type
== TypeManager
.short_type
) {
1078 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1079 return new ShortConstant ((short) Value
, loc
);
1081 else if (target_type
== TypeManager
.ushort_type
) {
1082 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1083 return new UShortConstant ((ushort) Value
, loc
);
1085 else if (target_type
== TypeManager
.uint32_type
) {
1087 return new UIntConstant ((uint) Value
, loc
);
1089 else if (target_type
== TypeManager
.uint64_type
) {
1091 // we can optimize this case: a positive int32
1092 // always fits on a uint64. But we need an opcode
1096 return new ULongConstant ((ulong) Value
, loc
);
1098 else if (target_type
== TypeManager
.double_type
)
1099 return new DoubleConstant ((double) Value
, loc
);
1100 else if (target_type
== TypeManager
.float_type
)
1101 return new FloatConstant ((float) Value
, loc
);
1107 public class UIntConstant
: IntegralConstant
{
1108 public readonly uint Value
;
1110 public UIntConstant (uint v
, Location loc
):
1116 protected override Expression
DoResolve (ResolveContext rc
)
1118 type
= TypeManager
.uint32_type
;
1119 eclass
= ExprClass
.Value
;
1123 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1125 enc
.Stream
.Write (Value
);
1128 public override void Emit (EmitContext ec
)
1130 ec
.EmitInt (unchecked ((int) Value
));
1133 public override string AsString ()
1135 return Value
.ToString ();
1138 public override object GetValue ()
1143 public override Constant
Increment ()
1145 return new UIntConstant (checked(Value
+ 1), loc
);
1148 public override bool IsDefaultValue
{
1154 public override bool IsNegative
{
1160 public override bool IsOneInteger
{
1166 public override bool IsZeroInteger
{
1167 get { return Value == 0; }
1170 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1172 if (target_type
== TypeManager
.byte_type
) {
1173 if (in_checked_context
){
1174 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1175 throw new OverflowException ();
1177 return new ByteConstant ((byte) Value
, Location
);
1179 if (target_type
== TypeManager
.sbyte_type
) {
1180 if (in_checked_context
){
1181 if (Value
> SByte
.MaxValue
)
1182 throw new OverflowException ();
1184 return new SByteConstant ((sbyte) Value
, Location
);
1186 if (target_type
== TypeManager
.short_type
) {
1187 if (in_checked_context
){
1188 if (Value
> Int16
.MaxValue
)
1189 throw new OverflowException ();
1191 return new ShortConstant ((short) Value
, Location
);
1193 if (target_type
== TypeManager
.ushort_type
) {
1194 if (in_checked_context
){
1195 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1196 throw new OverflowException ();
1198 return new UShortConstant ((ushort) Value
, Location
);
1200 if (target_type
== TypeManager
.int32_type
) {
1201 if (in_checked_context
){
1202 if (Value
> Int32
.MaxValue
)
1203 throw new OverflowException ();
1205 return new IntConstant ((int) Value
, Location
);
1207 if (target_type
== TypeManager
.int64_type
)
1208 return new LongConstant ((long) Value
, Location
);
1209 if (target_type
== TypeManager
.uint64_type
)
1210 return new ULongConstant ((ulong) Value
, Location
);
1211 if (target_type
== TypeManager
.float_type
)
1212 return new FloatConstant ((float) Value
, Location
);
1213 if (target_type
== TypeManager
.double_type
)
1214 return new DoubleConstant ((double) Value
, Location
);
1215 if (target_type
== TypeManager
.char_type
) {
1216 if (in_checked_context
){
1217 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1218 throw new OverflowException ();
1220 return new CharConstant ((char) Value
, Location
);
1222 if (target_type
== TypeManager
.decimal_type
)
1223 return new DecimalConstant ((decimal) Value
, Location
);
1230 public class LongConstant
: IntegralConstant
{
1231 public readonly long Value
;
1233 public LongConstant (long v
, Location loc
):
1239 protected override Expression
DoResolve (ResolveContext rc
)
1241 type
= TypeManager
.int64_type
;
1242 eclass
= ExprClass
.Value
;
1246 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1248 enc
.Stream
.Write (Value
);
1251 public override void Emit (EmitContext ec
)
1253 ec
.EmitLong (Value
);
1256 public override string AsString ()
1258 return Value
.ToString ();
1261 public override object GetValue ()
1266 public override Constant
Increment ()
1268 return new LongConstant (checked(Value
+ 1), loc
);
1271 public override bool IsDefaultValue
{
1277 public override bool IsNegative
{
1283 public override bool IsOneInteger
{
1289 public override bool IsZeroInteger
{
1290 get { return Value == 0; }
1293 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1295 if (target_type
== TypeManager
.byte_type
) {
1296 if (in_checked_context
){
1297 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1298 throw new OverflowException ();
1300 return new ByteConstant ((byte) Value
, Location
);
1302 if (target_type
== TypeManager
.sbyte_type
) {
1303 if (in_checked_context
){
1304 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1305 throw new OverflowException ();
1307 return new SByteConstant ((sbyte) Value
, Location
);
1309 if (target_type
== TypeManager
.short_type
) {
1310 if (in_checked_context
){
1311 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1312 throw new OverflowException ();
1314 return new ShortConstant ((short) Value
, Location
);
1316 if (target_type
== TypeManager
.ushort_type
) {
1317 if (in_checked_context
){
1318 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1319 throw new OverflowException ();
1321 return new UShortConstant ((ushort) Value
, Location
);
1323 if (target_type
== TypeManager
.int32_type
) {
1324 if (in_checked_context
){
1325 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1326 throw new OverflowException ();
1328 return new IntConstant ((int) Value
, Location
);
1330 if (target_type
== TypeManager
.uint32_type
) {
1331 if (in_checked_context
){
1332 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1333 throw new OverflowException ();
1335 return new UIntConstant ((uint) Value
, Location
);
1337 if (target_type
== TypeManager
.uint64_type
) {
1338 if (in_checked_context
&& Value
< 0)
1339 throw new OverflowException ();
1340 return new ULongConstant ((ulong) Value
, Location
);
1342 if (target_type
== TypeManager
.float_type
)
1343 return new FloatConstant ((float) Value
, Location
);
1344 if (target_type
== TypeManager
.double_type
)
1345 return new DoubleConstant ((double) Value
, Location
);
1346 if (target_type
== TypeManager
.char_type
) {
1347 if (in_checked_context
){
1348 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1349 throw new OverflowException ();
1351 return new CharConstant ((char) Value
, Location
);
1353 if (target_type
== TypeManager
.decimal_type
)
1354 return new DecimalConstant ((decimal) Value
, Location
);
1359 public override Constant
ConvertImplicitly (ResolveContext rc
, TypeSpec type
)
1361 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1362 return new ULongConstant ((ulong) Value
, loc
).Resolve (rc
);
1365 return base.ConvertImplicitly (rc
, type
);
1369 public class ULongConstant
: IntegralConstant
{
1370 public readonly ulong Value
;
1372 public ULongConstant (ulong v
, Location loc
):
1378 protected override Expression
DoResolve (ResolveContext rc
)
1380 type
= TypeManager
.uint64_type
;
1381 eclass
= ExprClass
.Value
;
1385 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1387 enc
.Stream
.Write (Value
);
1390 public override void Emit (EmitContext ec
)
1392 ec
.EmitLong (unchecked ((long) Value
));
1395 public override string AsString ()
1397 return Value
.ToString ();
1400 public override object GetValue ()
1405 public override Constant
Increment ()
1407 return new ULongConstant (checked(Value
+ 1), loc
);
1410 public override bool IsDefaultValue
{
1416 public override bool IsNegative
{
1422 public override bool IsOneInteger
{
1428 public override bool IsZeroInteger
{
1429 get { return Value == 0; }
1432 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1434 if (target_type
== TypeManager
.byte_type
) {
1435 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1436 throw new OverflowException ();
1437 return new ByteConstant ((byte) Value
, Location
);
1439 if (target_type
== TypeManager
.sbyte_type
) {
1440 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1441 throw new OverflowException ();
1442 return new SByteConstant ((sbyte) Value
, Location
);
1444 if (target_type
== TypeManager
.short_type
) {
1445 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1446 throw new OverflowException ();
1447 return new ShortConstant ((short) Value
, Location
);
1449 if (target_type
== TypeManager
.ushort_type
) {
1450 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1451 throw new OverflowException ();
1452 return new UShortConstant ((ushort) Value
, Location
);
1454 if (target_type
== TypeManager
.int32_type
) {
1455 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1456 throw new OverflowException ();
1457 return new IntConstant ((int) Value
, Location
);
1459 if (target_type
== TypeManager
.uint32_type
) {
1460 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1461 throw new OverflowException ();
1462 return new UIntConstant ((uint) Value
, Location
);
1464 if (target_type
== TypeManager
.int64_type
) {
1465 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1466 throw new OverflowException ();
1467 return new LongConstant ((long) Value
, Location
);
1469 if (target_type
== TypeManager
.float_type
)
1470 return new FloatConstant ((float) Value
, Location
);
1471 if (target_type
== TypeManager
.double_type
)
1472 return new DoubleConstant ((double) Value
, Location
);
1473 if (target_type
== TypeManager
.char_type
) {
1474 if (in_checked_context
&& Value
> Char
.MaxValue
)
1475 throw new OverflowException ();
1476 return new CharConstant ((char) Value
, Location
);
1478 if (target_type
== TypeManager
.decimal_type
)
1479 return new DecimalConstant ((decimal) Value
, Location
);
1486 public class FloatConstant
: Constant
{
1489 public FloatConstant (float v
, Location loc
):
1495 protected override Expression
DoResolve (ResolveContext rc
)
1497 type
= TypeManager
.float_type
;
1498 eclass
= ExprClass
.Value
;
1502 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1504 enc
.Stream
.Write (Value
);
1507 public override void Emit (EmitContext ec
)
1509 ec
.Emit (OpCodes
.Ldc_R4
, Value
);
1512 public override string AsString ()
1514 return Value
.ToString ();
1517 public override object GetValue ()
1522 public override bool IsDefaultValue
{
1528 public override bool IsNegative
{
1534 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1536 if (target_type
== TypeManager
.byte_type
) {
1537 if (in_checked_context
){
1538 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1539 throw new OverflowException ();
1541 return new ByteConstant ((byte) Value
, Location
);
1543 if (target_type
== TypeManager
.sbyte_type
) {
1544 if (in_checked_context
){
1545 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1546 throw new OverflowException ();
1548 return new SByteConstant ((sbyte) Value
, Location
);
1550 if (target_type
== TypeManager
.short_type
) {
1551 if (in_checked_context
){
1552 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1553 throw new OverflowException ();
1555 return new ShortConstant ((short) Value
, Location
);
1557 if (target_type
== TypeManager
.ushort_type
) {
1558 if (in_checked_context
){
1559 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1560 throw new OverflowException ();
1562 return new UShortConstant ((ushort) Value
, Location
);
1564 if (target_type
== TypeManager
.int32_type
) {
1565 if (in_checked_context
){
1566 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1567 throw new OverflowException ();
1569 return new IntConstant ((int) Value
, Location
);
1571 if (target_type
== TypeManager
.uint32_type
) {
1572 if (in_checked_context
){
1573 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1574 throw new OverflowException ();
1576 return new UIntConstant ((uint) Value
, Location
);
1578 if (target_type
== TypeManager
.int64_type
) {
1579 if (in_checked_context
){
1580 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1581 throw new OverflowException ();
1583 return new LongConstant ((long) Value
, Location
);
1585 if (target_type
== TypeManager
.uint64_type
) {
1586 if (in_checked_context
){
1587 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1588 throw new OverflowException ();
1590 return new ULongConstant ((ulong) Value
, Location
);
1592 if (target_type
== TypeManager
.double_type
)
1593 return new DoubleConstant ((double) Value
, Location
);
1594 if (target_type
== TypeManager
.char_type
) {
1595 if (in_checked_context
){
1596 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1597 throw new OverflowException ();
1599 return new CharConstant ((char) Value
, Location
);
1601 if (target_type
== TypeManager
.decimal_type
)
1602 return new DecimalConstant ((decimal) Value
, Location
);
1609 public class DoubleConstant
: Constant
{
1610 public double Value
;
1612 public DoubleConstant (double v
, Location loc
):
1618 protected override Expression
DoResolve (ResolveContext rc
)
1620 type
= TypeManager
.double_type
;
1621 eclass
= ExprClass
.Value
;
1625 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1627 enc
.Stream
.Write (Value
);
1630 public override void Emit (EmitContext ec
)
1632 ec
.Emit (OpCodes
.Ldc_R8
, Value
);
1635 public override string AsString ()
1637 return Value
.ToString ();
1640 public override object GetValue ()
1645 public override bool IsDefaultValue
{
1651 public override bool IsNegative
{
1657 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1659 if (target_type
== TypeManager
.byte_type
) {
1660 if (in_checked_context
){
1661 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1662 throw new OverflowException ();
1664 return new ByteConstant ((byte) Value
, Location
);
1666 if (target_type
== TypeManager
.sbyte_type
) {
1667 if (in_checked_context
){
1668 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1669 throw new OverflowException ();
1671 return new SByteConstant ((sbyte) Value
, Location
);
1673 if (target_type
== TypeManager
.short_type
) {
1674 if (in_checked_context
){
1675 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1676 throw new OverflowException ();
1678 return new ShortConstant ((short) Value
, Location
);
1680 if (target_type
== TypeManager
.ushort_type
) {
1681 if (in_checked_context
){
1682 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1683 throw new OverflowException ();
1685 return new UShortConstant ((ushort) Value
, Location
);
1687 if (target_type
== TypeManager
.int32_type
) {
1688 if (in_checked_context
){
1689 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1690 throw new OverflowException ();
1692 return new IntConstant ((int) Value
, Location
);
1694 if (target_type
== TypeManager
.uint32_type
) {
1695 if (in_checked_context
){
1696 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1697 throw new OverflowException ();
1699 return new UIntConstant ((uint) Value
, Location
);
1701 if (target_type
== TypeManager
.int64_type
) {
1702 if (in_checked_context
){
1703 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1704 throw new OverflowException ();
1706 return new LongConstant ((long) Value
, Location
);
1708 if (target_type
== TypeManager
.uint64_type
) {
1709 if (in_checked_context
){
1710 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1711 throw new OverflowException ();
1713 return new ULongConstant ((ulong) Value
, Location
);
1715 if (target_type
== TypeManager
.float_type
)
1716 return new FloatConstant ((float) Value
, Location
);
1717 if (target_type
== TypeManager
.char_type
) {
1718 if (in_checked_context
){
1719 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1720 throw new OverflowException ();
1722 return new CharConstant ((char) Value
, Location
);
1724 if (target_type
== TypeManager
.decimal_type
)
1725 return new DecimalConstant ((decimal) Value
, Location
);
1732 public class DecimalConstant
: Constant
{
1733 public readonly decimal Value
;
1735 public DecimalConstant (decimal d
, Location loc
):
1741 override public string AsString ()
1743 return Value
.ToString () + "M";
1746 protected override Expression
DoResolve (ResolveContext rc
)
1748 type
= TypeManager
.decimal_type
;
1749 eclass
= ExprClass
.Value
;
1753 public override object GetValue ()
1755 return (object) Value
;
1758 public override void Emit (EmitContext ec
)
1760 int [] words
= decimal.GetBits (Value
);
1761 int power
= (words
[3] >> 16) & 0xff;
1764 if (Value
<= int.MaxValue
&& Value
>= int.MinValue
) {
1765 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1766 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1767 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1769 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1773 ec
.EmitInt ((int) Value
);
1774 ec
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1778 if (Value
<= long.MaxValue
&& Value
>= long.MinValue
) {
1779 if (TypeManager
.void_decimal_ctor_long_arg
== null) {
1780 TypeManager
.void_decimal_ctor_long_arg
= TypeManager
.GetPredefinedConstructor (
1781 TypeManager
.decimal_type
, loc
, TypeManager
.int64_type
);
1783 if (TypeManager
.void_decimal_ctor_long_arg
== null)
1787 ec
.EmitLong ((long) Value
);
1788 ec
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_long_arg
);
1793 ec
.EmitInt (words
[0]);
1794 ec
.EmitInt (words
[1]);
1795 ec
.EmitInt (words
[2]);
1798 ec
.EmitInt (words
[3] >> 31);
1803 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1804 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1805 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1806 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1808 if (TypeManager
.void_decimal_ctor_five_args
== null)
1812 ec
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1815 public override bool IsDefaultValue
{
1821 public override bool IsNegative
{
1827 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1829 if (target_type
== TypeManager
.sbyte_type
)
1830 return new SByteConstant ((sbyte)Value
, loc
);
1831 if (target_type
== TypeManager
.byte_type
)
1832 return new ByteConstant ((byte)Value
, loc
);
1833 if (target_type
== TypeManager
.short_type
)
1834 return new ShortConstant ((short)Value
, loc
);
1835 if (target_type
== TypeManager
.ushort_type
)
1836 return new UShortConstant ((ushort)Value
, loc
);
1837 if (target_type
== TypeManager
.int32_type
)
1838 return new IntConstant ((int)Value
, loc
);
1839 if (target_type
== TypeManager
.uint32_type
)
1840 return new UIntConstant ((uint)Value
, loc
);
1841 if (target_type
== TypeManager
.int64_type
)
1842 return new LongConstant ((long)Value
, loc
);
1843 if (target_type
== TypeManager
.uint64_type
)
1844 return new ULongConstant ((ulong)Value
, loc
);
1845 if (target_type
== TypeManager
.char_type
)
1846 return new CharConstant ((char)Value
, loc
);
1847 if (target_type
== TypeManager
.float_type
)
1848 return new FloatConstant ((float)Value
, loc
);
1849 if (target_type
== TypeManager
.double_type
)
1850 return new DoubleConstant ((double)Value
, loc
);
1857 public class StringConstant
: Constant
{
1858 public readonly string Value
;
1860 public StringConstant (string s
, Location loc
):
1866 // FIXME: Escape the string.
1867 override public string AsString ()
1869 return "\"" + Value
+ "\"";
1872 protected override Expression
DoResolve (ResolveContext rc
)
1874 type
= TypeManager
.string_type
;
1875 eclass
= ExprClass
.Value
;
1879 public override object GetValue ()
1884 public override void Emit (EmitContext ec
)
1886 if (Value
== null) {
1887 ec
.Emit (OpCodes
.Ldnull
);
1892 // Use string.Empty for both literals and constants even if
1893 // it's not allowed at language level
1895 if (Value
.Length
== 0 && RootContext
.Optimize
&& !TypeManager
.IsEqual (ec
.CurrentType
, TypeManager
.string_type
)) {
1896 if (TypeManager
.string_empty
== null)
1897 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
, TypeManager
.string_type
);
1899 if (TypeManager
.string_empty
!= null) {
1900 ec
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1905 ec
.Emit (OpCodes
.Ldstr
, Value
);
1908 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1911 if (type
!= targetType
)
1917 public override bool IsDefaultValue
{
1919 return Value
== null;
1923 public override bool IsNegative
{
1929 public override bool IsNull
{
1931 return IsDefaultValue
;
1935 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
1942 // Null constant can have its own type, think of `default (Foo)'
1944 public class NullConstant
: Constant
1946 public NullConstant (TypeSpec type
, Location loc
)
1949 eclass
= ExprClass
.Value
;
1953 public override string AsString ()
1955 return GetSignatureForError ();
1958 public override Expression
CreateExpressionTree (ResolveContext ec
)
1960 if (type
== InternalType
.Null
|| type
== TypeManager
.object_type
) {
1961 // Optimized version, also avoids referencing literal internal type
1962 Arguments args
= new Arguments (1);
1963 args
.Add (new Argument (this));
1964 return CreateExpressionFactoryCall (ec
, "Constant", args
);
1967 return base.CreateExpressionTree (ec
);
1970 protected override Expression
DoResolve (ResolveContext ec
)
1975 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, TypeSpec targetType
)
1977 // Type it as string cast
1978 if (targetType
== TypeManager
.object_type
|| targetType
== TypeManager
.null_type
)
1979 enc
.Encode (TypeManager
.string_type
);
1981 var ac
= targetType
as ArrayContainer
;
1984 base.EncodeAttributeValue (rc
, enc
, targetType
);
1986 enc
.Stream
.Write (uint.MaxValue
);
1988 enc
.Stream
.Write (byte.MaxValue
);
1992 public override void Emit (EmitContext ec
)
1994 ec
.Emit (OpCodes
.Ldnull
);
1996 // Only to make verifier happy
1997 if (TypeManager
.IsGenericParameter (type
))
1998 ec
.Emit (OpCodes
.Unbox_Any
, type
);
2001 public override string ExprClassName
{
2003 return GetSignatureForError ();
2007 public override string GetSignatureForError ()
2012 public override Constant
ConvertExplicitly (bool inCheckedContext
, TypeSpec targetType
)
2014 if (targetType
.IsPointer
) {
2015 if (IsLiteral
|| this is NullPointer
)
2016 return new EmptyConstantCast (new NullPointer (loc
), targetType
);
2021 // Exlude internal compiler types
2022 if (targetType
== InternalType
.AnonymousMethod
)
2025 if (!IsLiteral
&& !Convert
.ImplicitStandardConversionExists (this, targetType
))
2028 if (TypeManager
.IsReferenceType (targetType
))
2029 return new NullConstant (targetType
, loc
);
2031 if (TypeManager
.IsNullableType (targetType
))
2032 return Nullable
.LiftedNull
.Create (targetType
, loc
);
2037 public override Constant
ConvertImplicitly (ResolveContext rc
, TypeSpec targetType
)
2039 return ConvertExplicitly (false, targetType
);
2042 public override object GetValue ()
2047 public override bool IsDefaultValue
{
2048 get { return true; }
2051 public override bool IsNegative
{
2052 get { return false; }
2055 public override bool IsNull
{
2056 get { return true; }
2059 public override bool IsZeroInteger
{
2060 get { return true; }
2065 /// The value is constant, but when emitted has a side effect. This is
2066 /// used by BitwiseAnd to ensure that the second expression is invoked
2067 /// regardless of the value of the left side.
2069 public class SideEffectConstant
: Constant
{
2070 public Constant
value;
2071 Expression side_effect
;
2073 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
2076 while (side_effect
is SideEffectConstant
)
2077 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
2078 this.side_effect
= side_effect
;
2081 public override string AsString ()
2083 return value.AsString ();
2086 protected override Expression
DoResolve (ResolveContext rc
)
2088 value = value.Resolve (rc
);
2091 eclass
= ExprClass
.Value
;
2095 public override object GetValue ()
2097 return value.GetValue ();
2100 public override void Emit (EmitContext ec
)
2102 side_effect
.EmitSideEffect (ec
);
2106 public override void EmitSideEffect (EmitContext ec
)
2108 side_effect
.EmitSideEffect (ec
);
2109 value.EmitSideEffect (ec
);
2112 public override bool IsDefaultValue
{
2113 get { return value.IsDefaultValue; }
2116 public override bool IsNegative
{
2117 get { return value.IsNegative; }
2120 public override bool IsZeroInteger
{
2121 get { return value.IsZeroInteger; }
2124 public override Constant
ConvertExplicitly (bool in_checked_context
, TypeSpec target_type
)
2126 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
2127 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);