2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2001 Ximian, Inc.
12 namespace Mono.CSharp {
15 using System.Reflection.Emit;
18 /// Base class for constants and literals.
20 public abstract class Constant : Expression {
22 protected Constant (Location loc)
28 /// This is different from ToString in that ToString
29 /// is supposed to be there for debugging purposes,
30 /// and is not guaranteed to be useful for anything else,
31 /// AsString() will provide something that can be used
32 /// for round-tripping C# code. Maybe it can be used
33 /// for IL assembly as well.
35 public abstract string AsString ();
37 override public string ToString ()
39 return this.GetType ().Name + " (" + AsString () + ")";
42 public override bool GetAttributableValue (Type value_type, out object value)
44 if (value_type == TypeManager.object_type) {
45 value = GetTypedValue ();
49 Constant c = ImplicitConversionRequired (value_type, loc);
55 value = c.GetTypedValue ();
60 /// This is used to obtain the actual value of the literal
61 /// cast into an object.
63 public abstract object GetValue ();
65 public virtual object GetTypedValue ()
71 /// Constants are always born in a fully resolved state
73 public override Expression DoResolve (EmitContext ec)
78 public Constant ImplicitConversionRequired (Type type, Location loc)
80 Constant c = ConvertImplicitly (type);
82 Error_ValueCannotBeConverted (null, loc, type, false);
86 public virtual Constant ConvertImplicitly (Type type)
88 if (this.type == type)
91 if (Convert.ImplicitNumericConversion (this, type) == null)
95 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
98 // We should always catch the error before this is ever
99 // reached, by calling Convert.ImplicitStandardConversionExists
101 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
102 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
105 return CreateConstant (type, constant_value, loc);
108 /// Returns a constant instance based on Type
109 /// The returned value is already resolved.
110 public static Constant CreateConstant (Type t, object v, Location loc)
112 if (t == TypeManager.int32_type)
113 return new IntConstant ((int) v, loc);
114 if (t == TypeManager.string_type)
115 return new StringConstant ((string) v, loc);
116 if (t == TypeManager.uint32_type)
117 return new UIntConstant ((uint) v, loc);
118 if (t == TypeManager.int64_type)
119 return new LongConstant ((long) v, loc);
120 if (t == TypeManager.uint64_type)
121 return new ULongConstant ((ulong) v, loc);
122 if (t == TypeManager.float_type)
123 return new FloatConstant ((float) v, loc);
124 if (t == TypeManager.double_type)
125 return new DoubleConstant ((double) v, loc);
126 if (t == TypeManager.short_type)
127 return new ShortConstant ((short)v, loc);
128 if (t == TypeManager.ushort_type)
129 return new UShortConstant ((ushort)v, loc);
130 if (t == TypeManager.sbyte_type)
131 return new SByteConstant ((sbyte)v, loc);
132 if (t == TypeManager.byte_type)
133 return new ByteConstant ((byte)v, loc);
134 if (t == TypeManager.char_type)
135 return new CharConstant ((char)v, loc);
136 if (t == TypeManager.bool_type)
137 return new BoolConstant ((bool) v, loc);
138 if (t == TypeManager.decimal_type)
139 return new DecimalConstant ((decimal) v, loc);
140 if (TypeManager.IsEnumType (t)) {
141 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
143 real_type = System.Enum.GetUnderlyingType (real_type);
144 return new EnumConstant (CreateConstant (real_type, v, loc), t);
146 if (v == null && !TypeManager.IsValueType (t))
147 return new EmptyConstantCast (new NullConstant (loc), t);
149 throw new Exception ("Unknown type for constant (" + t +
153 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
154 /// It throws OverflowException
156 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
157 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
160 /// Attempts to do a compile-time folding of a constant cast.
162 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
165 return TryReduce (ec, target_type);
167 catch (OverflowException) {
168 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
169 GetValue ().ToString (), TypeManager.CSharpName (target_type));
174 Constant TryReduce (EmitContext ec, Type target_type)
176 if (Type == target_type)
179 if (TypeManager.IsEnumType (target_type)) {
180 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
184 return new EnumConstant (c, target_type);
187 return ConvertExplicitly (ec.ConstantCheckState, target_type);
190 public abstract Constant Increment ();
193 /// Need to pass type as the constant can require a boxing
194 /// and in such case no optimization is possible
196 public bool IsDefaultInitializer (Type type)
199 return IsDefaultValue;
201 return Type == TypeManager.null_type;
204 public abstract bool IsDefaultValue {
208 public abstract bool IsNegative {
213 // Returns true iff 1) the stack type of this is one of Object,
214 // int32, int64 and 2) this == 0 or this == null.
216 public virtual bool IsZeroInteger {
217 get { return false; }
220 protected override void CloneTo (CloneContext clonectx, Expression target)
222 // CloneTo: Nothing, we do not keep any state on this expression
226 public abstract class IntegralConstant : Constant {
227 protected IntegralConstant (Location loc) :
232 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
235 ConvertExplicitly (true, target);
236 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
240 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
241 GetValue ().ToString (), TypeManager.CSharpName (target));
246 public class BoolConstant : Constant {
247 public readonly bool Value;
249 public BoolConstant (bool val, Location loc):
252 type = TypeManager.bool_type;
253 eclass = ExprClass.Value;
258 override public string AsString ()
260 return Value ? "true" : "false";
263 public override object GetValue ()
265 return (object) Value;
269 public override void Emit (EmitContext ec)
272 ec.ig.Emit (OpCodes.Ldc_I4_1);
274 ec.ig.Emit (OpCodes.Ldc_I4_0);
277 public override Constant Increment ()
279 throw new NotSupportedException ();
282 public override bool IsDefaultValue {
288 public override bool IsNegative {
294 public override bool IsZeroInteger {
295 get { return Value == false; }
298 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
305 public class ByteConstant : IntegralConstant {
306 public readonly byte Value;
308 public ByteConstant (byte v, Location loc):
311 type = TypeManager.byte_type;
312 eclass = ExprClass.Value;
316 public override void Emit (EmitContext ec)
318 IntLiteral.EmitInt (ec.ig, Value);
321 public override string AsString ()
323 return Value.ToString ();
326 public override object GetValue ()
331 public override Constant Increment ()
333 return new ByteConstant (checked ((byte)(Value + 1)), loc);
336 public override bool IsDefaultValue {
342 public override bool IsNegative {
348 public override bool IsZeroInteger {
349 get { return Value == 0; }
352 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
354 if (target_type == TypeManager.sbyte_type) {
355 if (in_checked_context){
356 if (Value > SByte.MaxValue)
357 throw new OverflowException ();
359 return new SByteConstant ((sbyte) Value, Location);
361 if (target_type == TypeManager.short_type)
362 return new ShortConstant ((short) Value, Location);
363 if (target_type == TypeManager.ushort_type)
364 return new UShortConstant ((ushort) Value, Location);
365 if (target_type == TypeManager.int32_type)
366 return new IntConstant ((int) Value, Location);
367 if (target_type == TypeManager.uint32_type)
368 return new UIntConstant ((uint) Value, Location);
369 if (target_type == TypeManager.int64_type)
370 return new LongConstant ((long) Value, Location);
371 if (target_type == TypeManager.uint64_type)
372 return new ULongConstant ((ulong) Value, Location);
373 if (target_type == TypeManager.float_type)
374 return new FloatConstant ((float) Value, Location);
375 if (target_type == TypeManager.double_type)
376 return new DoubleConstant ((double) Value, Location);
377 if (target_type == TypeManager.char_type)
378 return new CharConstant ((char) Value, Location);
379 if (target_type == TypeManager.decimal_type)
380 return new DecimalConstant ((decimal) Value, Location);
387 public class CharConstant : Constant {
388 public readonly char Value;
390 public CharConstant (char v, Location loc):
393 type = TypeManager.char_type;
394 eclass = ExprClass.Value;
398 public override void Emit (EmitContext ec)
400 IntLiteral.EmitInt (ec.ig, Value);
403 static public string descape (char c)
429 return c.ToString ();
432 public override string AsString ()
434 return "\"" + descape (Value) + "\"";
437 public override object GetValue ()
442 public override Constant Increment ()
444 return new CharConstant (checked ((char)(Value + 1)), loc);
447 public override bool IsDefaultValue {
453 public override bool IsNegative {
459 public override bool IsZeroInteger {
460 get { return Value == '\0'; }
463 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
465 if (target_type == TypeManager.byte_type) {
466 if (in_checked_context){
467 if (Value < Byte.MinValue || Value > Byte.MaxValue)
468 throw new OverflowException ();
470 return new ByteConstant ((byte) Value, Location);
472 if (target_type == TypeManager.sbyte_type) {
473 if (in_checked_context){
474 if (Value > SByte.MaxValue)
475 throw new OverflowException ();
477 return new SByteConstant ((sbyte) Value, Location);
479 if (target_type == TypeManager.short_type) {
480 if (in_checked_context){
481 if (Value > Int16.MaxValue)
482 throw new OverflowException ();
484 return new ShortConstant ((short) Value, Location);
486 if (target_type == TypeManager.int32_type)
487 return new IntConstant ((int) Value, Location);
488 if (target_type == TypeManager.uint32_type)
489 return new UIntConstant ((uint) Value, Location);
490 if (target_type == TypeManager.int64_type)
491 return new LongConstant ((long) Value, Location);
492 if (target_type == TypeManager.uint64_type)
493 return new ULongConstant ((ulong) Value, Location);
494 if (target_type == TypeManager.float_type)
495 return new FloatConstant ((float) Value, Location);
496 if (target_type == TypeManager.double_type)
497 return new DoubleConstant ((double) Value, Location);
498 if (target_type == TypeManager.decimal_type)
499 return new DecimalConstant ((decimal) Value, Location);
506 public class SByteConstant : IntegralConstant {
507 public readonly sbyte Value;
509 public SByteConstant (sbyte v, Location loc):
512 type = TypeManager.sbyte_type;
513 eclass = ExprClass.Value;
517 public override void Emit (EmitContext ec)
519 IntLiteral.EmitInt (ec.ig, Value);
522 public override string AsString ()
524 return Value.ToString ();
527 public override object GetValue ()
532 public override Constant Increment ()
534 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
537 public override bool IsDefaultValue {
543 public override bool IsNegative {
549 public override bool IsZeroInteger {
550 get { return Value == 0; }
553 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
555 if (target_type == TypeManager.byte_type) {
556 if (in_checked_context && Value < 0)
557 throw new OverflowException ();
558 return new ByteConstant ((byte) Value, Location);
560 if (target_type == TypeManager.short_type)
561 return new ShortConstant ((short) Value, Location);
562 if (target_type == TypeManager.ushort_type) {
563 if (in_checked_context && Value < 0)
564 throw new OverflowException ();
565 return new UShortConstant ((ushort) Value, Location);
566 } if (target_type == TypeManager.int32_type)
567 return new IntConstant ((int) Value, Location);
568 if (target_type == TypeManager.uint32_type) {
569 if (in_checked_context && Value < 0)
570 throw new OverflowException ();
571 return new UIntConstant ((uint) Value, Location);
572 } if (target_type == TypeManager.int64_type)
573 return new LongConstant ((long) Value, Location);
574 if (target_type == TypeManager.uint64_type) {
575 if (in_checked_context && Value < 0)
576 throw new OverflowException ();
577 return new ULongConstant ((ulong) Value, Location);
579 if (target_type == TypeManager.float_type)
580 return new FloatConstant ((float) Value, Location);
581 if (target_type == TypeManager.double_type)
582 return new DoubleConstant ((double) Value, Location);
583 if (target_type == TypeManager.char_type) {
584 if (in_checked_context && Value < 0)
585 throw new OverflowException ();
586 return new CharConstant ((char) Value, Location);
588 if (target_type == TypeManager.decimal_type)
589 return new DecimalConstant ((decimal) Value, Location);
596 public class ShortConstant : IntegralConstant {
597 public readonly short Value;
599 public ShortConstant (short v, Location loc):
602 type = TypeManager.short_type;
603 eclass = ExprClass.Value;
607 public override void Emit (EmitContext ec)
609 IntLiteral.EmitInt (ec.ig, Value);
612 public override string AsString ()
614 return Value.ToString ();
617 public override object GetValue ()
622 public override Constant Increment ()
624 return new ShortConstant (checked((short)(Value + 1)), loc);
627 public override bool IsDefaultValue {
633 public override bool IsZeroInteger {
634 get { return Value == 0; }
637 public override bool IsNegative {
643 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
645 if (target_type == TypeManager.byte_type) {
646 if (in_checked_context){
647 if (Value < Byte.MinValue || Value > Byte.MaxValue)
648 throw new OverflowException ();
650 return new ByteConstant ((byte) Value, Location);
652 if (target_type == TypeManager.sbyte_type) {
653 if (in_checked_context){
654 if (Value < SByte.MinValue || Value > SByte.MaxValue)
655 throw new OverflowException ();
657 return new SByteConstant ((sbyte) Value, Location);
659 if (target_type == TypeManager.ushort_type) {
660 if (in_checked_context && Value < 0)
661 throw new OverflowException ();
663 return new UShortConstant ((ushort) Value, Location);
665 if (target_type == TypeManager.int32_type)
666 return new IntConstant ((int) Value, Location);
667 if (target_type == TypeManager.uint32_type) {
668 if (in_checked_context && Value < 0)
669 throw new OverflowException ();
670 return new UIntConstant ((uint) Value, Location);
672 if (target_type == TypeManager.int64_type)
673 return new LongConstant ((long) Value, Location);
674 if (target_type == TypeManager.uint64_type) {
675 if (in_checked_context && Value < 0)
676 throw new OverflowException ();
677 return new ULongConstant ((ulong) Value, Location);
679 if (target_type == TypeManager.float_type)
680 return new FloatConstant ((float) Value, Location);
681 if (target_type == TypeManager.double_type)
682 return new DoubleConstant ((double) Value, Location);
683 if (target_type == TypeManager.char_type) {
684 if (in_checked_context){
685 if (Value < Char.MinValue)
686 throw new OverflowException ();
688 return new CharConstant ((char) Value, Location);
690 if (target_type == TypeManager.decimal_type)
691 return new DecimalConstant ((decimal) Value, Location);
698 public class UShortConstant : IntegralConstant {
699 public readonly ushort Value;
701 public UShortConstant (ushort v, Location loc):
704 type = TypeManager.ushort_type;
705 eclass = ExprClass.Value;
709 public override void Emit (EmitContext ec)
711 IntLiteral.EmitInt (ec.ig, Value);
714 public override string AsString ()
716 return Value.ToString ();
719 public override object GetValue ()
724 public override Constant Increment ()
726 return new UShortConstant (checked((ushort)(Value + 1)), loc);
729 public override bool IsDefaultValue {
735 public override bool IsNegative {
741 public override bool IsZeroInteger {
742 get { return Value == 0; }
745 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
747 if (target_type == TypeManager.byte_type) {
748 if (in_checked_context){
749 if (Value > Byte.MaxValue)
750 throw new OverflowException ();
752 return new ByteConstant ((byte) Value, Location);
754 if (target_type == TypeManager.sbyte_type) {
755 if (in_checked_context){
756 if (Value > SByte.MaxValue)
757 throw new OverflowException ();
759 return new SByteConstant ((sbyte) Value, Location);
761 if (target_type == TypeManager.short_type) {
762 if (in_checked_context){
763 if (Value > Int16.MaxValue)
764 throw new OverflowException ();
766 return new ShortConstant ((short) Value, Location);
768 if (target_type == TypeManager.int32_type)
769 return new IntConstant ((int) Value, Location);
770 if (target_type == TypeManager.uint32_type)
771 return new UIntConstant ((uint) Value, Location);
772 if (target_type == TypeManager.int64_type)
773 return new LongConstant ((long) Value, Location);
774 if (target_type == TypeManager.uint64_type)
775 return new ULongConstant ((ulong) Value, Location);
776 if (target_type == TypeManager.float_type)
777 return new FloatConstant ((float) Value, Location);
778 if (target_type == TypeManager.double_type)
779 return new DoubleConstant ((double) Value, Location);
780 if (target_type == TypeManager.char_type) {
781 if (in_checked_context){
782 if (Value > Char.MaxValue)
783 throw new OverflowException ();
785 return new CharConstant ((char) Value, Location);
787 if (target_type == TypeManager.decimal_type)
788 return new DecimalConstant ((decimal) Value, Location);
794 public class IntConstant : IntegralConstant {
795 public readonly int Value;
797 public IntConstant (int v, Location loc):
800 type = TypeManager.int32_type;
801 eclass = ExprClass.Value;
805 static public void EmitInt (ILGenerator ig, int i)
809 ig.Emit (OpCodes.Ldc_I4_M1);
813 ig.Emit (OpCodes.Ldc_I4_0);
817 ig.Emit (OpCodes.Ldc_I4_1);
821 ig.Emit (OpCodes.Ldc_I4_2);
825 ig.Emit (OpCodes.Ldc_I4_3);
829 ig.Emit (OpCodes.Ldc_I4_4);
833 ig.Emit (OpCodes.Ldc_I4_5);
837 ig.Emit (OpCodes.Ldc_I4_6);
841 ig.Emit (OpCodes.Ldc_I4_7);
845 ig.Emit (OpCodes.Ldc_I4_8);
849 if (i >= -128 && i <= 127){
850 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
852 ig.Emit (OpCodes.Ldc_I4, i);
857 public override void Emit (EmitContext ec)
859 EmitInt (ec.ig, Value);
862 public override string AsString ()
864 return Value.ToString ();
867 public override object GetValue ()
872 public override Constant Increment ()
874 return new IntConstant (checked(Value + 1), loc);
877 public override bool IsDefaultValue {
883 public override bool IsNegative {
889 public override bool IsZeroInteger {
890 get { return Value == 0; }
893 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
895 if (target_type == TypeManager.byte_type) {
896 if (in_checked_context){
897 if (Value < Byte.MinValue || Value > Byte.MaxValue)
898 throw new OverflowException ();
900 return new ByteConstant ((byte) Value, Location);
902 if (target_type == TypeManager.sbyte_type) {
903 if (in_checked_context){
904 if (Value < SByte.MinValue || Value > SByte.MaxValue)
905 throw new OverflowException ();
907 return new SByteConstant ((sbyte) Value, Location);
909 if (target_type == TypeManager.short_type) {
910 if (in_checked_context){
911 if (Value < Int16.MinValue || Value > Int16.MaxValue)
912 throw new OverflowException ();
914 return new ShortConstant ((short) Value, Location);
916 if (target_type == TypeManager.ushort_type) {
917 if (in_checked_context){
918 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
919 throw new OverflowException ();
921 return new UShortConstant ((ushort) Value, Location);
923 if (target_type == TypeManager.uint32_type) {
924 if (in_checked_context){
925 if (Value < UInt32.MinValue)
926 throw new OverflowException ();
928 return new UIntConstant ((uint) Value, Location);
930 if (target_type == TypeManager.int64_type)
931 return new LongConstant ((long) Value, Location);
932 if (target_type == TypeManager.uint64_type) {
933 if (in_checked_context && Value < 0)
934 throw new OverflowException ();
935 return new ULongConstant ((ulong) Value, Location);
937 if (target_type == TypeManager.float_type)
938 return new FloatConstant ((float) Value, Location);
939 if (target_type == TypeManager.double_type)
940 return new DoubleConstant ((double) Value, Location);
941 if (target_type == TypeManager.char_type) {
942 if (in_checked_context){
943 if (Value < Char.MinValue || Value > Char.MaxValue)
944 throw new OverflowException ();
946 return new CharConstant ((char) Value, Location);
948 if (target_type == TypeManager.decimal_type)
949 return new DecimalConstant ((decimal) Value, Location);
954 public override Constant ConvertImplicitly (Type type)
956 if (this.type == type)
959 Constant c = TryImplicitIntConversion (type);
963 return base.ConvertImplicitly (type);
967 /// Attempts to perform an implicit constant conversion of the IntConstant
968 /// into a different data type using casts (See Implicit Constant
969 /// Expression Conversions)
971 Constant TryImplicitIntConversion (Type target_type)
973 if (target_type == TypeManager.sbyte_type) {
974 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
975 return new SByteConstant ((sbyte) Value, loc);
977 else if (target_type == TypeManager.byte_type) {
978 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
979 return new ByteConstant ((byte) Value, loc);
981 else if (target_type == TypeManager.short_type) {
982 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
983 return new ShortConstant ((short) Value, loc);
985 else if (target_type == TypeManager.ushort_type) {
986 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
987 return new UShortConstant ((ushort) Value, loc);
989 else if (target_type == TypeManager.uint32_type) {
991 return new UIntConstant ((uint) Value, loc);
993 else if (target_type == TypeManager.uint64_type) {
995 // we can optimize this case: a positive int32
996 // always fits on a uint64. But we need an opcode
1000 return new ULongConstant ((ulong) Value, loc);
1002 else if (target_type == TypeManager.double_type)
1003 return new DoubleConstant ((double) Value, loc);
1004 else if (target_type == TypeManager.float_type)
1005 return new FloatConstant ((float) Value, loc);
1011 public class UIntConstant : IntegralConstant {
1012 public readonly uint Value;
1014 public UIntConstant (uint v, Location loc):
1017 type = TypeManager.uint32_type;
1018 eclass = ExprClass.Value;
1022 public override void Emit (EmitContext ec)
1024 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1027 public override string AsString ()
1029 return Value.ToString ();
1032 public override object GetValue ()
1037 public override Constant Increment ()
1039 return new UIntConstant (checked(Value + 1), loc);
1042 public override bool IsDefaultValue {
1048 public override bool IsNegative {
1054 public override bool IsZeroInteger {
1055 get { return Value == 0; }
1058 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1060 if (target_type == TypeManager.byte_type) {
1061 if (in_checked_context){
1062 if (Value < Char.MinValue || Value > Char.MaxValue)
1063 throw new OverflowException ();
1065 return new ByteConstant ((byte) Value, Location);
1067 if (target_type == TypeManager.sbyte_type) {
1068 if (in_checked_context){
1069 if (Value > SByte.MaxValue)
1070 throw new OverflowException ();
1072 return new SByteConstant ((sbyte) Value, Location);
1074 if (target_type == TypeManager.short_type) {
1075 if (in_checked_context){
1076 if (Value > Int16.MaxValue)
1077 throw new OverflowException ();
1079 return new ShortConstant ((short) Value, Location);
1081 if (target_type == TypeManager.ushort_type) {
1082 if (in_checked_context){
1083 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1084 throw new OverflowException ();
1086 return new UShortConstant ((ushort) Value, Location);
1088 if (target_type == TypeManager.int32_type) {
1089 if (in_checked_context){
1090 if (Value > Int32.MaxValue)
1091 throw new OverflowException ();
1093 return new IntConstant ((int) Value, Location);
1095 if (target_type == TypeManager.int64_type)
1096 return new LongConstant ((long) Value, Location);
1097 if (target_type == TypeManager.uint64_type)
1098 return new ULongConstant ((ulong) Value, Location);
1099 if (target_type == TypeManager.float_type)
1100 return new FloatConstant ((float) Value, Location);
1101 if (target_type == TypeManager.double_type)
1102 return new DoubleConstant ((double) Value, Location);
1103 if (target_type == TypeManager.char_type) {
1104 if (in_checked_context){
1105 if (Value < Char.MinValue || Value > Char.MaxValue)
1106 throw new OverflowException ();
1108 return new CharConstant ((char) Value, Location);
1110 if (target_type == TypeManager.decimal_type)
1111 return new DecimalConstant ((decimal) Value, Location);
1118 public class LongConstant : IntegralConstant {
1119 public readonly long Value;
1121 public LongConstant (long v, Location loc):
1124 type = TypeManager.int64_type;
1125 eclass = ExprClass.Value;
1129 public override void Emit (EmitContext ec)
1131 EmitLong (ec.ig, Value);
1134 static public void EmitLong (ILGenerator ig, long l)
1136 if (l >= int.MinValue && l <= int.MaxValue) {
1137 IntLiteral.EmitInt (ig, unchecked ((int) l));
1138 ig.Emit (OpCodes.Conv_I8);
1141 ig.Emit (OpCodes.Ldc_I8, l);
1144 public override string AsString ()
1146 return Value.ToString ();
1149 public override object GetValue ()
1154 public override Constant Increment ()
1156 return new LongConstant (checked(Value + 1), loc);
1159 public override bool IsDefaultValue {
1165 public override bool IsNegative {
1171 public override bool IsZeroInteger {
1172 get { return Value == 0; }
1175 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1177 if (target_type == TypeManager.byte_type) {
1178 if (in_checked_context){
1179 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1180 throw new OverflowException ();
1182 return new ByteConstant ((byte) Value, Location);
1184 if (target_type == TypeManager.sbyte_type) {
1185 if (in_checked_context){
1186 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1187 throw new OverflowException ();
1189 return new SByteConstant ((sbyte) Value, Location);
1191 if (target_type == TypeManager.short_type) {
1192 if (in_checked_context){
1193 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1194 throw new OverflowException ();
1196 return new ShortConstant ((short) Value, Location);
1198 if (target_type == TypeManager.ushort_type) {
1199 if (in_checked_context){
1200 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1201 throw new OverflowException ();
1203 return new UShortConstant ((ushort) Value, Location);
1205 if (target_type == TypeManager.int32_type) {
1206 if (in_checked_context){
1207 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1208 throw new OverflowException ();
1210 return new IntConstant ((int) Value, Location);
1212 if (target_type == TypeManager.uint32_type) {
1213 if (in_checked_context){
1214 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1215 throw new OverflowException ();
1217 return new UIntConstant ((uint) Value, Location);
1219 if (target_type == TypeManager.uint64_type) {
1220 if (in_checked_context && Value < 0)
1221 throw new OverflowException ();
1222 return new ULongConstant ((ulong) Value, Location);
1224 if (target_type == TypeManager.float_type)
1225 return new FloatConstant ((float) Value, Location);
1226 if (target_type == TypeManager.double_type)
1227 return new DoubleConstant ((double) Value, Location);
1228 if (target_type == TypeManager.char_type) {
1229 if (in_checked_context){
1230 if (Value < Char.MinValue || Value > Char.MaxValue)
1231 throw new OverflowException ();
1233 return new CharConstant ((char) Value, Location);
1235 if (target_type == TypeManager.decimal_type)
1236 return new DecimalConstant ((decimal) Value, Location);
1241 public override Constant ConvertImplicitly (Type type)
1243 if (Value >= 0 && type == TypeManager.uint64_type) {
1244 return new ULongConstant ((ulong) Value, loc);
1247 return base.ConvertImplicitly (type);
1251 public class ULongConstant : IntegralConstant {
1252 public readonly ulong Value;
1254 public ULongConstant (ulong v, Location loc):
1257 type = TypeManager.uint64_type;
1258 eclass = ExprClass.Value;
1262 public override void Emit (EmitContext ec)
1264 ILGenerator ig = ec.ig;
1266 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1269 public override string AsString ()
1271 return Value.ToString ();
1274 public override object GetValue ()
1279 public override Constant Increment ()
1281 return new ULongConstant (checked(Value + 1), loc);
1284 public override bool IsDefaultValue {
1290 public override bool IsNegative {
1296 public override bool IsZeroInteger {
1297 get { return Value == 0; }
1300 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1302 if (target_type == TypeManager.byte_type) {
1303 if (in_checked_context && Value > Byte.MaxValue)
1304 throw new OverflowException ();
1305 return new ByteConstant ((byte) Value, Location);
1307 if (target_type == TypeManager.sbyte_type) {
1308 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1309 throw new OverflowException ();
1310 return new SByteConstant ((sbyte) Value, Location);
1312 if (target_type == TypeManager.short_type) {
1313 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1314 throw new OverflowException ();
1315 return new ShortConstant ((short) Value, Location);
1317 if (target_type == TypeManager.ushort_type) {
1318 if (in_checked_context && Value > UInt16.MaxValue)
1319 throw new OverflowException ();
1320 return new UShortConstant ((ushort) Value, Location);
1322 if (target_type == TypeManager.int32_type) {
1323 if (in_checked_context && Value > UInt32.MaxValue)
1324 throw new OverflowException ();
1325 return new IntConstant ((int) Value, Location);
1327 if (target_type == TypeManager.uint32_type) {
1328 if (in_checked_context && Value > UInt32.MaxValue)
1329 throw new OverflowException ();
1330 return new UIntConstant ((uint) Value, Location);
1332 if (target_type == TypeManager.int64_type) {
1333 if (in_checked_context && Value > Int64.MaxValue)
1334 throw new OverflowException ();
1335 return new LongConstant ((long) Value, Location);
1337 if (target_type == TypeManager.float_type)
1338 return new FloatConstant ((float) Value, Location);
1339 if (target_type == TypeManager.double_type)
1340 return new DoubleConstant ((double) Value, Location);
1341 if (target_type == TypeManager.char_type) {
1342 if (in_checked_context && Value > Char.MaxValue)
1343 throw new OverflowException ();
1344 return new CharConstant ((char) Value, Location);
1346 if (target_type == TypeManager.decimal_type)
1347 return new DecimalConstant ((decimal) Value, Location);
1354 public class FloatConstant : Constant {
1357 public FloatConstant (float v, Location loc):
1360 type = TypeManager.float_type;
1361 eclass = ExprClass.Value;
1365 public override void Emit (EmitContext ec)
1367 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1370 public override string AsString ()
1372 return Value.ToString ();
1375 public override object GetValue ()
1380 public override Constant Increment ()
1382 return new FloatConstant (checked(Value + 1), loc);
1385 public override bool IsDefaultValue {
1391 public override bool IsNegative {
1397 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1399 if (target_type == TypeManager.byte_type) {
1400 if (in_checked_context){
1401 if (Value < byte.MinValue || Value > byte.MaxValue)
1402 throw new OverflowException ();
1404 return new ByteConstant ((byte) Value, Location);
1406 if (target_type == TypeManager.sbyte_type) {
1407 if (in_checked_context){
1408 if (Value < sbyte.MinValue || Value > sbyte.MaxValue)
1409 throw new OverflowException ();
1411 return new SByteConstant ((sbyte) Value, Location);
1413 if (target_type == TypeManager.short_type) {
1414 if (in_checked_context){
1415 if (Value < short.MinValue || Value > short.MaxValue)
1416 throw new OverflowException ();
1418 return new ShortConstant ((short) Value, Location);
1420 if (target_type == TypeManager.ushort_type) {
1421 if (in_checked_context){
1422 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1423 throw new OverflowException ();
1425 return new UShortConstant ((ushort) Value, Location);
1427 if (target_type == TypeManager.int32_type) {
1428 if (in_checked_context){
1429 if (Value < int.MinValue || Value > int.MaxValue)
1430 throw new OverflowException ();
1432 return new IntConstant ((int) Value, Location);
1434 if (target_type == TypeManager.uint32_type) {
1435 if (in_checked_context){
1436 if (Value < uint.MinValue || Value > uint.MaxValue)
1437 throw new OverflowException ();
1439 return new UIntConstant ((uint) Value, Location);
1441 if (target_type == TypeManager.int64_type) {
1442 if (in_checked_context){
1443 if (Value < long.MinValue || Value > long.MaxValue)
1444 throw new OverflowException ();
1446 return new LongConstant ((long) Value, Location);
1448 if (target_type == TypeManager.uint64_type) {
1449 if (in_checked_context){
1450 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1451 throw new OverflowException ();
1453 return new ULongConstant ((ulong) Value, Location);
1455 if (target_type == TypeManager.double_type)
1456 return new DoubleConstant ((double) Value, Location);
1457 if (target_type == TypeManager.char_type) {
1458 if (in_checked_context){
1459 if (Value < (float) char.MinValue || Value > (float) char.MaxValue)
1460 throw new OverflowException ();
1462 return new CharConstant ((char) Value, Location);
1464 if (target_type == TypeManager.decimal_type)
1465 return new DecimalConstant ((decimal) Value, Location);
1472 public class DoubleConstant : Constant {
1473 public double Value;
1475 public DoubleConstant (double v, Location loc):
1478 type = TypeManager.double_type;
1479 eclass = ExprClass.Value;
1483 public override void Emit (EmitContext ec)
1485 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1488 public override string AsString ()
1490 return Value.ToString ();
1493 public override object GetValue ()
1498 public override Constant Increment ()
1500 return new DoubleConstant (checked(Value + 1), loc);
1503 public override bool IsDefaultValue {
1509 public override bool IsNegative {
1515 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1517 if (target_type == TypeManager.byte_type) {
1518 if (in_checked_context){
1519 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1520 throw new OverflowException ();
1522 return new ByteConstant ((byte) Value, Location);
1524 if (target_type == TypeManager.sbyte_type) {
1525 if (in_checked_context){
1526 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1527 throw new OverflowException ();
1529 return new SByteConstant ((sbyte) Value, Location);
1531 if (target_type == TypeManager.short_type) {
1532 if (in_checked_context){
1533 if (Value < short.MinValue || Value > short.MaxValue)
1534 throw new OverflowException ();
1536 return new ShortConstant ((short) Value, Location);
1538 if (target_type == TypeManager.ushort_type) {
1539 if (in_checked_context){
1540 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1541 throw new OverflowException ();
1543 return new UShortConstant ((ushort) Value, Location);
1545 if (target_type == TypeManager.int32_type) {
1546 if (in_checked_context){
1547 if (Value < int.MinValue || Value > int.MaxValue)
1548 throw new OverflowException ();
1550 return new IntConstant ((int) Value, Location);
1552 if (target_type == TypeManager.uint32_type) {
1553 if (in_checked_context){
1554 if (Value < uint.MinValue || Value > uint.MaxValue)
1555 throw new OverflowException ();
1557 return new UIntConstant ((uint) Value, Location);
1559 if (target_type == TypeManager.int64_type) {
1560 if (in_checked_context){
1561 if (Value < long.MinValue || Value > long.MaxValue)
1562 throw new OverflowException ();
1564 return new LongConstant ((long) Value, Location);
1566 if (target_type == TypeManager.uint64_type) {
1567 if (in_checked_context){
1568 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1569 throw new OverflowException ();
1571 return new ULongConstant ((ulong) Value, Location);
1573 if (target_type == TypeManager.float_type)
1574 return new FloatConstant ((float) Value, Location);
1575 if (target_type == TypeManager.char_type) {
1576 if (in_checked_context){
1577 if (Value < (double) char.MinValue || Value > (double) char.MaxValue)
1578 throw new OverflowException ();
1580 return new CharConstant ((char) Value, Location);
1582 if (target_type == TypeManager.decimal_type)
1583 return new DecimalConstant ((decimal) Value, Location);
1590 public class DecimalConstant : Constant {
1591 public readonly decimal Value;
1593 public DecimalConstant (decimal d, Location loc):
1596 type = TypeManager.decimal_type;
1597 eclass = ExprClass.Value;
1601 override public string AsString ()
1603 return Value.ToString ();
1606 public override object GetValue ()
1608 return (object) Value;
1611 public override void Emit (EmitContext ec)
1613 ILGenerator ig = ec.ig;
1615 int [] words = Decimal.GetBits (Value);
1616 int power = (words [3] >> 16) & 0xff;
1618 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1620 IntConstant.EmitInt (ig, (int)Value);
1621 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1627 // FIXME: we could optimize this, and call a better
1631 IntConstant.EmitInt (ig, words [0]);
1632 IntConstant.EmitInt (ig, words [1]);
1633 IntConstant.EmitInt (ig, words [2]);
1636 IntConstant.EmitInt (ig, words [3] >> 31);
1639 IntConstant.EmitInt (ig, power);
1641 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1644 public override Constant Increment ()
1646 return new DecimalConstant (checked (Value + 1), loc);
1649 public override bool IsDefaultValue {
1655 public override bool IsNegative {
1661 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1663 if (target_type == TypeManager.sbyte_type)
1664 return new SByteConstant ((sbyte)Value, loc);
1665 if (target_type == TypeManager.byte_type)
1666 return new ByteConstant ((byte)Value, loc);
1667 if (target_type == TypeManager.short_type)
1668 return new ShortConstant ((short)Value, loc);
1669 if (target_type == TypeManager.ushort_type)
1670 return new UShortConstant ((ushort)Value, loc);
1671 if (target_type == TypeManager.int32_type)
1672 return new IntConstant ((int)Value, loc);
1673 if (target_type == TypeManager.uint32_type)
1674 return new UIntConstant ((uint)Value, loc);
1675 if (target_type == TypeManager.int64_type)
1676 return new LongConstant ((long)Value, loc);
1677 if (target_type == TypeManager.uint64_type)
1678 return new ULongConstant ((ulong)Value, loc);
1679 if (target_type == TypeManager.char_type)
1680 return new CharConstant ((char)Value, loc);
1681 if (target_type == TypeManager.float_type)
1682 return new FloatConstant ((float)Value, loc);
1683 if (target_type == TypeManager.double_type)
1684 return new DoubleConstant ((double)Value, loc);
1691 public class StringConstant : Constant {
1692 public readonly string Value;
1694 public StringConstant (string s, Location loc):
1697 type = TypeManager.string_type;
1698 eclass = ExprClass.Value;
1702 // FIXME: Escape the string.
1703 override public string AsString ()
1705 return "\"" + Value + "\"";
1708 public override object GetValue ()
1713 public override void Emit (EmitContext ec)
1716 ec.ig.Emit (OpCodes.Ldnull);
1718 ec.ig.Emit (OpCodes.Ldstr, Value);
1721 public override Constant Increment ()
1723 throw new NotSupportedException ();
1726 public override bool IsDefaultValue {
1728 return Value == null;
1732 public override bool IsNegative {
1738 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)