2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
12 namespace Mono
.CSharp
{
15 using System
.Reflection
.Emit
;
16 using System
.Collections
;
19 /// Base class for constants and literals.
21 public abstract class Constant
: Expression
{
23 protected Constant (Location loc
)
29 /// This is different from ToString in that ToString
30 /// is supposed to be there for debugging purposes,
31 /// and is not guaranteed to be useful for anything else,
32 /// AsString() will provide something that can be used
33 /// for round-tripping C# code. Maybe it can be used
34 /// for IL assembly as well.
36 public abstract string AsString ();
38 override public string ToString ()
40 return this.GetType ().Name
+ " (" + AsString () + ")";
43 public override bool GetAttributableValue (ResolveContext ec
, Type value_type
, out object value)
45 if (value_type
== TypeManager
.object_type
) {
46 value = GetTypedValue ();
50 Constant c
= ImplicitConversionRequired (ec
, value_type
, loc
);
56 value = c
.GetTypedValue ();
61 /// This is used to obtain the actual value of the literal
62 /// cast into an object.
64 public abstract object GetValue ();
66 public virtual object GetTypedValue ()
71 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
73 if (!expl
&& IsLiteral
&&
74 (TypeManager
.IsPrimitiveType (target
) || type
== TypeManager
.decimal_type
) &&
75 (TypeManager
.IsPrimitiveType (type
) || type
== TypeManager
.decimal_type
)) {
76 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
77 AsString (), TypeManager
.CSharpName (target
));
79 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
83 public Constant
ImplicitConversionRequired (ResolveContext ec
, Type type
, Location loc
)
85 Constant c
= ConvertImplicitly (ec
, type
);
87 Error_ValueCannotBeConverted (ec
, loc
, type
, false);
92 public virtual Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
94 if (this.type
== type
)
97 if (Convert
.ImplicitNumericConversion (this, type
) == null)
101 object constant_value
= TypeManager
.ChangeType (GetValue (), type
, out fail
);
104 // We should always catch the error before this is ever
105 // reached, by calling Convert.ImplicitStandardConversionExists
107 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
108 TypeManager
.CSharpName (Type
), TypeManager
.CSharpName (type
));
111 return CreateConstant (rc
, type
, constant_value
, loc
);
115 // Returns a constant instance based on Type
117 public static Constant
CreateConstant (ResolveContext rc
, Type t
, object v
, Location loc
)
119 return CreateConstantFromValue (t
, v
, loc
).Resolve (rc
);
122 public static Constant
CreateConstantFromValue (Type t
, object v
, Location loc
)
124 if (t
== TypeManager
.int32_type
)
125 return new IntConstant ((int) v
, loc
);
126 if (t
== TypeManager
.string_type
)
127 return new StringConstant ((string) v
, loc
);
128 if (t
== TypeManager
.uint32_type
)
129 return new UIntConstant ((uint) v
, loc
);
130 if (t
== TypeManager
.int64_type
)
131 return new LongConstant ((long) v
, loc
);
132 if (t
== TypeManager
.uint64_type
)
133 return new ULongConstant ((ulong) v
, loc
);
134 if (t
== TypeManager
.float_type
)
135 return new FloatConstant ((float) v
, loc
);
136 if (t
== TypeManager
.double_type
)
137 return new DoubleConstant ((double) v
, loc
);
138 if (t
== TypeManager
.short_type
)
139 return new ShortConstant ((short)v
, loc
);
140 if (t
== TypeManager
.ushort_type
)
141 return new UShortConstant ((ushort)v
, loc
);
142 if (t
== TypeManager
.sbyte_type
)
143 return new SByteConstant ((sbyte)v
, loc
);
144 if (t
== TypeManager
.byte_type
)
145 return new ByteConstant ((byte)v
, loc
);
146 if (t
== TypeManager
.char_type
)
147 return new CharConstant ((char)v
, loc
);
148 if (t
== TypeManager
.bool_type
)
149 return new BoolConstant ((bool) v
, loc
);
150 if (t
== TypeManager
.decimal_type
)
151 return new DecimalConstant ((decimal) v
, loc
);
152 if (TypeManager
.IsEnumType (t
)) {
153 Type real_type
= TypeManager
.GetEnumUnderlyingType (t
);
154 return new EnumConstant (CreateConstantFromValue (real_type
, v
, loc
).Resolve (null), t
);
157 if (TypeManager
.IsNullableType (t
))
158 return Nullable
.LiftedNull
.Create (t
, loc
);
160 if (TypeManager
.IsReferenceType (t
))
161 return new NullConstant (t
, loc
);
164 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
165 v
, TypeManager
.CSharpName (t
));
168 public override Expression
CreateExpressionTree (ResolveContext ec
)
170 Arguments args
= new Arguments (2);
171 args
.Add (new Argument (this));
172 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
174 return CreateExpressionFactoryCall (ec
, "Constant", args
);
179 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
180 /// It throws OverflowException
182 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
183 public abstract Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
);
186 /// Attempts to do a compile-time folding of a constant cast.
188 public Constant
TryReduce (ResolveContext ec
, Type target_type
, Location loc
)
191 return TryReduce (ec
, target_type
);
193 catch (OverflowException
) {
194 if (ec
.ConstantCheckState
) {
195 ec
.Report
.Error (221, loc
, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
196 GetValue ().ToString (), TypeManager
.CSharpName (target_type
));
198 Error_ValueCannotBeConverted (ec
, loc
, target_type
, false);
201 return New
.Constantify (target_type
).Resolve (ec
);
205 Constant
TryReduce (ResolveContext ec
, Type target_type
)
207 if (Type
== target_type
)
211 if (TypeManager
.IsEnumType (target_type
)) {
212 c
= TryReduce (ec
, TypeManager
.GetEnumUnderlyingType (target_type
));
216 return new EnumConstant (c
, target_type
).Resolve (ec
);
219 c
= ConvertExplicitly (ec
.ConstantCheckState
, target_type
);
227 /// Need to pass type as the constant can require a boxing
228 /// and in such case no optimization is possible
230 public bool IsDefaultInitializer (Type type
)
233 return IsDefaultValue
;
235 return this is NullLiteral
;
238 public abstract bool IsDefaultValue
{
242 public abstract bool IsNegative
{
247 // When constant is declared as literal
249 public virtual bool IsLiteral
{
250 get { return false; }
254 // Returns true iff 1) the stack type of this is one of Object,
255 // int32, int64 and 2) this == 0 or this == null.
257 public virtual bool IsZeroInteger
{
258 get { return false; }
261 public override void EmitSideEffect (EmitContext ec
)
266 protected override void CloneTo (CloneContext clonectx
, Expression target
)
268 // CloneTo: Nothing, we do not keep any state on this expression
272 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
274 return System
.Linq
.Expressions
.Expression
.Constant (GetTypedValue (), type
);
278 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
280 // A constant cannot be of generic type
283 public new Constant
Resolve (ResolveContext rc
)
285 if (eclass
!= ExprClass
.Unresolved
)
288 // Resolved constant has to be still a constant
289 Constant c
= (Constant
) DoResolve (rc
);
293 if ((c
.eclass
& ExprClass
.Value
) == 0) {
294 c
.Error_UnexpectedKind (rc
, ResolveFlags
.VariableOrValue
, loc
);
299 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c
.GetType ());
305 public abstract class IntegralConstant
: Constant
{
306 protected IntegralConstant (Location loc
) :
311 public override void Error_ValueCannotBeConverted (ResolveContext ec
, Location loc
, Type target
, bool expl
)
314 ConvertExplicitly (true, target
);
315 base.Error_ValueCannotBeConverted (ec
, loc
, target
, expl
);
319 ec
.Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
320 GetValue ().ToString (), TypeManager
.CSharpName (target
));
324 public abstract Constant
Increment ();
327 public class BoolConstant
: Constant
{
328 public readonly bool Value
;
330 public BoolConstant (bool val
, Location loc
):
336 override public string AsString ()
338 return Value
? "true" : "false";
341 protected override Expression
DoResolve (ResolveContext ec
)
343 type
= TypeManager
.bool_type
;
344 eclass
= ExprClass
.Value
;
348 public override object GetValue ()
350 return (object) Value
;
353 public override void Emit (EmitContext ec
)
356 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
358 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
361 public override bool IsDefaultValue
{
367 public override bool IsNegative
{
373 public override bool IsZeroInteger
{
374 get { return Value == false; }
377 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
384 public class ByteConstant
: IntegralConstant
{
385 public readonly byte Value
;
387 public ByteConstant (byte v
, Location loc
):
393 public override void Emit (EmitContext ec
)
395 IntLiteral
.EmitInt (ec
.ig
, Value
);
398 public override string AsString ()
400 return Value
.ToString ();
403 protected override Expression
DoResolve (ResolveContext ec
)
405 type
= TypeManager
.byte_type
;
406 eclass
= ExprClass
.Value
;
410 public override object GetValue ()
415 public override Constant
Increment ()
417 return new ByteConstant (checked ((byte)(Value
+ 1)), loc
);
420 public override bool IsDefaultValue
{
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 Emit (EmitContext ec
)
489 IntLiteral
.EmitInt (ec
.ig
, Value
);
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
, Type 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 Emit (EmitContext ec
)
608 IntLiteral
.EmitInt (ec
.ig
, Value
);
611 public override string AsString ()
613 return Value
.ToString ();
616 public override object GetValue ()
621 public override Constant
Increment ()
623 return new SByteConstant (checked((sbyte)(Value
+ 1)), loc
);
626 public override bool IsDefaultValue
{
632 public override bool IsNegative
{
638 public override bool IsZeroInteger
{
639 get { return Value == 0; }
642 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
644 if (target_type
== TypeManager
.byte_type
) {
645 if (in_checked_context
&& Value
< 0)
646 throw new OverflowException ();
647 return new ByteConstant ((byte) Value
, Location
);
649 if (target_type
== TypeManager
.short_type
)
650 return new ShortConstant ((short) Value
, Location
);
651 if (target_type
== TypeManager
.ushort_type
) {
652 if (in_checked_context
&& Value
< 0)
653 throw new OverflowException ();
654 return new UShortConstant ((ushort) Value
, Location
);
655 } if (target_type
== TypeManager
.int32_type
)
656 return new IntConstant ((int) Value
, Location
);
657 if (target_type
== TypeManager
.uint32_type
) {
658 if (in_checked_context
&& Value
< 0)
659 throw new OverflowException ();
660 return new UIntConstant ((uint) Value
, Location
);
661 } if (target_type
== TypeManager
.int64_type
)
662 return new LongConstant ((long) Value
, Location
);
663 if (target_type
== TypeManager
.uint64_type
) {
664 if (in_checked_context
&& Value
< 0)
665 throw new OverflowException ();
666 return new ULongConstant ((ulong) Value
, Location
);
668 if (target_type
== TypeManager
.float_type
)
669 return new FloatConstant ((float) Value
, Location
);
670 if (target_type
== TypeManager
.double_type
)
671 return new DoubleConstant ((double) Value
, Location
);
672 if (target_type
== TypeManager
.char_type
) {
673 if (in_checked_context
&& Value
< 0)
674 throw new OverflowException ();
675 return new CharConstant ((char) Value
, Location
);
677 if (target_type
== TypeManager
.decimal_type
)
678 return new DecimalConstant ((decimal) Value
, Location
);
685 public class ShortConstant
: IntegralConstant
{
686 public readonly short Value
;
688 public ShortConstant (short v
, Location loc
):
694 protected override Expression
DoResolve (ResolveContext rc
)
696 type
= TypeManager
.short_type
;
697 eclass
= ExprClass
.Value
;
701 public override void Emit (EmitContext ec
)
703 IntLiteral
.EmitInt (ec
.ig
, Value
);
706 public override string AsString ()
708 return Value
.ToString ();
711 public override object GetValue ()
716 public override Constant
Increment ()
718 return new ShortConstant (checked((short)(Value
+ 1)), loc
);
721 public override bool IsDefaultValue
{
727 public override bool IsZeroInteger
{
728 get { return Value == 0; }
731 public override bool IsNegative
{
737 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
739 if (target_type
== TypeManager
.byte_type
) {
740 if (in_checked_context
){
741 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
742 throw new OverflowException ();
744 return new ByteConstant ((byte) Value
, Location
);
746 if (target_type
== TypeManager
.sbyte_type
) {
747 if (in_checked_context
){
748 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
749 throw new OverflowException ();
751 return new SByteConstant ((sbyte) Value
, Location
);
753 if (target_type
== TypeManager
.ushort_type
) {
754 if (in_checked_context
&& Value
< 0)
755 throw new OverflowException ();
757 return new UShortConstant ((ushort) Value
, Location
);
759 if (target_type
== TypeManager
.int32_type
)
760 return new IntConstant ((int) Value
, Location
);
761 if (target_type
== TypeManager
.uint32_type
) {
762 if (in_checked_context
&& Value
< 0)
763 throw new OverflowException ();
764 return new UIntConstant ((uint) Value
, Location
);
766 if (target_type
== TypeManager
.int64_type
)
767 return new LongConstant ((long) Value
, Location
);
768 if (target_type
== TypeManager
.uint64_type
) {
769 if (in_checked_context
&& Value
< 0)
770 throw new OverflowException ();
771 return new ULongConstant ((ulong) Value
, Location
);
773 if (target_type
== TypeManager
.float_type
)
774 return new FloatConstant ((float) Value
, Location
);
775 if (target_type
== TypeManager
.double_type
)
776 return new DoubleConstant ((double) Value
, Location
);
777 if (target_type
== TypeManager
.char_type
) {
778 if (in_checked_context
){
779 if (Value
< Char
.MinValue
)
780 throw new OverflowException ();
782 return new CharConstant ((char) Value
, Location
);
784 if (target_type
== TypeManager
.decimal_type
)
785 return new DecimalConstant ((decimal) Value
, Location
);
792 public class UShortConstant
: IntegralConstant
{
793 public readonly ushort Value
;
795 public UShortConstant (ushort v
, Location loc
):
801 protected override Expression
DoResolve (ResolveContext rc
)
803 type
= TypeManager
.ushort_type
;
804 eclass
= ExprClass
.Value
;
808 public override void Emit (EmitContext ec
)
810 IntLiteral
.EmitInt (ec
.ig
, Value
);
813 public override string AsString ()
815 return Value
.ToString ();
818 public override object GetValue ()
823 public override Constant
Increment ()
825 return new UShortConstant (checked((ushort)(Value
+ 1)), loc
);
828 public override bool IsDefaultValue
{
834 public override bool IsNegative
{
840 public override bool IsZeroInteger
{
841 get { return Value == 0; }
844 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
846 if (target_type
== TypeManager
.byte_type
) {
847 if (in_checked_context
){
848 if (Value
> Byte
.MaxValue
)
849 throw new OverflowException ();
851 return new ByteConstant ((byte) Value
, Location
);
853 if (target_type
== TypeManager
.sbyte_type
) {
854 if (in_checked_context
){
855 if (Value
> SByte
.MaxValue
)
856 throw new OverflowException ();
858 return new SByteConstant ((sbyte) Value
, Location
);
860 if (target_type
== TypeManager
.short_type
) {
861 if (in_checked_context
){
862 if (Value
> Int16
.MaxValue
)
863 throw new OverflowException ();
865 return new ShortConstant ((short) Value
, Location
);
867 if (target_type
== TypeManager
.int32_type
)
868 return new IntConstant ((int) Value
, Location
);
869 if (target_type
== TypeManager
.uint32_type
)
870 return new UIntConstant ((uint) Value
, Location
);
871 if (target_type
== TypeManager
.int64_type
)
872 return new LongConstant ((long) Value
, Location
);
873 if (target_type
== TypeManager
.uint64_type
)
874 return new ULongConstant ((ulong) Value
, Location
);
875 if (target_type
== TypeManager
.float_type
)
876 return new FloatConstant ((float) Value
, Location
);
877 if (target_type
== TypeManager
.double_type
)
878 return new DoubleConstant ((double) Value
, Location
);
879 if (target_type
== TypeManager
.char_type
) {
880 if (in_checked_context
){
881 if (Value
> Char
.MaxValue
)
882 throw new OverflowException ();
884 return new CharConstant ((char) Value
, Location
);
886 if (target_type
== TypeManager
.decimal_type
)
887 return new DecimalConstant ((decimal) Value
, Location
);
893 public class IntConstant
: IntegralConstant
{
894 public readonly int Value
;
896 public IntConstant (int v
, Location loc
):
902 protected override Expression
DoResolve (ResolveContext rc
)
904 type
= TypeManager
.int32_type
;
905 eclass
= ExprClass
.Value
;
909 static public void EmitInt (ILGenerator ig
, int i
)
913 ig
.Emit (OpCodes
.Ldc_I4_M1
);
917 ig
.Emit (OpCodes
.Ldc_I4_0
);
921 ig
.Emit (OpCodes
.Ldc_I4_1
);
925 ig
.Emit (OpCodes
.Ldc_I4_2
);
929 ig
.Emit (OpCodes
.Ldc_I4_3
);
933 ig
.Emit (OpCodes
.Ldc_I4_4
);
937 ig
.Emit (OpCodes
.Ldc_I4_5
);
941 ig
.Emit (OpCodes
.Ldc_I4_6
);
945 ig
.Emit (OpCodes
.Ldc_I4_7
);
949 ig
.Emit (OpCodes
.Ldc_I4_8
);
953 if (i
>= -128 && i
<= 127){
954 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
956 ig
.Emit (OpCodes
.Ldc_I4
, i
);
961 public override void Emit (EmitContext ec
)
963 EmitInt (ec
.ig
, Value
);
966 public override string AsString ()
968 return Value
.ToString ();
971 public override object GetValue ()
976 public override Constant
Increment ()
978 return new IntConstant (checked(Value
+ 1), loc
);
981 public override bool IsDefaultValue
{
987 public override bool IsNegative
{
993 public override bool IsZeroInteger
{
994 get { return Value == 0; }
997 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
999 if (target_type
== TypeManager
.byte_type
) {
1000 if (in_checked_context
){
1001 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1002 throw new OverflowException ();
1004 return new ByteConstant ((byte) Value
, Location
);
1006 if (target_type
== TypeManager
.sbyte_type
) {
1007 if (in_checked_context
){
1008 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1009 throw new OverflowException ();
1011 return new SByteConstant ((sbyte) Value
, Location
);
1013 if (target_type
== TypeManager
.short_type
) {
1014 if (in_checked_context
){
1015 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1016 throw new OverflowException ();
1018 return new ShortConstant ((short) Value
, Location
);
1020 if (target_type
== TypeManager
.ushort_type
) {
1021 if (in_checked_context
){
1022 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1023 throw new OverflowException ();
1025 return new UShortConstant ((ushort) Value
, Location
);
1027 if (target_type
== TypeManager
.uint32_type
) {
1028 if (in_checked_context
){
1029 if (Value
< UInt32
.MinValue
)
1030 throw new OverflowException ();
1032 return new UIntConstant ((uint) Value
, Location
);
1034 if (target_type
== TypeManager
.int64_type
)
1035 return new LongConstant ((long) Value
, Location
);
1036 if (target_type
== TypeManager
.uint64_type
) {
1037 if (in_checked_context
&& Value
< 0)
1038 throw new OverflowException ();
1039 return new ULongConstant ((ulong) Value
, Location
);
1041 if (target_type
== TypeManager
.float_type
)
1042 return new FloatConstant ((float) Value
, Location
);
1043 if (target_type
== TypeManager
.double_type
)
1044 return new DoubleConstant ((double) Value
, Location
);
1045 if (target_type
== TypeManager
.char_type
) {
1046 if (in_checked_context
){
1047 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1048 throw new OverflowException ();
1050 return new CharConstant ((char) Value
, Location
);
1052 if (target_type
== TypeManager
.decimal_type
)
1053 return new DecimalConstant ((decimal) Value
, Location
);
1058 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
1060 if (this.type
== type
)
1063 Constant c
= TryImplicitIntConversion (type
);
1065 return c
.Resolve (rc
);
1067 return base.ConvertImplicitly (rc
, type
);
1071 /// Attempts to perform an implicit constant conversion of the IntConstant
1072 /// into a different data type using casts (See Implicit Constant
1073 /// Expression Conversions)
1075 Constant
TryImplicitIntConversion (Type target_type
)
1077 if (target_type
== TypeManager
.sbyte_type
) {
1078 if (Value
>= SByte
.MinValue
&& Value
<= SByte
.MaxValue
)
1079 return new SByteConstant ((sbyte) Value
, loc
);
1081 else if (target_type
== TypeManager
.byte_type
) {
1082 if (Value
>= Byte
.MinValue
&& Value
<= Byte
.MaxValue
)
1083 return new ByteConstant ((byte) Value
, loc
);
1085 else if (target_type
== TypeManager
.short_type
) {
1086 if (Value
>= Int16
.MinValue
&& Value
<= Int16
.MaxValue
)
1087 return new ShortConstant ((short) Value
, loc
);
1089 else if (target_type
== TypeManager
.ushort_type
) {
1090 if (Value
>= UInt16
.MinValue
&& Value
<= UInt16
.MaxValue
)
1091 return new UShortConstant ((ushort) Value
, loc
);
1093 else if (target_type
== TypeManager
.uint32_type
) {
1095 return new UIntConstant ((uint) Value
, loc
);
1097 else if (target_type
== TypeManager
.uint64_type
) {
1099 // we can optimize this case: a positive int32
1100 // always fits on a uint64. But we need an opcode
1104 return new ULongConstant ((ulong) Value
, loc
);
1106 else if (target_type
== TypeManager
.double_type
)
1107 return new DoubleConstant ((double) Value
, loc
);
1108 else if (target_type
== TypeManager
.float_type
)
1109 return new FloatConstant ((float) Value
, loc
);
1115 public class UIntConstant
: IntegralConstant
{
1116 public readonly uint Value
;
1118 public UIntConstant (uint v
, Location loc
):
1124 protected override Expression
DoResolve (ResolveContext rc
)
1126 type
= TypeManager
.uint32_type
;
1127 eclass
= ExprClass
.Value
;
1131 public override void Emit (EmitContext ec
)
1133 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
1136 public override string AsString ()
1138 return Value
.ToString ();
1141 public override object GetValue ()
1146 public override Constant
Increment ()
1148 return new UIntConstant (checked(Value
+ 1), loc
);
1151 public override bool IsDefaultValue
{
1157 public override bool IsNegative
{
1163 public override bool IsZeroInteger
{
1164 get { return Value == 0; }
1167 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1169 if (target_type
== TypeManager
.byte_type
) {
1170 if (in_checked_context
){
1171 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1172 throw new OverflowException ();
1174 return new ByteConstant ((byte) Value
, Location
);
1176 if (target_type
== TypeManager
.sbyte_type
) {
1177 if (in_checked_context
){
1178 if (Value
> SByte
.MaxValue
)
1179 throw new OverflowException ();
1181 return new SByteConstant ((sbyte) Value
, Location
);
1183 if (target_type
== TypeManager
.short_type
) {
1184 if (in_checked_context
){
1185 if (Value
> Int16
.MaxValue
)
1186 throw new OverflowException ();
1188 return new ShortConstant ((short) Value
, Location
);
1190 if (target_type
== TypeManager
.ushort_type
) {
1191 if (in_checked_context
){
1192 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1193 throw new OverflowException ();
1195 return new UShortConstant ((ushort) Value
, Location
);
1197 if (target_type
== TypeManager
.int32_type
) {
1198 if (in_checked_context
){
1199 if (Value
> Int32
.MaxValue
)
1200 throw new OverflowException ();
1202 return new IntConstant ((int) Value
, Location
);
1204 if (target_type
== TypeManager
.int64_type
)
1205 return new LongConstant ((long) Value
, Location
);
1206 if (target_type
== TypeManager
.uint64_type
)
1207 return new ULongConstant ((ulong) Value
, Location
);
1208 if (target_type
== TypeManager
.float_type
)
1209 return new FloatConstant ((float) Value
, Location
);
1210 if (target_type
== TypeManager
.double_type
)
1211 return new DoubleConstant ((double) Value
, Location
);
1212 if (target_type
== TypeManager
.char_type
) {
1213 if (in_checked_context
){
1214 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1215 throw new OverflowException ();
1217 return new CharConstant ((char) Value
, Location
);
1219 if (target_type
== TypeManager
.decimal_type
)
1220 return new DecimalConstant ((decimal) Value
, Location
);
1227 public class LongConstant
: IntegralConstant
{
1228 public readonly long Value
;
1230 public LongConstant (long v
, Location loc
):
1236 protected override Expression
DoResolve (ResolveContext rc
)
1238 type
= TypeManager
.int64_type
;
1239 eclass
= ExprClass
.Value
;
1243 public override void Emit (EmitContext ec
)
1245 EmitLong (ec
.ig
, Value
);
1248 static public void EmitLong (ILGenerator ig
, long l
)
1250 if (l
>= int.MinValue
&& l
<= int.MaxValue
) {
1251 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1252 ig
.Emit (OpCodes
.Conv_I8
);
1256 if (l
>= 0 && l
<= uint.MaxValue
) {
1257 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
1258 ig
.Emit (OpCodes
.Conv_U8
);
1262 ig
.Emit (OpCodes
.Ldc_I8
, l
);
1265 public override string AsString ()
1267 return Value
.ToString ();
1270 public override object GetValue ()
1275 public override Constant
Increment ()
1277 return new LongConstant (checked(Value
+ 1), loc
);
1280 public override bool IsDefaultValue
{
1286 public override bool IsNegative
{
1292 public override bool IsZeroInteger
{
1293 get { return Value == 0; }
1296 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1298 if (target_type
== TypeManager
.byte_type
) {
1299 if (in_checked_context
){
1300 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
)
1301 throw new OverflowException ();
1303 return new ByteConstant ((byte) Value
, Location
);
1305 if (target_type
== TypeManager
.sbyte_type
) {
1306 if (in_checked_context
){
1307 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
)
1308 throw new OverflowException ();
1310 return new SByteConstant ((sbyte) Value
, Location
);
1312 if (target_type
== TypeManager
.short_type
) {
1313 if (in_checked_context
){
1314 if (Value
< Int16
.MinValue
|| Value
> Int16
.MaxValue
)
1315 throw new OverflowException ();
1317 return new ShortConstant ((short) Value
, Location
);
1319 if (target_type
== TypeManager
.ushort_type
) {
1320 if (in_checked_context
){
1321 if (Value
< UInt16
.MinValue
|| Value
> UInt16
.MaxValue
)
1322 throw new OverflowException ();
1324 return new UShortConstant ((ushort) Value
, Location
);
1326 if (target_type
== TypeManager
.int32_type
) {
1327 if (in_checked_context
){
1328 if (Value
< Int32
.MinValue
|| Value
> Int32
.MaxValue
)
1329 throw new OverflowException ();
1331 return new IntConstant ((int) Value
, Location
);
1333 if (target_type
== TypeManager
.uint32_type
) {
1334 if (in_checked_context
){
1335 if (Value
< UInt32
.MinValue
|| Value
> UInt32
.MaxValue
)
1336 throw new OverflowException ();
1338 return new UIntConstant ((uint) Value
, Location
);
1340 if (target_type
== TypeManager
.uint64_type
) {
1341 if (in_checked_context
&& Value
< 0)
1342 throw new OverflowException ();
1343 return new ULongConstant ((ulong) Value
, Location
);
1345 if (target_type
== TypeManager
.float_type
)
1346 return new FloatConstant ((float) Value
, Location
);
1347 if (target_type
== TypeManager
.double_type
)
1348 return new DoubleConstant ((double) Value
, Location
);
1349 if (target_type
== TypeManager
.char_type
) {
1350 if (in_checked_context
){
1351 if (Value
< Char
.MinValue
|| Value
> Char
.MaxValue
)
1352 throw new OverflowException ();
1354 return new CharConstant ((char) Value
, Location
);
1356 if (target_type
== TypeManager
.decimal_type
)
1357 return new DecimalConstant ((decimal) Value
, Location
);
1362 public override Constant
ConvertImplicitly (ResolveContext rc
, Type type
)
1364 if (Value
>= 0 && type
== TypeManager
.uint64_type
) {
1365 return new ULongConstant ((ulong) Value
, loc
).Resolve (rc
);
1368 return base.ConvertImplicitly (rc
, type
);
1372 public class ULongConstant
: IntegralConstant
{
1373 public readonly ulong Value
;
1375 public ULongConstant (ulong v
, Location loc
):
1381 protected override Expression
DoResolve (ResolveContext rc
)
1383 type
= TypeManager
.uint64_type
;
1384 eclass
= ExprClass
.Value
;
1388 public override void Emit (EmitContext ec
)
1390 ILGenerator ig
= ec
.ig
;
1392 LongLiteral
.EmitLong (ig
, 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 IsZeroInteger
{
1423 get { return Value == 0; }
1426 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1428 if (target_type
== TypeManager
.byte_type
) {
1429 if (in_checked_context
&& Value
> Byte
.MaxValue
)
1430 throw new OverflowException ();
1431 return new ByteConstant ((byte) Value
, Location
);
1433 if (target_type
== TypeManager
.sbyte_type
) {
1434 if (in_checked_context
&& Value
> ((ulong) SByte
.MaxValue
))
1435 throw new OverflowException ();
1436 return new SByteConstant ((sbyte) Value
, Location
);
1438 if (target_type
== TypeManager
.short_type
) {
1439 if (in_checked_context
&& Value
> ((ulong) Int16
.MaxValue
))
1440 throw new OverflowException ();
1441 return new ShortConstant ((short) Value
, Location
);
1443 if (target_type
== TypeManager
.ushort_type
) {
1444 if (in_checked_context
&& Value
> UInt16
.MaxValue
)
1445 throw new OverflowException ();
1446 return new UShortConstant ((ushort) Value
, Location
);
1448 if (target_type
== TypeManager
.int32_type
) {
1449 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1450 throw new OverflowException ();
1451 return new IntConstant ((int) Value
, Location
);
1453 if (target_type
== TypeManager
.uint32_type
) {
1454 if (in_checked_context
&& Value
> UInt32
.MaxValue
)
1455 throw new OverflowException ();
1456 return new UIntConstant ((uint) Value
, Location
);
1458 if (target_type
== TypeManager
.int64_type
) {
1459 if (in_checked_context
&& Value
> Int64
.MaxValue
)
1460 throw new OverflowException ();
1461 return new LongConstant ((long) Value
, Location
);
1463 if (target_type
== TypeManager
.float_type
)
1464 return new FloatConstant ((float) Value
, Location
);
1465 if (target_type
== TypeManager
.double_type
)
1466 return new DoubleConstant ((double) Value
, Location
);
1467 if (target_type
== TypeManager
.char_type
) {
1468 if (in_checked_context
&& Value
> Char
.MaxValue
)
1469 throw new OverflowException ();
1470 return new CharConstant ((char) Value
, Location
);
1472 if (target_type
== TypeManager
.decimal_type
)
1473 return new DecimalConstant ((decimal) Value
, Location
);
1480 public class FloatConstant
: Constant
{
1483 public FloatConstant (float v
, Location loc
):
1489 protected override Expression
DoResolve (ResolveContext rc
)
1491 type
= TypeManager
.float_type
;
1492 eclass
= ExprClass
.Value
;
1496 public override void Emit (EmitContext ec
)
1498 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
1501 public override string AsString ()
1503 return Value
.ToString ();
1506 public override object GetValue ()
1511 public override bool IsDefaultValue
{
1517 public override bool IsNegative
{
1523 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1525 if (target_type
== TypeManager
.byte_type
) {
1526 if (in_checked_context
){
1527 if (Value
< byte.MinValue
|| Value
> byte.MaxValue
|| float.IsNaN (Value
))
1528 throw new OverflowException ();
1530 return new ByteConstant ((byte) Value
, Location
);
1532 if (target_type
== TypeManager
.sbyte_type
) {
1533 if (in_checked_context
){
1534 if (Value
< sbyte.MinValue
|| Value
> sbyte.MaxValue
|| float.IsNaN (Value
))
1535 throw new OverflowException ();
1537 return new SByteConstant ((sbyte) Value
, Location
);
1539 if (target_type
== TypeManager
.short_type
) {
1540 if (in_checked_context
){
1541 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| float.IsNaN (Value
))
1542 throw new OverflowException ();
1544 return new ShortConstant ((short) Value
, Location
);
1546 if (target_type
== TypeManager
.ushort_type
) {
1547 if (in_checked_context
){
1548 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| float.IsNaN (Value
))
1549 throw new OverflowException ();
1551 return new UShortConstant ((ushort) Value
, Location
);
1553 if (target_type
== TypeManager
.int32_type
) {
1554 if (in_checked_context
){
1555 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| float.IsNaN (Value
))
1556 throw new OverflowException ();
1558 return new IntConstant ((int) Value
, Location
);
1560 if (target_type
== TypeManager
.uint32_type
) {
1561 if (in_checked_context
){
1562 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| float.IsNaN (Value
))
1563 throw new OverflowException ();
1565 return new UIntConstant ((uint) Value
, Location
);
1567 if (target_type
== TypeManager
.int64_type
) {
1568 if (in_checked_context
){
1569 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| float.IsNaN (Value
))
1570 throw new OverflowException ();
1572 return new LongConstant ((long) Value
, Location
);
1574 if (target_type
== TypeManager
.uint64_type
) {
1575 if (in_checked_context
){
1576 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| float.IsNaN (Value
))
1577 throw new OverflowException ();
1579 return new ULongConstant ((ulong) Value
, Location
);
1581 if (target_type
== TypeManager
.double_type
)
1582 return new DoubleConstant ((double) Value
, Location
);
1583 if (target_type
== TypeManager
.char_type
) {
1584 if (in_checked_context
){
1585 if (Value
< (float) char.MinValue
|| Value
> (float) char.MaxValue
|| float.IsNaN (Value
))
1586 throw new OverflowException ();
1588 return new CharConstant ((char) Value
, Location
);
1590 if (target_type
== TypeManager
.decimal_type
)
1591 return new DecimalConstant ((decimal) Value
, Location
);
1598 public class DoubleConstant
: Constant
{
1599 public double Value
;
1601 public DoubleConstant (double v
, Location loc
):
1607 protected override Expression
DoResolve (ResolveContext rc
)
1609 type
= TypeManager
.double_type
;
1610 eclass
= ExprClass
.Value
;
1614 public override void Emit (EmitContext ec
)
1616 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
1619 public override string AsString ()
1621 return Value
.ToString ();
1624 public override object GetValue ()
1629 public override bool IsDefaultValue
{
1635 public override bool IsNegative
{
1641 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1643 if (target_type
== TypeManager
.byte_type
) {
1644 if (in_checked_context
){
1645 if (Value
< Byte
.MinValue
|| Value
> Byte
.MaxValue
|| double.IsNaN (Value
))
1646 throw new OverflowException ();
1648 return new ByteConstant ((byte) Value
, Location
);
1650 if (target_type
== TypeManager
.sbyte_type
) {
1651 if (in_checked_context
){
1652 if (Value
< SByte
.MinValue
|| Value
> SByte
.MaxValue
|| double.IsNaN (Value
))
1653 throw new OverflowException ();
1655 return new SByteConstant ((sbyte) Value
, Location
);
1657 if (target_type
== TypeManager
.short_type
) {
1658 if (in_checked_context
){
1659 if (Value
< short.MinValue
|| Value
> short.MaxValue
|| double.IsNaN (Value
))
1660 throw new OverflowException ();
1662 return new ShortConstant ((short) Value
, Location
);
1664 if (target_type
== TypeManager
.ushort_type
) {
1665 if (in_checked_context
){
1666 if (Value
< ushort.MinValue
|| Value
> ushort.MaxValue
|| double.IsNaN (Value
))
1667 throw new OverflowException ();
1669 return new UShortConstant ((ushort) Value
, Location
);
1671 if (target_type
== TypeManager
.int32_type
) {
1672 if (in_checked_context
){
1673 if (Value
< int.MinValue
|| Value
> int.MaxValue
|| double.IsNaN (Value
))
1674 throw new OverflowException ();
1676 return new IntConstant ((int) Value
, Location
);
1678 if (target_type
== TypeManager
.uint32_type
) {
1679 if (in_checked_context
){
1680 if (Value
< uint.MinValue
|| Value
> uint.MaxValue
|| double.IsNaN (Value
))
1681 throw new OverflowException ();
1683 return new UIntConstant ((uint) Value
, Location
);
1685 if (target_type
== TypeManager
.int64_type
) {
1686 if (in_checked_context
){
1687 if (Value
< long.MinValue
|| Value
> long.MaxValue
|| double.IsNaN (Value
))
1688 throw new OverflowException ();
1690 return new LongConstant ((long) Value
, Location
);
1692 if (target_type
== TypeManager
.uint64_type
) {
1693 if (in_checked_context
){
1694 if (Value
< ulong.MinValue
|| Value
> ulong.MaxValue
|| double.IsNaN (Value
))
1695 throw new OverflowException ();
1697 return new ULongConstant ((ulong) Value
, Location
);
1699 if (target_type
== TypeManager
.float_type
)
1700 return new FloatConstant ((float) Value
, Location
);
1701 if (target_type
== TypeManager
.char_type
) {
1702 if (in_checked_context
){
1703 if (Value
< (double) char.MinValue
|| Value
> (double) char.MaxValue
|| double.IsNaN (Value
))
1704 throw new OverflowException ();
1706 return new CharConstant ((char) Value
, Location
);
1708 if (target_type
== TypeManager
.decimal_type
)
1709 return new DecimalConstant ((decimal) Value
, Location
);
1716 public class DecimalConstant
: Constant
{
1717 public readonly decimal Value
;
1719 public DecimalConstant (decimal d
, Location loc
):
1725 override public string AsString ()
1727 return Value
.ToString () + "M";
1730 protected override Expression
DoResolve (ResolveContext rc
)
1732 type
= TypeManager
.decimal_type
;
1733 eclass
= ExprClass
.Value
;
1737 public override object GetValue ()
1739 return (object) Value
;
1742 public override void Emit (EmitContext ec
)
1744 ILGenerator ig
= ec
.ig
;
1746 int [] words
= decimal.GetBits (Value
);
1747 int power
= (words
[3] >> 16) & 0xff;
1750 if (Value
<= int.MaxValue
&& Value
>= int.MinValue
) {
1751 if (TypeManager
.void_decimal_ctor_int_arg
== null) {
1752 TypeManager
.void_decimal_ctor_int_arg
= TypeManager
.GetPredefinedConstructor (
1753 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
);
1755 if (TypeManager
.void_decimal_ctor_int_arg
== null)
1759 IntConstant
.EmitInt (ig
, (int) Value
);
1760 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_int_arg
);
1764 if (Value
<= long.MaxValue
&& Value
>= long.MinValue
) {
1765 if (TypeManager
.void_decimal_ctor_long_arg
== null) {
1766 TypeManager
.void_decimal_ctor_long_arg
= TypeManager
.GetPredefinedConstructor (
1767 TypeManager
.decimal_type
, loc
, TypeManager
.int64_type
);
1769 if (TypeManager
.void_decimal_ctor_long_arg
== null)
1773 LongConstant
.EmitLong (ig
, (long) Value
);
1774 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_long_arg
);
1779 IntConstant
.EmitInt (ig
, words
[0]);
1780 IntConstant
.EmitInt (ig
, words
[1]);
1781 IntConstant
.EmitInt (ig
, words
[2]);
1784 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1787 IntConstant
.EmitInt (ig
, power
);
1789 if (TypeManager
.void_decimal_ctor_five_args
== null) {
1790 TypeManager
.void_decimal_ctor_five_args
= TypeManager
.GetPredefinedConstructor (
1791 TypeManager
.decimal_type
, loc
, TypeManager
.int32_type
, TypeManager
.int32_type
,
1792 TypeManager
.int32_type
, TypeManager
.bool_type
, TypeManager
.byte_type
);
1794 if (TypeManager
.void_decimal_ctor_five_args
== null)
1798 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1801 public override bool IsDefaultValue
{
1807 public override bool IsNegative
{
1813 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1815 if (target_type
== TypeManager
.sbyte_type
)
1816 return new SByteConstant ((sbyte)Value
, loc
);
1817 if (target_type
== TypeManager
.byte_type
)
1818 return new ByteConstant ((byte)Value
, loc
);
1819 if (target_type
== TypeManager
.short_type
)
1820 return new ShortConstant ((short)Value
, loc
);
1821 if (target_type
== TypeManager
.ushort_type
)
1822 return new UShortConstant ((ushort)Value
, loc
);
1823 if (target_type
== TypeManager
.int32_type
)
1824 return new IntConstant ((int)Value
, loc
);
1825 if (target_type
== TypeManager
.uint32_type
)
1826 return new UIntConstant ((uint)Value
, loc
);
1827 if (target_type
== TypeManager
.int64_type
)
1828 return new LongConstant ((long)Value
, loc
);
1829 if (target_type
== TypeManager
.uint64_type
)
1830 return new ULongConstant ((ulong)Value
, loc
);
1831 if (target_type
== TypeManager
.char_type
)
1832 return new CharConstant ((char)Value
, loc
);
1833 if (target_type
== TypeManager
.float_type
)
1834 return new FloatConstant ((float)Value
, loc
);
1835 if (target_type
== TypeManager
.double_type
)
1836 return new DoubleConstant ((double)Value
, loc
);
1843 public class StringConstant
: Constant
{
1844 public readonly string Value
;
1846 public StringConstant (string s
, Location loc
):
1852 // FIXME: Escape the string.
1853 override public string AsString ()
1855 return "\"" + Value
+ "\"";
1858 protected override Expression
DoResolve (ResolveContext rc
)
1860 type
= TypeManager
.string_type
;
1861 eclass
= ExprClass
.Value
;
1865 public override object GetValue ()
1870 public override void Emit (EmitContext ec
)
1872 if (Value
== null) {
1873 ec
.ig
.Emit (OpCodes
.Ldnull
);
1878 // Use string.Empty for both literals and constants even if
1879 // it's not allowed at language level
1881 if (Value
.Length
== 0 && RootContext
.Optimize
&& !TypeManager
.IsEqual (ec
.CurrentType
, TypeManager
.string_type
)) {
1882 if (TypeManager
.string_empty
== null)
1883 TypeManager
.string_empty
= TypeManager
.GetPredefinedField (TypeManager
.string_type
, "Empty", loc
);
1885 if (TypeManager
.string_empty
!= null) {
1886 ec
.ig
.Emit (OpCodes
.Ldsfld
, TypeManager
.string_empty
);
1891 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1894 public override bool IsDefaultValue
{
1896 return Value
== null;
1900 public override bool IsNegative
{
1906 public override bool IsNull
{
1908 return IsDefaultValue
;
1912 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
1919 // Null constant can have its own type, think of `default (Foo)'
1921 public class NullConstant
: Constant
1923 public NullConstant (Type type
, Location loc
)
1926 eclass
= ExprClass
.Value
;
1930 public override string AsString ()
1932 return GetSignatureForError ();
1935 protected override Expression
DoResolve (ResolveContext ec
)
1940 public override void Emit (EmitContext ec
)
1942 ec
.ig
.Emit (OpCodes
.Ldnull
);
1944 // Only to make verifier happy
1945 if (TypeManager
.IsGenericParameter (type
))
1946 ec
.ig
.Emit (OpCodes
.Unbox_Any
, type
);
1949 public override string ExprClassName
{
1951 return GetSignatureForError ();
1955 public override string GetSignatureForError ()
1960 public override Constant
ConvertExplicitly (bool inCheckedContext
, Type targetType
)
1962 if (targetType
.IsPointer
) {
1963 if (IsLiteral
|| this is NullPointer
)
1964 return new EmptyConstantCast (new NullPointer (loc
), targetType
);
1969 // Exlude internal compiler types
1970 if (targetType
== InternalType
.AnonymousMethod
)
1973 if (!IsLiteral
&& !Convert
.ImplicitStandardConversionExists (this, targetType
))
1976 if (TypeManager
.IsReferenceType (targetType
))
1977 return new NullConstant (targetType
, loc
);
1979 if (TypeManager
.IsNullableType (targetType
))
1980 return Nullable
.LiftedNull
.Create (targetType
, loc
);
1985 public override Constant
ConvertImplicitly (ResolveContext rc
, Type targetType
)
1987 return ConvertExplicitly (false, targetType
);
1990 public override object GetValue ()
1995 public override bool IsDefaultValue
{
1996 get { return true; }
1999 public override bool IsNegative
{
2000 get { return false; }
2003 public override bool IsNull
{
2004 get { return true; }
2007 public override bool IsZeroInteger
{
2008 get { return true; }
2011 public override void MutateHoistedGenericType (AnonymousMethodStorey storey
)
2013 type
= storey
.MutateType (type
);
2018 /// The value is constant, but when emitted has a side effect. This is
2019 /// used by BitwiseAnd to ensure that the second expression is invoked
2020 /// regardless of the value of the left side.
2022 public class SideEffectConstant
: Constant
{
2023 public Constant
value;
2024 Expression side_effect
;
2026 public SideEffectConstant (Constant
value, Expression side_effect
, Location loc
) : base (loc
)
2029 while (side_effect
is SideEffectConstant
)
2030 side_effect
= ((SideEffectConstant
) side_effect
).side_effect
;
2031 this.side_effect
= side_effect
;
2034 public override string AsString ()
2036 return value.AsString ();
2039 protected override Expression
DoResolve (ResolveContext rc
)
2041 value = value.Resolve (rc
);
2044 eclass
= ExprClass
.Value
;
2048 public override object GetValue ()
2050 return value.GetValue ();
2053 public override void Emit (EmitContext ec
)
2055 side_effect
.EmitSideEffect (ec
);
2059 public override void EmitSideEffect (EmitContext ec
)
2061 side_effect
.EmitSideEffect (ec
);
2062 value.EmitSideEffect (ec
);
2065 public override bool IsDefaultValue
{
2066 get { return value.IsDefaultValue; }
2069 public override bool IsNegative
{
2070 get { return value.IsNegative; }
2073 public override bool IsZeroInteger
{
2074 get { return value.IsZeroInteger; }
2077 public override Constant
ConvertExplicitly (bool in_checked_context
, Type target_type
)
2079 Constant new_value
= value.ConvertExplicitly (in_checked_context
, target_type
);
2080 return new_value
== null ? null : new SideEffectConstant (new_value
, side_effect
, new_value
.Location
);