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
, Type 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
, Type type
, Location loc
)
67 Constant c
= ConvertImplicitly (ec
, type
);
69 Error_ValueCannotBeConverted (ec
, loc
, type
, false);
74 public virtual Constant
ConvertImplicitly (ResolveContext rc
, Type 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
, Type t
, object v
, Location loc
)
101 return CreateConstantFromValue (t
, v
, loc
).Resolve (rc
);
104 public static Constant
CreateConstantFromValue (Type 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 Type real_type
= TypeManager
.GetEnumUnderlyingType (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
, Type target_type
);
168 /// Attempts to do a compile-time folding of a constant cast.
170 public Constant
TryReduce (ResolveContext ec
, Type 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
, Type target_type
)
189 if (Type
== target_type
)
193 if (TypeManager
.IsEnumType (target_type
)) {
194 c
= TryReduce (ec
, TypeManager
.GetEnumUnderlyingType (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 (Type 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
);
262 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
264 // A constant cannot be of generic type
267 public new Constant
Resolve (ResolveContext rc
)
269 if (eclass
!= ExprClass
.Unresolved
)
272 // Resolved constant has to be still a constant
273 Constant c
= (Constant
) DoResolve (rc
);
277 if ((c
.eclass
& ExprClass
.Value
) == 0) {
278 c
.Error_UnexpectedKind (rc
, ResolveFlags
.VariableOrValue
, loc
);
283 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c
.GetType ());
289 public abstract class IntegralConstant
: Constant
{
290 protected IntegralConstant (Location loc
) :
295 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
298 ConvertExplicitly (true, target
);
299 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
303 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
304 GetValue ().ToString (), TypeManager
.CSharpName (target
));
308 public abstract Constant
Increment ();
311 public class BoolConstant
: Constant
{
312 public readonly bool Value
;
314 public BoolConstant (bool val
, Location loc
):
320 override public string AsString ()
322 return Value
? "true" : "false";
325 protected override Expression
DoResolve (ResolveContext ec
)
327 type
= TypeManager
.bool_type
;
328 eclass
= ExprClass
.Value
;
332 public override object GetValue ()
334 return (object) Value
;
337 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
339 enc
.Stream
.Write (Value
);
342 public override void Emit (EmitContext ec
)
345 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
347 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
350 public override bool IsDefaultValue
{
356 public override bool IsNegative
{
362 public override bool IsZeroInteger
{
363 get { return Value == false; }
366 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
373 public class ByteConstant
: IntegralConstant
{
374 public readonly byte Value
;
376 public ByteConstant (byte v
, Location loc
):
382 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
384 enc
.Stream
.Write (Value
);
387 public override void Emit (EmitContext ec
)
389 IntLiteral
.EmitInt (ec
.ig
, Value
);
392 public override string AsString ()
394 return Value
.ToString ();
397 protected override Expression
DoResolve (ResolveContext ec
)
399 type
= TypeManager
.byte_type
;
400 eclass
= ExprClass
.Value
;
404 public override object GetValue ()
409 public override Constant
Increment ()
411 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
414 public override bool IsDefaultValue
{
420 public override bool IsOneInteger
{
426 public override bool IsNegative
{
432 public override bool IsZeroInteger
{
433 get { return Value == 0; }
436 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
438 if (target_type
== TypeManager
.sbyte_type
) {
439 if (in_checked_context
){
440 if (Value
> SByte
.MaxValue
)
441 throw new OverflowException ();
443 return new SByteConstant ((sbyte) Value
, Location
);
445 if (target_type
== TypeManager
.short_type
)
446 return new ShortConstant ((short) Value
, Location
);
447 if (target_type
== TypeManager
.ushort_type
)
448 return new UShortConstant ((ushort) Value
, Location
);
449 if (target_type
== TypeManager
.int32_type
)
450 return new IntConstant ((int) Value
, Location
);
451 if (target_type
== TypeManager
.uint32_type
)
452 return new UIntConstant ((uint) Value
, Location
);
453 if (target_type
== TypeManager
.int64_type
)
454 return new LongConstant ((long) Value
, Location
);
455 if (target_type
== TypeManager
.uint64_type
)
456 return new ULongConstant ((ulong) Value
, Location
);
457 if (target_type
== TypeManager
.float_type
)
458 return new FloatConstant ((float) Value
, Location
);
459 if (target_type
== TypeManager
.double_type
)
460 return new DoubleConstant ((double) Value
, Location
);
461 if (target_type
== TypeManager
.char_type
)
462 return new CharConstant ((char) Value
, Location
);
463 if (target_type
== TypeManager
.decimal_type
)
464 return new DecimalConstant ((decimal) Value
, Location
);
471 public class CharConstant
: Constant
{
472 public readonly char Value
;
474 public CharConstant (char v
, Location loc
):
480 protected override Expression
DoResolve (ResolveContext rc
)
482 type
= TypeManager
.char_type
;
483 eclass
= ExprClass
.Value
;
487 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
489 enc
.Stream
.Write ((ushort) Value
);
492 public override void Emit (EmitContext ec
)
494 IntLiteral
.EmitInt (ec
.ig
, Value
);
497 static string descape (char c
)
523 return c
.ToString ();
526 public override string AsString ()
528 return "\"" + descape (Value
) + "\"";
531 public override object GetValue ()
536 public override bool IsDefaultValue
{
542 public override bool IsNegative
{
548 public override bool IsZeroInteger
{
549 get { return Value == '\0'; }
552 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
554 if (target_type
== TypeManager
.byte_type
) {
555 if (in_checked_context
){
556 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
557 throw new OverflowException ();
559 return new ByteConstant ((byte) Value
, Location
);
561 if (target_type
== TypeManager
.sbyte_type
) {
562 if (in_checked_context
){
563 if (Value
> SByte
.MaxValue
)
564 throw new OverflowException ();
566 return new SByteConstant ((sbyte) Value
, Location
);
568 if (target_type
== TypeManager
.short_type
) {
569 if (in_checked_context
){
570 if (Value
> Int16
.MaxValue
)
571 throw new OverflowException ();
573 return new ShortConstant ((short) Value
, Location
);
575 if (target_type
== TypeManager
.int32_type
)
576 return new IntConstant ((int) Value
, Location
);
577 if (target_type
== TypeManager
.uint32_type
)
578 return new UIntConstant ((uint) Value
, Location
);
579 if (target_type
== TypeManager
.int64_type
)
580 return new LongConstant ((long) Value
, Location
);
581 if (target_type
== TypeManager
.uint64_type
)
582 return new ULongConstant ((ulong) Value
, Location
);
583 if (target_type
== TypeManager
.float_type
)
584 return new FloatConstant ((float) Value
, Location
);
585 if (target_type
== TypeManager
.double_type
)
586 return new DoubleConstant ((double) Value
, Location
);
587 if (target_type
== TypeManager
.decimal_type
)
588 return new DecimalConstant ((decimal) Value
, Location
);
595 public class SByteConstant
: IntegralConstant
{
596 public readonly sbyte Value
;
598 public SByteConstant (sbyte v
, Location loc
):
604 protected override Expression
DoResolve (ResolveContext rc
)
606 type
= TypeManager
.sbyte_type
;
607 eclass
= ExprClass
.Value
;
611 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
613 enc
.Stream
.Write (Value
);
616 public override void Emit (EmitContext ec
)
618 IntLiteral
.EmitInt (ec
.ig
, Value
);
621 public override string AsString ()
623 return Value
.ToString ();
626 public override object GetValue ()
631 public override Constant
Increment ()
633 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
636 public override bool IsDefaultValue
{
642 public override bool IsNegative
{
648 public override bool IsOneInteger
{
654 public override bool IsZeroInteger
{
655 get { return Value == 0; }
658 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
660 if (target_type
== TypeManager
.byte_type
) {
661 if (in_checked_context
&& Value
< 0)
662 throw new OverflowException ();
663 return new ByteConstant ((byte) Value
, Location
);
665 if (target_type
== TypeManager
.short_type
)
666 return new ShortConstant ((short) Value
, Location
);
667 if (target_type
== TypeManager
.ushort_type
) {
668 if (in_checked_context
&& Value
< 0)
669 throw new OverflowException ();
670 return new UShortConstant ((ushort) Value
, Location
);
671 } if (target_type
== TypeManager
.int32_type
)
672 return new IntConstant ((int) Value
, Location
);
673 if (target_type
== TypeManager
.uint32_type
) {
674 if (in_checked_context
&& Value
< 0)
675 throw new OverflowException ();
676 return new UIntConstant ((uint) Value
, Location
);
677 } if (target_type
== TypeManager
.int64_type
)
678 return new LongConstant ((long) Value
, Location
);
679 if (target_type
== TypeManager
.uint64_type
) {
680 if (in_checked_context
&& Value
< 0)
681 throw new OverflowException ();
682 return new ULongConstant ((ulong) Value
, Location
);
684 if (target_type
== TypeManager
.float_type
)
685 return new FloatConstant ((float) Value
, Location
);
686 if (target_type
== TypeManager
.double_type
)
687 return new DoubleConstant ((double) Value
, Location
);
688 if (target_type
== TypeManager
.char_type
) {
689 if (in_checked_context
&& Value
< 0)
690 throw new OverflowException ();
691 return new CharConstant ((char) Value
, Location
);
693 if (target_type
== TypeManager
.decimal_type
)
694 return new DecimalConstant ((decimal) Value
, Location
);
701 public class ShortConstant
: IntegralConstant
{
702 public readonly short Value
;
704 public ShortConstant (short v
, Location loc
):
710 protected override Expression
DoResolve (ResolveContext rc
)
712 type
= TypeManager
.short_type
;
713 eclass
= ExprClass
.Value
;
717 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
719 enc
.Stream
.Write (Value
);
722 public override void Emit (EmitContext ec
)
724 IntLiteral
.EmitInt (ec
.ig
, Value
);
727 public override string AsString ()
729 return Value
.ToString ();
732 public override object GetValue ()
737 public override Constant
Increment ()
739 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
742 public override bool IsDefaultValue
{
748 public override bool IsZeroInteger
{
749 get { return Value == 0; }
752 public override bool IsNegative
{
758 public override bool IsOneInteger
{
764 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
766 if (target_type
== TypeManager
.byte_type
) {
767 if (in_checked_context
){
768 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
769 throw new OverflowException ();
771 return new ByteConstant ((byte) Value
, Location
);
773 if (target_type
== TypeManager
.sbyte_type
) {
774 if (in_checked_context
){
775 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
776 throw new OverflowException ();
778 return new SByteConstant ((sbyte) Value
, Location
);
780 if (target_type
== TypeManager
.ushort_type
) {
781 if (in_checked_context
&& Value
< 0)
782 throw new OverflowException ();
784 return new UShortConstant ((ushort) Value
, Location
);
786 if (target_type
== TypeManager
.int32_type
)
787 return new IntConstant ((int) Value
, Location
);
788 if (target_type
== TypeManager
.uint32_type
) {
789 if (in_checked_context
&& Value
< 0)
790 throw new OverflowException ();
791 return new UIntConstant ((uint) Value
, Location
);
793 if (target_type
== TypeManager
.int64_type
)
794 return new LongConstant ((long) Value
, Location
);
795 if (target_type
== TypeManager
.uint64_type
) {
796 if (in_checked_context
&& Value
< 0)
797 throw new OverflowException ();
798 return new ULongConstant ((ulong) Value
, Location
);
800 if (target_type
== TypeManager
.float_type
)
801 return new FloatConstant ((float) Value
, Location
);
802 if (target_type
== TypeManager
.double_type
)
803 return new DoubleConstant ((double) Value
, Location
);
804 if (target_type
== TypeManager
.char_type
) {
805 if (in_checked_context
){
806 if (Value
< Char
.MinValue
)
807 throw new OverflowException ();
809 return new CharConstant ((char) Value
, Location
);
811 if (target_type
== TypeManager
.decimal_type
)
812 return new DecimalConstant ((decimal) Value
, Location
);
819 public class UShortConstant
: IntegralConstant
{
820 public readonly ushort Value
;
822 public UShortConstant (ushort v
, Location loc
):
828 protected override Expression
DoResolve (ResolveContext rc
)
830 type
= TypeManager
.ushort_type
;
831 eclass
= ExprClass
.Value
;
835 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
837 enc
.Stream
.Write (Value
);
840 public override void Emit (EmitContext ec
)
842 IntLiteral
.EmitInt (ec
.ig
, Value
);
845 public override string AsString ()
847 return Value
.ToString ();
850 public override object GetValue ()
855 public override Constant
Increment ()
857 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
860 public override bool IsDefaultValue
{
866 public override bool IsNegative
{
872 public override bool IsOneInteger
{
878 public override bool IsZeroInteger
{
879 get { return Value == 0; }
882 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
884 if (target_type
== TypeManager
.byte_type
) {
885 if (in_checked_context
){
886 if (Value
> Byte
.MaxValue
)
887 throw new OverflowException ();
889 return new ByteConstant ((byte) Value
, Location
);
891 if (target_type
== TypeManager
.sbyte_type
) {
892 if (in_checked_context
){
893 if (Value
> SByte
.MaxValue
)
894 throw new OverflowException ();
896 return new SByteConstant ((sbyte) Value
, Location
);
898 if (target_type
== TypeManager
.short_type
) {
899 if (in_checked_context
){
900 if (Value
> Int16
.MaxValue
)
901 throw new OverflowException ();
903 return new ShortConstant ((short) Value
, Location
);
905 if (target_type
== TypeManager
.int32_type
)
906 return new IntConstant ((int) Value
, Location
);
907 if (target_type
== TypeManager
.uint32_type
)
908 return new UIntConstant ((uint) Value
, Location
);
909 if (target_type
== TypeManager
.int64_type
)
910 return new LongConstant ((long) Value
, Location
);
911 if (target_type
== TypeManager
.uint64_type
)
912 return new ULongConstant ((ulong) Value
, Location
);
913 if (target_type
== TypeManager
.float_type
)
914 return new FloatConstant ((float) Value
, Location
);
915 if (target_type
== TypeManager
.double_type
)
916 return new DoubleConstant ((double) Value
, Location
);
917 if (target_type
== TypeManager
.char_type
) {
918 if (in_checked_context
){
919 if (Value
> Char
.MaxValue
)
920 throw new OverflowException ();
922 return new CharConstant ((char) Value
, Location
);
924 if (target_type
== TypeManager
.decimal_type
)
925 return new DecimalConstant ((decimal) Value
, Location
);
931 public class IntConstant
: IntegralConstant
{
932 public readonly int Value
;
934 public IntConstant (int v
, Location loc
):
940 protected override Expression
DoResolve (ResolveContext rc
)
942 type
= TypeManager
.int32_type
;
943 eclass
= ExprClass
.Value
;
947 static public void EmitInt (ILGenerator ig
, int i
)
951 ig
.Emit (OpCodes
.Ldc_I4_M1
);
955 ig
.Emit (OpCodes
.Ldc_I4_0
);
959 ig
.Emit (OpCodes
.Ldc_I4_1
);
963 ig
.Emit (OpCodes
.Ldc_I4_2
);
967 ig
.Emit (OpCodes
.Ldc_I4_3
);
971 ig
.Emit (OpCodes
.Ldc_I4_4
);
975 ig
.Emit (OpCodes
.Ldc_I4_5
);
979 ig
.Emit (OpCodes
.Ldc_I4_6
);
983 ig
.Emit (OpCodes
.Ldc_I4_7
);
987 ig
.Emit (OpCodes
.Ldc_I4_8
);
991 if (i
>= -128 && i
<= 127){
992 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
994 ig
.Emit (OpCodes
.Ldc_I4
, i
);
999 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1001 enc
.Stream
.Write (Value
);
1004 public override void Emit (EmitContext ec
)
1006 EmitInt (ec
.ig
, Value
);
1009 public override string AsString ()
1011 return Value
.ToString ();
1014 public override object GetValue ()
1019 public override Constant
Increment ()
1021 return new IntConstant (checked(Value
+ 1), loc
);
1024 public override bool IsDefaultValue
{
1030 public override bool IsNegative
{
1036 public override bool IsOneInteger
{
1042 public override bool IsZeroInteger
{
1043 get { return Value == 0; }
1046 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1048 if (target_type
== TypeManager
.byte_type
) {
1049 if (in_checked_context
){
1050 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1051 throw new OverflowException ();
1053 return new ByteConstant ((byte) Value
, Location
);
1055 if (target_type
== TypeManager
.sbyte_type
) {
1056 if (in_checked_context
){
1057 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1058 throw new OverflowException ();
1060 return new SByteConstant ((sbyte) Value
, Location
);
1062 if (target_type
== TypeManager
.short_type
) {
1063 if (in_checked_context
){
1064 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1065 throw new OverflowException ();
1067 return new ShortConstant ((short) Value
, Location
);
1069 if (target_type
== TypeManager
.ushort_type
) {
1070 if (in_checked_context
){
1071 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1072 throw new OverflowException ();
1074 return new UShortConstant ((ushort) Value
, Location
);
1076 if (target_type
== TypeManager
.uint32_type
) {
1077 if (in_checked_context
){
1078 if (Value
< UInt32
.MinValue
)
1079 throw new OverflowException ();
1081 return new UIntConstant ((uint) Value
, Location
);
1083 if (target_type
== TypeManager
.int64_type
)
1084 return new LongConstant ((long) Value
, Location
);
1085 if (target_type
== TypeManager
.uint64_type
) {
1086 if (in_checked_context
&& Value
< 0)
1087 throw new OverflowException ();
1088 return new ULongConstant ((ulong) Value
, Location
);
1090 if (target_type
== TypeManager
.float_type
)
1091 return new FloatConstant ((float) Value
, Location
);
1092 if (target_type
== TypeManager
.double_type
)
1093 return new DoubleConstant ((double) Value
, Location
);
1094 if (target_type
== TypeManager
.char_type
) {
1095 if (in_checked_context
){
1096 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1097 throw new OverflowException ();
1099 return new CharConstant ((char) Value
, Location
);
1101 if (target_type
== TypeManager
.decimal_type
)
1102 return new DecimalConstant ((decimal) Value
, Location
);
1107 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
1109 if (this.type
== type
)
1112 Constant c
= TryImplicitIntConversion (type
);
1114 return c
.Resolve (rc
);
1116 return base.ConvertImplicitly (rc
, type
);
1120 /// Attempts to perform an implicit constant conversion of the IntConstant
1121 /// into a different data type using casts (See Implicit Constant
1122 /// Expression Conversions)
1124 Constant
TryImplicitIntConversion (Type target_type
)
1126 if (target_type
== TypeManager
.sbyte_type
) {
1127 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1128 return new SByteConstant ((sbyte) Value
, loc
);
1130 else if (target_type
== TypeManager
.byte_type
) {
1131 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1132 return new ByteConstant ((byte) Value
, loc
);
1134 else if (target_type
== TypeManager
.short_type
) {
1135 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1136 return new ShortConstant ((short) Value
, loc
);
1138 else if (target_type
== TypeManager
.ushort_type
) {
1139 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1140 return new UShortConstant ((ushort) Value
, loc
);
1142 else if (target_type
== TypeManager
.uint32_type
) {
1144 return new UIntConstant ((uint) Value
, loc
);
1146 else if (target_type
== TypeManager
.uint64_type
) {
1148 // we can optimize this case: a positive int32
1149 // always fits on a uint64. But we need an opcode
1153 return new ULongConstant ((ulong) Value
, loc
);
1155 else if (target_type
== TypeManager
.double_type
)
1156 return new DoubleConstant ((double) Value
, loc
);
1157 else if (target_type
== TypeManager
.float_type
)
1158 return new FloatConstant ((float) Value
, loc
);
1164 public class UIntConstant
: IntegralConstant
{
1165 public readonly uint Value
;
1167 public UIntConstant (uint v
, Location loc
):
1173 protected override Expression
DoResolve (ResolveContext rc
)
1175 type
= TypeManager
.uint32_type
;
1176 eclass
= ExprClass
.Value
;
1180 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1182 enc
.Stream
.Write (Value
);
1185 public override void Emit (EmitContext ec
)
1187 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
1190 public override string AsString ()
1192 return Value
.ToString ();
1195 public override object GetValue ()
1200 public override Constant
Increment ()
1202 return new UIntConstant (checked(Value
+ 1), loc
);
1205 public override bool IsDefaultValue
{
1211 public override bool IsNegative
{
1217 public override bool IsOneInteger
{
1223 public override bool IsZeroInteger
{
1224 get { return Value == 0; }
1227 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1229 if (target_type
== TypeManager
.byte_type
) {
1230 if (in_checked_context
){
1231 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1232 throw new OverflowException ();
1234 return new ByteConstant ((byte) Value
, Location
);
1236 if (target_type
== TypeManager
.sbyte_type
) {
1237 if (in_checked_context
){
1238 if (Value
> SByte
.MaxValue
)
1239 throw new OverflowException ();
1241 return new SByteConstant ((sbyte) Value
, Location
);
1243 if (target_type
== TypeManager
.short_type
) {
1244 if (in_checked_context
){
1245 if (Value
> Int16
.MaxValue
)
1246 throw new OverflowException ();
1248 return new ShortConstant ((short) Value
, Location
);
1250 if (target_type
== TypeManager
.ushort_type
) {
1251 if (in_checked_context
){
1252 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1253 throw new OverflowException ();
1255 return new UShortConstant ((ushort) Value
, Location
);
1257 if (target_type
== TypeManager
.int32_type
) {
1258 if (in_checked_context
){
1259 if (Value
> Int32
.MaxValue
)
1260 throw new OverflowException ();
1262 return new IntConstant ((int) Value
, Location
);
1264 if (target_type
== TypeManager
.int64_type
)
1265 return new LongConstant ((long) Value
, Location
);
1266 if (target_type
== TypeManager
.uint64_type
)
1267 return new ULongConstant ((ulong) Value
, Location
);
1268 if (target_type
== TypeManager
.float_type
)
1269 return new FloatConstant ((float) Value
, Location
);
1270 if (target_type
== TypeManager
.double_type
)
1271 return new DoubleConstant ((double) Value
, Location
);
1272 if (target_type
== TypeManager
.char_type
) {
1273 if (in_checked_context
){
1274 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1275 throw new OverflowException ();
1277 return new CharConstant ((char) Value
, Location
);
1279 if (target_type
== TypeManager
.decimal_type
)
1280 return new DecimalConstant ((decimal) Value
, Location
);
1287 public class LongConstant
: IntegralConstant
{
1288 public readonly long Value
;
1290 public LongConstant (long v
, Location loc
):
1296 protected override Expression
DoResolve (ResolveContext rc
)
1298 type
= TypeManager
.int64_type
;
1299 eclass
= ExprClass
.Value
;
1303 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1305 enc
.Stream
.Write (Value
);
1308 public override void Emit (EmitContext ec
)
1310 EmitLong (ec
.ig
, Value
);
1313 static public void EmitLong (ILGenerator ig
, long l
)
1315 if (l
>= int.MinValue
&& l
<= int.MaxValue
) {
1316 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1317 ig
.Emit (OpCodes
.Conv_I8
);
1321 if (l
>= 0 && l
<= uint.MaxValue
) {
1322 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1323 ig
.Emit (OpCodes
.Conv_U8
);
1327 ig
.Emit (OpCodes
.Ldc_I8
, l
);
1330 public override string AsString ()
1332 return Value
.ToString ();
1335 public override object GetValue ()
1340 public override Constant
Increment ()
1342 return new LongConstant (checked(Value
+ 1), loc
);
1345 public override bool IsDefaultValue
{
1351 public override bool IsNegative
{
1357 public override bool IsOneInteger
{
1363 public override bool IsZeroInteger
{
1364 get { return Value == 0; }
1367 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1369 if (target_type
== TypeManager
.byte_type
) {
1370 if (in_checked_context
){
1371 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1372 throw new OverflowException ();
1374 return new ByteConstant ((byte) Value
, Location
);
1376 if (target_type
== TypeManager
.sbyte_type
) {
1377 if (in_checked_context
){
1378 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1379 throw new OverflowException ();
1381 return new SByteConstant ((sbyte) Value
, Location
);
1383 if (target_type
== TypeManager
.short_type
) {
1384 if (in_checked_context
){
1385 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1386 throw new OverflowException ();
1388 return new ShortConstant ((short) Value
, Location
);
1390 if (target_type
== TypeManager
.ushort_type
) {
1391 if (in_checked_context
){
1392 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1393 throw new OverflowException ();
1395 return new UShortConstant ((ushort) Value
, Location
);
1397 if (target_type
== TypeManager
.int32_type
) {
1398 if (in_checked_context
){
1399 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1400 throw new OverflowException ();
1402 return new IntConstant ((int) Value
, Location
);
1404 if (target_type
== TypeManager
.uint32_type
) {
1405 if (in_checked_context
){
1406 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1407 throw new OverflowException ();
1409 return new UIntConstant ((uint) Value
, Location
);
1411 if (target_type
== TypeManager
.uint64_type
) {
1412 if (in_checked_context
&& Value
< 0)
1413 throw new OverflowException ();
1414 return new ULongConstant ((ulong) Value
, Location
);
1416 if (target_type
== TypeManager
.float_type
)
1417 return new FloatConstant ((float) Value
, Location
);
1418 if (target_type
== TypeManager
.double_type
)
1419 return new DoubleConstant ((double) Value
, Location
);
1420 if (target_type
== TypeManager
.char_type
) {
1421 if (in_checked_context
){
1422 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1423 throw new OverflowException ();
1425 return new CharConstant ((char) Value
, Location
);
1427 if (target_type
== TypeManager
.decimal_type
)
1428 return new DecimalConstant ((decimal) Value
, Location
);
1433 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
1435 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1436 return new ULongConstant ((ulong) Value
, loc
).Resolve (rc
);
1439 return base.ConvertImplicitly (rc
, type
);
1443 public class ULongConstant
: IntegralConstant
{
1444 public readonly ulong Value
;
1446 public ULongConstant (ulong v
, Location loc
):
1452 protected override Expression
DoResolve (ResolveContext rc
)
1454 type
= TypeManager
.uint64_type
;
1455 eclass
= ExprClass
.Value
;
1459 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1461 enc
.Stream
.Write (Value
);
1464 public override void Emit (EmitContext ec
)
1466 ILGenerator ig
= ec
.ig
;
1468 LongLiteral
.EmitLong (ig
, unchecked ((long) Value
));
1471 public override string AsString ()
1473 return Value
.ToString ();
1476 public override object GetValue ()
1481 public override Constant
Increment ()
1483 return new ULongConstant (checked(Value
+ 1), loc
);
1486 public override bool IsDefaultValue
{
1492 public override bool IsNegative
{
1498 public override bool IsOneInteger
{
1504 public override bool IsZeroInteger
{
1505 get { return Value == 0; }
1508 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1510 if (target_type
== TypeManager
.byte_type
) {
1511 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1512 throw new OverflowException ();
1513 return new ByteConstant ((byte) Value
, Location
);
1515 if (target_type
== TypeManager
.sbyte_type
) {
1516 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1517 throw new OverflowException ();
1518 return new SByteConstant ((sbyte) Value
, Location
);
1520 if (target_type
== TypeManager
.short_type
) {
1521 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1522 throw new OverflowException ();
1523 return new ShortConstant ((short) Value
, Location
);
1525 if (target_type
== TypeManager
.ushort_type
) {
1526 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1527 throw new OverflowException ();
1528 return new UShortConstant ((ushort) Value
, Location
);
1530 if (target_type
== TypeManager
.int32_type
) {
1531 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1532 throw new OverflowException ();
1533 return new IntConstant ((int) Value
, Location
);
1535 if (target_type
== TypeManager
.uint32_type
) {
1536 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1537 throw new OverflowException ();
1538 return new UIntConstant ((uint) Value
, Location
);
1540 if (target_type
== TypeManager
.int64_type
) {
1541 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1542 throw new OverflowException ();
1543 return new LongConstant ((long) Value
, Location
);
1545 if (target_type
== TypeManager
.float_type
)
1546 return new FloatConstant ((float) Value
, Location
);
1547 if (target_type
== TypeManager
.double_type
)
1548 return new DoubleConstant ((double) Value
, Location
);
1549 if (target_type
== TypeManager
.char_type
) {
1550 if (in_checked_context
&& Value
> Char
.MaxValue
)
1551 throw new OverflowException ();
1552 return new CharConstant ((char) Value
, Location
);
1554 if (target_type
== TypeManager
.decimal_type
)
1555 return new DecimalConstant ((decimal) Value
, Location
);
1562 public class FloatConstant
: Constant
{
1565 public FloatConstant (float v
, Location loc
):
1571 protected override Expression
DoResolve (ResolveContext rc
)
1573 type
= TypeManager
.float_type
;
1574 eclass
= ExprClass
.Value
;
1578 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1580 enc
.Stream
.Write (Value
);
1583 public override void Emit (EmitContext ec
)
1585 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
1588 public override string AsString ()
1590 return Value
.ToString ();
1593 public override object GetValue ()
1598 public override bool IsDefaultValue
{
1604 public override bool IsNegative
{
1610 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1612 if (target_type
== TypeManager
.byte_type
) {
1613 if (in_checked_context
){
1614 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1615 throw new OverflowException ();
1617 return new ByteConstant ((byte) Value
, Location
);
1619 if (target_type
== TypeManager
.sbyte_type
) {
1620 if (in_checked_context
){
1621 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1622 throw new OverflowException ();
1624 return new SByteConstant ((sbyte) Value
, Location
);
1626 if (target_type
== TypeManager
.short_type
) {
1627 if (in_checked_context
){
1628 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1629 throw new OverflowException ();
1631 return new ShortConstant ((short) Value
, Location
);
1633 if (target_type
== TypeManager
.ushort_type
) {
1634 if (in_checked_context
){
1635 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1636 throw new OverflowException ();
1638 return new UShortConstant ((ushort) Value
, Location
);
1640 if (target_type
== TypeManager
.int32_type
) {
1641 if (in_checked_context
){
1642 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1643 throw new OverflowException ();
1645 return new IntConstant ((int) Value
, Location
);
1647 if (target_type
== TypeManager
.uint32_type
) {
1648 if (in_checked_context
){
1649 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1650 throw new OverflowException ();
1652 return new UIntConstant ((uint) Value
, Location
);
1654 if (target_type
== TypeManager
.int64_type
) {
1655 if (in_checked_context
){
1656 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1657 throw new OverflowException ();
1659 return new LongConstant ((long) Value
, Location
);
1661 if (target_type
== TypeManager
.uint64_type
) {
1662 if (in_checked_context
){
1663 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1664 throw new OverflowException ();
1666 return new ULongConstant ((ulong) Value
, Location
);
1668 if (target_type
== TypeManager
.double_type
)
1669 return new DoubleConstant ((double) Value
, Location
);
1670 if (target_type
== TypeManager
.char_type
) {
1671 if (in_checked_context
){
1672 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1673 throw new OverflowException ();
1675 return new CharConstant ((char) Value
, Location
);
1677 if (target_type
== TypeManager
.decimal_type
)
1678 return new DecimalConstant ((decimal) Value
, Location
);
1685 public class DoubleConstant
: Constant
{
1686 public double Value
;
1688 public DoubleConstant (double v
, Location loc
):
1694 protected override Expression
DoResolve (ResolveContext rc
)
1696 type
= TypeManager
.double_type
;
1697 eclass
= ExprClass
.Value
;
1701 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1703 enc
.Stream
.Write (Value
);
1706 public override void Emit (EmitContext ec
)
1708 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
1711 public override string AsString ()
1713 return Value
.ToString ();
1716 public override object GetValue ()
1721 public override bool IsDefaultValue
{
1727 public override bool IsNegative
{
1733 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1735 if (target_type
== TypeManager
.byte_type
) {
1736 if (in_checked_context
){
1737 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1738 throw new OverflowException ();
1740 return new ByteConstant ((byte) Value
, Location
);
1742 if (target_type
== TypeManager
.sbyte_type
) {
1743 if (in_checked_context
){
1744 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1745 throw new OverflowException ();
1747 return new SByteConstant ((sbyte) Value
, Location
);
1749 if (target_type
== TypeManager
.short_type
) {
1750 if (in_checked_context
){
1751 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1752 throw new OverflowException ();
1754 return new ShortConstant ((short) Value
, Location
);
1756 if (target_type
== TypeManager
.ushort_type
) {
1757 if (in_checked_context
){
1758 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1759 throw new OverflowException ();
1761 return new UShortConstant ((ushort) Value
, Location
);
1763 if (target_type
== TypeManager
.int32_type
) {
1764 if (in_checked_context
){
1765 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1766 throw new OverflowException ();
1768 return new IntConstant ((int) Value
, Location
);
1770 if (target_type
== TypeManager
.uint32_type
) {
1771 if (in_checked_context
){
1772 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1773 throw new OverflowException ();
1775 return new UIntConstant ((uint) Value
, Location
);
1777 if (target_type
== TypeManager
.int64_type
) {
1778 if (in_checked_context
){
1779 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1780 throw new OverflowException ();
1782 return new LongConstant ((long) Value
, Location
);
1784 if (target_type
== TypeManager
.uint64_type
) {
1785 if (in_checked_context
){
1786 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1787 throw new OverflowException ();
1789 return new ULongConstant ((ulong) Value
, Location
);
1791 if (target_type
== TypeManager
.float_type
)
1792 return new FloatConstant ((float) Value
, Location
);
1793 if (target_type
== TypeManager
.char_type
) {
1794 if (in_checked_context
){
1795 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1796 throw new OverflowException ();
1798 return new CharConstant ((char) Value
, Location
);
1800 if (target_type
== TypeManager
.decimal_type
)
1801 return new DecimalConstant ((decimal) Value
, Location
);
1808 public class DecimalConstant
: Constant
{
1809 public readonly decimal Value
;
1811 public DecimalConstant (decimal d
, Location loc
):
1817 override public string AsString ()
1819 return Value
.ToString () + "M";
1822 protected override Expression
DoResolve (ResolveContext rc
)
1824 type
= TypeManager
.decimal_type
;
1825 eclass
= ExprClass
.Value
;
1829 public override object GetValue ()
1831 return (object) Value
;
1834 public override void Emit (EmitContext ec
)
1836 ILGenerator ig
= ec
.ig
;
1838 int [] words
= decimal.GetBits (Value
);
1839 int power
= (words
[3] >> 16) & 0xff;
1842 if (Value
<= int.MaxValue
&& Value
>= int.MinValue
) {
1843 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1844 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1845 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1847 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1851 IntConstant
.EmitInt (ig
, (int) Value
);
1852 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1856 if (Value
<= long.MaxValue
&& Value
>= long.MinValue
) {
1857 if (TypeManager
.void_decimal_ctor_long_arg
== null) {
1858 TypeManager
.void_decimal_ctor_long_arg
= TypeManager
.GetPredefinedConstructor (
1859 TypeManager
.decimal_type
, loc
, TypeManager
.int64_type
);
1861 if (TypeManager
.void_decimal_ctor_long_arg
== null)
1865 LongConstant
.EmitLong (ig
, (long) Value
);
1866 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_long_arg
);
1871 IntConstant
.EmitInt (ig
, words
[0]);
1872 IntConstant
.EmitInt (ig
, words
[1]);
1873 IntConstant
.EmitInt (ig
, words
[2]);
1876 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1879 IntConstant
.EmitInt (ig
, power
);
1881 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1882 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1883 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1884 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1886 if (TypeManager
.void_decimal_ctor_five_args
== null)
1890 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1893 public override bool IsDefaultValue
{
1899 public override bool IsNegative
{
1905 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1907 if (target_type
== TypeManager
.sbyte_type
)
1908 return new SByteConstant ((sbyte)Value
, loc
);
1909 if (target_type
== TypeManager
.byte_type
)
1910 return new ByteConstant ((byte)Value
, loc
);
1911 if (target_type
== TypeManager
.short_type
)
1912 return new ShortConstant ((short)Value
, loc
);
1913 if (target_type
== TypeManager
.ushort_type
)
1914 return new UShortConstant ((ushort)Value
, loc
);
1915 if (target_type
== TypeManager
.int32_type
)
1916 return new IntConstant ((int)Value
, loc
);
1917 if (target_type
== TypeManager
.uint32_type
)
1918 return new UIntConstant ((uint)Value
, loc
);
1919 if (target_type
== TypeManager
.int64_type
)
1920 return new LongConstant ((long)Value
, loc
);
1921 if (target_type
== TypeManager
.uint64_type
)
1922 return new ULongConstant ((ulong)Value
, loc
);
1923 if (target_type
== TypeManager
.char_type
)
1924 return new CharConstant ((char)Value
, loc
);
1925 if (target_type
== TypeManager
.float_type
)
1926 return new FloatConstant ((float)Value
, loc
);
1927 if (target_type
== TypeManager
.double_type
)
1928 return new DoubleConstant ((double)Value
, loc
);
1935 public class StringConstant
: Constant
{
1936 public readonly string Value
;
1938 public StringConstant (string s
, Location loc
):
1944 // FIXME: Escape the string.
1945 override public string AsString ()
1947 return "\"" + Value
+ "\"";
1950 protected override Expression
DoResolve (ResolveContext rc
)
1952 type
= TypeManager
.string_type
;
1953 eclass
= ExprClass
.Value
;
1957 public override object GetValue ()
1962 public override void Emit (EmitContext ec
)
1964 if (Value
== null) {
1965 ec
.ig
.Emit (OpCodes
.Ldnull
);
1970 // Use string.Empty for both literals and constants even if
1971 // it's not allowed at language level
1973 if (Value
.Length
== 0 && RootContext
.Optimize
&& !TypeManager
.IsEqual (ec
.CurrentType
, TypeManager
.string_type
)) {
1974 if (TypeManager
.string_empty
== null)
1975 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
);
1977 if (TypeManager
.string_empty
!= null) {
1978 ec
.ig
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1983 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1986 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
1989 if (type
!= targetType
)
1995 public override bool IsDefaultValue
{
1997 return Value
== null;
2001 public override bool IsNegative
{
2007 public override bool IsNull
{
2009 return IsDefaultValue
;
2013 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
2020 // Null constant can have its own type, think of `default (Foo)'
2022 public class NullConstant
: Constant
2024 public NullConstant (Type type
, Location loc
)
2027 eclass
= ExprClass
.Value
;
2031 public override string AsString ()
2033 return GetSignatureForError ();
2036 protected override Expression
DoResolve (ResolveContext ec
)
2041 public override void EncodeAttributeValue (IMemberContext rc
, AttributeEncoder enc
, Type targetType
)
2043 // Type it as string cast
2044 if (targetType
== TypeManager
.object_type
|| targetType
== TypeManager
.null_type
)
2045 enc
.Encode (TypeManager
.string_type
);
2047 if (targetType
.IsArray
) {
2048 if (targetType
.GetArrayRank () != 1)
2049 base.EncodeAttributeValue (rc
, enc
, targetType
);
2051 enc
.Stream
.Write (uint.MaxValue
);
2053 enc
.Stream
.Write (byte.MaxValue
);
2057 public override void Emit (EmitContext ec
)
2059 ec
.ig
.Emit (OpCodes
.Ldnull
);
2061 // Only to make verifier happy
2062 if (TypeManager
.IsGenericParameter (type
))
2063 ec
.ig
.Emit (OpCodes
.Unbox_Any
, type
);
2066 public override string ExprClassName
{
2068 return GetSignatureForError ();
2072 public override string GetSignatureForError ()
2077 public override Constant
ConvertExplicitly (bool inCheckedContext
, Type targetType
)
2079 if (targetType
.IsPointer
) {
2080 if (IsLiteral
|| this is NullPointer
)
2081 return new EmptyConstantCast (new NullPointer (loc
), targetType
);
2086 // Exlude internal compiler types
2087 if (targetType
== InternalType
.AnonymousMethod
)
2090 if (!IsLiteral
&& !Convert
.ImplicitStandardConversionExists (this, targetType
))
2093 if (TypeManager
.IsReferenceType (targetType
))
2094 return new NullConstant (targetType
, loc
);
2096 if (TypeManager
.IsNullableType (targetType
))
2097 return Nullable
.LiftedNull
.Create (targetType
, loc
);
2102 public override Constant
ConvertImplicitly (ResolveContext rc
, Type targetType
)
2104 return ConvertExplicitly (false, targetType
);
2107 public override object GetValue ()
2112 public override bool IsDefaultValue
{
2113 get { return true; }
2116 public override bool IsNegative
{
2117 get { return false; }
2120 public override bool IsNull
{
2121 get { return true; }
2124 public override bool IsZeroInteger
{
2125 get { return true; }
2128 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
2130 type
= storey
.MutateType (type
);
2135 /// The value is constant, but when emitted has a side effect. This is
2136 /// used by BitwiseAnd to ensure that the second expression is invoked
2137 /// regardless of the value of the left side.
2139 public class SideEffectConstant
: Constant
{
2140 public Constant
value;
2141 Expression side_effect
;
2143 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
2146 while (side_effect
is SideEffectConstant
)
2147 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
2148 this.side_effect
= side_effect
;
2151 public override string AsString ()
2153 return value.AsString ();
2156 protected override Expression
DoResolve (ResolveContext rc
)
2158 value = value.Resolve (rc
);
2161 eclass
= ExprClass
.Value
;
2165 public override object GetValue ()
2167 return value.GetValue ();
2170 public override void Emit (EmitContext ec
)
2172 side_effect
.EmitSideEffect (ec
);
2176 public override void EmitSideEffect (EmitContext ec
)
2178 side_effect
.EmitSideEffect (ec
);
2179 value.EmitSideEffect (ec
);
2182 public override bool IsDefaultValue
{
2183 get { return value.IsDefaultValue; }
2186 public override bool IsNegative
{
2187 get { return value.IsNegative; }
2190 public override bool IsZeroInteger
{
2191 get { return value.IsZeroInteger; }
2194 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
2196 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
2197 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);