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 valueType, out object value)
44 Constant c = ImplicitConversionRequired (valueType, loc);
50 value = c.GetTypedValue ();
55 /// This is used to obtain the actual value of the literal
56 /// cast into an object.
58 public abstract object GetValue ();
60 public virtual object GetTypedValue ()
66 /// Constants are always born in a fully resolved state
68 public override Expression DoResolve (EmitContext ec)
73 public Constant ImplicitConversionRequired (Type type, Location loc)
75 Constant c = ToType (type);
77 Error_ValueCannotBeConverted (loc, type, false);
82 // The various ToXXXX conversion functions are used by the constant
83 // folding evaluator. A null value is returned if the conversion is
86 // Note: not all the patterns for catching `implicit_conv' are the same.
87 // some implicit conversions can never be performed between two types
88 // even if the conversion would be lossless (for example short to uint),
89 // but some conversions are explicitly permitted by the standard provided
90 // that there will be no loss of information (for example, int to uint).
92 public DoubleConstant ToDouble (Location loc)
94 DoubleConstant c = ConvertToDouble ();
97 Error_ValueCannotBeConverted (loc, TypeManager.double_type, false);
102 public FloatConstant ToFloat (Location loc)
104 FloatConstant c = ConvertToFloat ();
107 Error_ValueCannotBeConverted (loc, TypeManager.float_type, false);
112 public ULongConstant ToULong (Location loc)
114 ULongConstant c = ConvertToULong ();
117 Error_ValueCannotBeConverted (loc, TypeManager.uint64_type, false);
122 public LongConstant ToLong (Location loc)
124 LongConstant c = ConvertToLong ();
127 Error_ValueCannotBeConverted (loc, TypeManager.int64_type, false);
132 public UIntConstant ToUInt (Location loc)
134 UIntConstant c = ConvertToUInt ();
137 Error_ValueCannotBeConverted (loc, TypeManager.uint32_type, false);
142 public IntConstant ToInt (Location loc)
144 IntConstant c = ConvertToInt ();
147 Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
152 public DecimalConstant ToDecimal (Location loc)
154 DecimalConstant c = ConvertToDecimal ();
157 Error_ValueCannotBeConverted (loc, TypeManager.decimal_type, false);
162 public virtual Constant ToType (Type type)
167 if (type == TypeManager.object_type)
170 if (!Convert.ImplicitStandardConversionExists (this, type)){
174 // Special-case: The 0 literal can be converted to an enum value,
175 // and ImplicitStandardConversionExists will return true in that case.
176 if (IsZeroInteger && Type == TypeManager.int32_type && TypeManager.IsEnumType (type)) {
177 return new EnumConstant (this, type);
181 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
184 // We should always catch the error before this is ever
185 // reached, by calling Convert.ImplicitStandardConversionExists
187 throw new Exception (
188 String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
191 return CreateConstant (type, constant_value, loc);
194 /// Returns a constant instance based on Type
195 /// The returned value is already resolved.
196 public static Constant CreateConstant (Type t, object v, Location loc)
198 if (t == TypeManager.int32_type)
199 return new IntConstant ((int) v, loc);
200 if (t == TypeManager.string_type)
201 return new StringConstant ((string) v, loc);
202 if (t == TypeManager.uint32_type)
203 return new UIntConstant ((uint) v, loc);
204 if (t == TypeManager.int64_type)
205 return new LongConstant ((long) v, loc);
206 if (t == TypeManager.uint64_type)
207 return new ULongConstant ((ulong) v, loc);
208 if (t == TypeManager.float_type)
209 return new FloatConstant ((float) v, loc);
210 if (t == TypeManager.double_type)
211 return new DoubleConstant ((double) v, loc);
212 if (t == TypeManager.short_type)
213 return new ShortConstant ((short)v, loc);
214 if (t == TypeManager.ushort_type)
215 return new UShortConstant ((ushort)v, loc);
216 if (t == TypeManager.sbyte_type)
217 return new SByteConstant ((sbyte)v, loc);
218 if (t == TypeManager.byte_type)
219 return new ByteConstant ((byte)v, loc);
220 if (t == TypeManager.char_type)
221 return new CharConstant ((char)v, loc);
222 if (t == TypeManager.bool_type)
223 return new BoolConstant ((bool) v, loc);
224 if (t == TypeManager.decimal_type)
225 return new DecimalConstant ((decimal) v, loc);
226 if (TypeManager.IsEnumType (t)) {
227 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
229 real_type = System.Enum.GetUnderlyingType (real_type);
230 return new EnumConstant (CreateConstant (real_type, v, loc), t);
232 if (v == null && !TypeManager.IsValueType (t))
233 return new EmptyConstantCast (new NullConstant (loc), t);
235 throw new Exception ("Unknown type for constant (" + t +
239 protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
241 if (!inCheckedContext)
245 throw new OverflowException ();
248 protected static void CheckRange (bool inCheckedContext, double value, long min, long max)
250 if (!inCheckedContext)
253 if (((value < min) || (value > max)))
254 throw new OverflowException ();
256 if (double.IsNaN (value))
257 throw new OverflowException ();
260 protected static void CheckRange (bool inCheckedContext, double value, ulong min, ulong max)
262 if (!inCheckedContext)
265 if (((value < min) || (value > max)))
266 throw new OverflowException ();
268 if (double.IsNaN (value))
269 throw new OverflowException ();
272 protected static void CheckUnsigned (bool inCheckedContext, long value)
274 if (!inCheckedContext)
278 throw new OverflowException ();
282 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
283 /// It throws OverflowException
285 public abstract Constant Reduce (bool inCheckedContext, Type target_type);
288 /// Attempts to do a compile-time folding of a constant cast.
290 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
293 return TryReduce (ec, target_type);
295 catch (OverflowException) {
296 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
297 GetValue ().ToString (), TypeManager.CSharpName (target_type));
302 Constant TryReduce (EmitContext ec, Type target_type)
304 if (Type == target_type)
307 if (TypeManager.IsEnumType (target_type)) {
308 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
312 return new EnumConstant (c, target_type);
315 return Reduce (ec.ConstantCheckState, target_type);
319 public virtual DecimalConstant ConvertToDecimal ()
324 public virtual DoubleConstant ConvertToDouble ()
329 public virtual FloatConstant ConvertToFloat ()
334 public virtual ULongConstant ConvertToULong ()
339 public virtual LongConstant ConvertToLong ()
344 public virtual UIntConstant ConvertToUInt ()
349 public virtual IntConstant ConvertToInt ()
354 public abstract Constant Increment ();
357 /// Need to pass type as the constant can require a boxing
358 /// and in such case no optimization is possible
360 public bool IsDefaultInitializer (Type type)
363 return IsDefaultValue;
365 return Type == TypeManager.null_type;
368 public abstract bool IsDefaultValue {
372 public abstract bool IsNegative {
377 // Returns true iff 1) the stack type of this is one of Object,
378 // int32, int64 and 2) this == 0 or this == null.
380 public virtual bool IsZeroInteger {
381 get { return false; }
385 public abstract class IntegralConstant : Constant {
386 protected IntegralConstant (Location loc) :
391 public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
394 Reduce (true, target);
395 base.Error_ValueCannotBeConverted (loc, target, expl);
399 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
400 GetValue ().ToString (), TypeManager.CSharpName (target));
405 public class BoolConstant : Constant {
406 public readonly bool Value;
408 public BoolConstant (bool val, Location loc):
411 type = TypeManager.bool_type;
412 eclass = ExprClass.Value;
417 override public string AsString ()
419 return Value ? "true" : "false";
422 public override object GetValue ()
424 return (object) Value;
428 public override void Emit (EmitContext ec)
431 ec.ig.Emit (OpCodes.Ldc_I4_1);
433 ec.ig.Emit (OpCodes.Ldc_I4_0);
436 public override Constant Increment ()
438 throw new NotSupportedException ();
441 public override bool IsDefaultValue {
447 public override bool IsNegative {
453 public override bool IsZeroInteger {
454 get { return Value == false; }
457 public override Constant Reduce (bool inCheckedContext, Type target_type)
464 public class ByteConstant : IntegralConstant {
465 public readonly byte Value;
467 public ByteConstant (byte v, Location loc):
470 type = TypeManager.byte_type;
471 eclass = ExprClass.Value;
475 public override void Emit (EmitContext ec)
477 IntLiteral.EmitInt (ec.ig, Value);
480 public override string AsString ()
482 return Value.ToString ();
485 public override object GetValue ()
490 public override DoubleConstant ConvertToDouble ()
492 return new DoubleConstant (Value, loc);
495 public override FloatConstant ConvertToFloat ()
497 return new FloatConstant (Value, loc);
500 public override ULongConstant ConvertToULong ()
502 return new ULongConstant (Value, loc);
505 public override LongConstant ConvertToLong ()
507 return new LongConstant (Value, loc);
510 public override UIntConstant ConvertToUInt ()
512 return new UIntConstant (Value, loc);
515 public override IntConstant ConvertToInt ()
517 return new IntConstant (Value, loc);
520 public override Constant Increment ()
522 return new ByteConstant (checked ((byte)(Value + 1)), loc);
525 public override bool IsDefaultValue {
531 public override bool IsNegative {
537 public override bool IsZeroInteger {
538 get { return Value == 0; }
541 public override Constant Reduce (bool inCheckedContext, Type target_type)
543 if (target_type == TypeManager.sbyte_type) {
544 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
545 return new SByteConstant ((sbyte) Value, Location);
547 if (target_type == TypeManager.short_type)
548 return new ShortConstant ((short) Value, Location);
549 if (target_type == TypeManager.ushort_type)
550 return new UShortConstant ((ushort) Value, Location);
551 if (target_type == TypeManager.int32_type)
552 return new IntConstant ((int) Value, Location);
553 if (target_type == TypeManager.uint32_type)
554 return new UIntConstant ((uint) Value, Location);
555 if (target_type == TypeManager.int64_type)
556 return new LongConstant ((long) Value, Location);
557 if (target_type == TypeManager.uint64_type)
558 return new ULongConstant ((ulong) Value, Location);
559 if (target_type == TypeManager.float_type)
560 return new FloatConstant ((float) Value, Location);
561 if (target_type == TypeManager.double_type)
562 return new DoubleConstant ((double) Value, Location);
563 if (target_type == TypeManager.char_type)
564 return new CharConstant ((char) Value, Location);
565 if (target_type == TypeManager.decimal_type)
566 return new DecimalConstant ((decimal) Value, Location);
573 public class CharConstant : Constant {
574 public readonly char Value;
576 public CharConstant (char v, Location loc):
579 type = TypeManager.char_type;
580 eclass = ExprClass.Value;
584 public override void Emit (EmitContext ec)
586 IntLiteral.EmitInt (ec.ig, Value);
589 static public string descape (char c)
615 return c.ToString ();
618 public override string AsString ()
620 return "\"" + descape (Value) + "\"";
623 public override object GetValue ()
628 public override DoubleConstant ConvertToDouble ()
630 return new DoubleConstant (Value, loc);
633 public override FloatConstant ConvertToFloat ()
635 return new FloatConstant (Value, loc);
638 public override ULongConstant ConvertToULong ()
640 return new ULongConstant (Value, loc);
643 public override LongConstant ConvertToLong ()
645 return new LongConstant (Value, loc);
648 public override UIntConstant ConvertToUInt ()
650 return new UIntConstant (Value, loc);
653 public override IntConstant ConvertToInt ()
655 return new IntConstant (Value, loc);
658 public override Constant Increment ()
660 return new CharConstant (checked ((char)(Value + 1)), loc);
663 public override bool IsDefaultValue {
669 public override bool IsNegative {
675 public override bool IsZeroInteger {
676 get { return Value == '\0'; }
679 public override Constant Reduce (bool inCheckedContext, Type target_type)
681 if (target_type == TypeManager.byte_type) {
682 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
683 return new ByteConstant ((byte) Value, Location);
685 if (target_type == TypeManager.sbyte_type) {
686 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
687 return new SByteConstant ((sbyte) Value, Location);
689 if (target_type == TypeManager.short_type) {
690 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
691 return new ShortConstant ((short) Value, Location);
693 if (target_type == TypeManager.int32_type)
694 return new IntConstant ((int) Value, Location);
695 if (target_type == TypeManager.uint32_type)
696 return new UIntConstant ((uint) Value, Location);
697 if (target_type == TypeManager.int64_type)
698 return new LongConstant ((long) Value, Location);
699 if (target_type == TypeManager.uint64_type)
700 return new ULongConstant ((ulong) Value, Location);
701 if (target_type == TypeManager.float_type)
702 return new FloatConstant ((float) Value, Location);
703 if (target_type == TypeManager.double_type)
704 return new DoubleConstant ((double) Value, Location);
705 if (target_type == TypeManager.decimal_type)
706 return new DecimalConstant ((decimal) Value, Location);
713 public class SByteConstant : IntegralConstant {
714 public readonly sbyte Value;
716 public SByteConstant (sbyte v, Location loc):
719 type = TypeManager.sbyte_type;
720 eclass = ExprClass.Value;
724 public override void Emit (EmitContext ec)
726 IntLiteral.EmitInt (ec.ig, Value);
729 public override string AsString ()
731 return Value.ToString ();
734 public override object GetValue ()
739 public override DoubleConstant ConvertToDouble ()
741 return new DoubleConstant (Value, loc);
744 public override FloatConstant ConvertToFloat ()
746 return new FloatConstant (Value, loc);
749 public override ULongConstant ConvertToULong ()
752 return new ULongConstant ((ulong) Value, loc);
757 public override LongConstant ConvertToLong ()
759 return new LongConstant (Value, loc);
762 public override UIntConstant ConvertToUInt ()
767 public override IntConstant ConvertToInt ()
769 return new IntConstant (Value, loc);
772 public override Constant Increment ()
774 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
777 public override bool IsDefaultValue {
783 public override bool IsNegative {
789 public override bool IsZeroInteger {
790 get { return Value == 0; }
793 public override Constant Reduce (bool inCheckedContext, Type target_type)
795 if (target_type == TypeManager.byte_type) {
796 CheckUnsigned (inCheckedContext, Value);
797 return new ByteConstant ((byte) Value, Location);
799 if (target_type == TypeManager.short_type)
800 return new ShortConstant ((short) Value, Location);
801 if (target_type == TypeManager.ushort_type) {
802 CheckUnsigned (inCheckedContext, Value);
803 return new UShortConstant ((ushort) Value, Location);
804 } if (target_type == TypeManager.int32_type)
805 return new IntConstant ((int) Value, Location);
806 if (target_type == TypeManager.uint32_type) {
807 CheckUnsigned (inCheckedContext, Value);
808 return new UIntConstant ((uint) Value, Location);
809 } if (target_type == TypeManager.int64_type)
810 return new LongConstant ((long) Value, Location);
811 if (target_type == TypeManager.uint64_type) {
812 CheckUnsigned (inCheckedContext, Value);
813 return new ULongConstant ((ulong) Value, Location);
815 if (target_type == TypeManager.float_type)
816 return new FloatConstant ((float) Value, Location);
817 if (target_type == TypeManager.double_type)
818 return new DoubleConstant ((double) Value, Location);
819 if (target_type == TypeManager.char_type) {
820 CheckUnsigned (inCheckedContext, Value);
821 return new CharConstant ((char) Value, Location);
823 if (target_type == TypeManager.decimal_type)
824 return new DecimalConstant ((decimal) Value, Location);
831 public class ShortConstant : IntegralConstant {
832 public readonly short Value;
834 public ShortConstant (short v, Location loc):
837 type = TypeManager.short_type;
838 eclass = ExprClass.Value;
842 public override void Emit (EmitContext ec)
844 IntLiteral.EmitInt (ec.ig, Value);
847 public override string AsString ()
849 return Value.ToString ();
852 public override object GetValue ()
857 public override DoubleConstant ConvertToDouble ()
859 return new DoubleConstant (Value, loc);
862 public override FloatConstant ConvertToFloat ()
864 return new FloatConstant (Value, loc);
867 public override ULongConstant ConvertToULong ()
872 public override LongConstant ConvertToLong ()
874 return new LongConstant (Value, loc);
877 public override UIntConstant ConvertToUInt ()
882 public override IntConstant ConvertToInt ()
884 return new IntConstant (Value, loc);
887 public override Constant Increment ()
889 return new ShortConstant (checked((short)(Value + 1)), loc);
892 public override bool IsDefaultValue {
898 public override bool IsZeroInteger {
899 get { return Value == 0; }
902 public override bool IsNegative {
908 public override Constant Reduce (bool inCheckedContext, Type target_type)
910 if (target_type == TypeManager.byte_type) {
911 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
912 return new ByteConstant ((byte) Value, Location);
914 if (target_type == TypeManager.sbyte_type) {
915 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
916 return new SByteConstant ((sbyte) Value, Location);
918 if (target_type == TypeManager.ushort_type) {
919 CheckUnsigned (inCheckedContext, Value);
920 return new UShortConstant ((ushort) Value, Location);
922 if (target_type == TypeManager.int32_type)
923 return new IntConstant ((int) Value, Location);
924 if (target_type == TypeManager.uint32_type) {
925 CheckUnsigned (inCheckedContext, Value);
926 return new UIntConstant ((uint) Value, Location);
928 if (target_type == TypeManager.int64_type)
929 return new LongConstant ((long) Value, Location);
930 if (target_type == TypeManager.uint64_type) {
931 CheckUnsigned (inCheckedContext, Value);
932 return new ULongConstant ((ulong) Value, Location);
934 if (target_type == TypeManager.float_type)
935 return new FloatConstant ((float) Value, Location);
936 if (target_type == TypeManager.double_type)
937 return new DoubleConstant ((double) Value, Location);
938 if (target_type == TypeManager.char_type) {
939 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
940 return new CharConstant ((char) Value, Location);
942 if (target_type == TypeManager.decimal_type)
943 return new DecimalConstant ((decimal) Value, Location);
950 public class UShortConstant : IntegralConstant {
951 public readonly ushort Value;
953 public UShortConstant (ushort v, Location loc):
956 type = TypeManager.ushort_type;
957 eclass = ExprClass.Value;
961 public override void Emit (EmitContext ec)
963 IntLiteral.EmitInt (ec.ig, Value);
966 public override string AsString ()
968 return Value.ToString ();
971 public override object GetValue ()
976 public override DoubleConstant ConvertToDouble ()
978 return new DoubleConstant (Value, loc);
981 public override FloatConstant ConvertToFloat ()
983 return new FloatConstant (Value, loc);
986 public override ULongConstant ConvertToULong ()
988 return new ULongConstant (Value, loc);
991 public override LongConstant ConvertToLong ()
993 return new LongConstant (Value, loc);
996 public override UIntConstant ConvertToUInt ()
998 return new UIntConstant (Value, loc);
1001 public override IntConstant ConvertToInt ()
1003 return new IntConstant (Value, loc);
1006 public override Constant Increment ()
1008 return new UShortConstant (checked((ushort)(Value + 1)), loc);
1011 public override bool IsDefaultValue {
1017 public override bool IsNegative {
1023 public override bool IsZeroInteger {
1024 get { return Value == 0; }
1027 public override Constant Reduce (bool inCheckedContext, Type target_type)
1029 if (target_type == TypeManager.byte_type) {
1030 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1031 return new ByteConstant ((byte) Value, Location);
1033 if (target_type == TypeManager.sbyte_type) {
1034 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1035 return new SByteConstant ((sbyte) Value, Location);
1037 if (target_type == TypeManager.short_type) {
1038 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1039 return new ShortConstant ((short) Value, Location);
1041 if (target_type == TypeManager.int32_type)
1042 return new IntConstant ((int) Value, Location);
1043 if (target_type == TypeManager.uint32_type)
1044 return new UIntConstant ((uint) Value, Location);
1045 if (target_type == TypeManager.int64_type)
1046 return new LongConstant ((long) Value, Location);
1047 if (target_type == TypeManager.uint64_type)
1048 return new ULongConstant ((ulong) Value, Location);
1049 if (target_type == TypeManager.float_type)
1050 return new FloatConstant ((float) Value, Location);
1051 if (target_type == TypeManager.double_type)
1052 return new DoubleConstant ((double) Value, Location);
1053 if (target_type == TypeManager.char_type) {
1054 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1055 return new CharConstant ((char) Value, Location);
1057 if (target_type == TypeManager.decimal_type)
1058 return new DecimalConstant ((decimal) Value, Location);
1064 public class IntConstant : IntegralConstant {
1065 public readonly int Value;
1067 public IntConstant (int v, Location loc):
1070 type = TypeManager.int32_type;
1071 eclass = ExprClass.Value;
1075 static public void EmitInt (ILGenerator ig, int i)
1079 ig.Emit (OpCodes.Ldc_I4_M1);
1083 ig.Emit (OpCodes.Ldc_I4_0);
1087 ig.Emit (OpCodes.Ldc_I4_1);
1091 ig.Emit (OpCodes.Ldc_I4_2);
1095 ig.Emit (OpCodes.Ldc_I4_3);
1099 ig.Emit (OpCodes.Ldc_I4_4);
1103 ig.Emit (OpCodes.Ldc_I4_5);
1107 ig.Emit (OpCodes.Ldc_I4_6);
1111 ig.Emit (OpCodes.Ldc_I4_7);
1115 ig.Emit (OpCodes.Ldc_I4_8);
1119 if (i >= -128 && i <= 127){
1120 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
1122 ig.Emit (OpCodes.Ldc_I4, i);
1127 public override void Emit (EmitContext ec)
1129 EmitInt (ec.ig, Value);
1132 public override string AsString ()
1134 return Value.ToString ();
1137 public override object GetValue ()
1142 public override DecimalConstant ConvertToDecimal()
1144 return new DecimalConstant (Value, loc);
1147 public override DoubleConstant ConvertToDouble ()
1149 return new DoubleConstant (Value, loc);
1152 public override FloatConstant ConvertToFloat ()
1154 return new FloatConstant (Value, loc);
1157 public override ULongConstant ConvertToULong ()
1162 return new ULongConstant ((ulong) Value, loc);
1165 public override LongConstant ConvertToLong ()
1167 return new LongConstant (Value, loc);
1170 public override UIntConstant ConvertToUInt ()
1175 return new UIntConstant ((uint) Value, loc);
1178 public override IntConstant ConvertToInt ()
1183 public override Constant Increment ()
1185 return new IntConstant (checked(Value + 1), loc);
1188 public override bool IsDefaultValue {
1194 public override bool IsNegative {
1200 public override bool IsZeroInteger {
1201 get { return Value == 0; }
1204 public override Constant Reduce (bool inCheckedContext, Type target_type)
1206 if (target_type == TypeManager.byte_type) {
1207 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1208 return new ByteConstant ((byte) Value, Location);
1210 if (target_type == TypeManager.sbyte_type) {
1211 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1212 return new SByteConstant ((sbyte) Value, Location);
1214 if (target_type == TypeManager.short_type) {
1215 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1216 return new ShortConstant ((short) Value, Location);
1218 if (target_type == TypeManager.ushort_type) {
1219 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1220 return new UShortConstant ((ushort) Value, Location);
1222 if (target_type == TypeManager.uint32_type) {
1223 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1224 return new UIntConstant ((uint) Value, Location);
1226 if (target_type == TypeManager.int64_type)
1227 return new LongConstant ((long) Value, Location);
1228 if (target_type == TypeManager.uint64_type) {
1229 CheckUnsigned (inCheckedContext, Value);
1230 return new ULongConstant ((ulong) Value, Location);
1232 if (target_type == TypeManager.float_type)
1233 return new FloatConstant ((float) Value, Location);
1234 if (target_type == TypeManager.double_type)
1235 return new DoubleConstant ((double) Value, Location);
1236 if (target_type == TypeManager.char_type) {
1237 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1238 return new CharConstant ((char) Value, Location);
1240 if (target_type == TypeManager.decimal_type)
1241 return new DecimalConstant ((decimal) Value, Location);
1247 public class UIntConstant : IntegralConstant {
1248 public readonly uint Value;
1250 public UIntConstant (uint v, Location loc):
1253 type = TypeManager.uint32_type;
1254 eclass = ExprClass.Value;
1258 public override void Emit (EmitContext ec)
1260 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1263 public override string AsString ()
1265 return Value.ToString ();
1268 public override object GetValue ()
1273 public override DoubleConstant ConvertToDouble ()
1275 return new DoubleConstant (Value, loc);
1278 public override FloatConstant ConvertToFloat ()
1280 return new FloatConstant (Value, loc);
1283 public override ULongConstant ConvertToULong ()
1285 return new ULongConstant (Value, loc);
1288 public override LongConstant ConvertToLong ()
1290 return new LongConstant (Value, loc);
1293 public override UIntConstant ConvertToUInt ()
1298 public override IntConstant ConvertToInt ()
1303 public override Constant Increment ()
1305 return new UIntConstant (checked(Value + 1), loc);
1308 public override bool IsDefaultValue {
1314 public override bool IsNegative {
1320 public override bool IsZeroInteger {
1321 get { return Value == 0; }
1324 public override Constant Reduce (bool inCheckedContext, Type target_type)
1326 if (target_type == TypeManager.byte_type) {
1327 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1328 return new ByteConstant ((byte) Value, Location);
1330 if (target_type == TypeManager.sbyte_type) {
1331 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1332 return new SByteConstant ((sbyte) Value, Location);
1334 if (target_type == TypeManager.short_type) {
1335 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1336 return new ShortConstant ((short) Value, Location);
1338 if (target_type == TypeManager.ushort_type) {
1339 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1340 return new UShortConstant ((ushort) Value, Location);
1342 if (target_type == TypeManager.int32_type) {
1343 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1344 return new IntConstant ((int) Value, Location);
1346 if (target_type == TypeManager.int64_type)
1347 return new LongConstant ((long) Value, Location);
1348 if (target_type == TypeManager.uint64_type)
1349 return new ULongConstant ((ulong) Value, Location);
1350 if (target_type == TypeManager.float_type)
1351 return new FloatConstant ((float) Value, Location);
1352 if (target_type == TypeManager.double_type)
1353 return new DoubleConstant ((double) Value, Location);
1354 if (target_type == TypeManager.char_type) {
1355 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1356 return new CharConstant ((char) Value, Location);
1358 if (target_type == TypeManager.decimal_type)
1359 return new DecimalConstant ((decimal) Value, Location);
1366 public class LongConstant : IntegralConstant {
1367 public readonly long Value;
1369 public LongConstant (long v, Location loc):
1372 type = TypeManager.int64_type;
1373 eclass = ExprClass.Value;
1377 public override void Emit (EmitContext ec)
1379 EmitLong (ec.ig, Value);
1382 static public void EmitLong (ILGenerator ig, long l)
1384 if (l >= int.MinValue && l <= int.MaxValue) {
1385 IntLiteral.EmitInt (ig, unchecked ((int) l));
1386 ig.Emit (OpCodes.Conv_I8);
1389 ig.Emit (OpCodes.Ldc_I8, l);
1392 public override string AsString ()
1394 return Value.ToString ();
1397 public override object GetValue ()
1402 public override DoubleConstant ConvertToDouble ()
1404 return new DoubleConstant (Value, loc);
1407 public override FloatConstant ConvertToFloat ()
1409 return new FloatConstant (Value, loc);
1412 public override ULongConstant ConvertToULong ()
1417 return new ULongConstant ((ulong) Value, loc);
1420 public override LongConstant ConvertToLong ()
1425 public override UIntConstant ConvertToUInt ()
1430 public override IntConstant ConvertToInt ()
1435 public override Constant Increment ()
1437 return new LongConstant (checked(Value + 1), loc);
1440 public override bool IsDefaultValue {
1446 public override bool IsNegative {
1452 public override bool IsZeroInteger {
1453 get { return Value == 0; }
1456 public override Constant Reduce (bool inCheckedContext, Type target_type)
1458 if (target_type == TypeManager.byte_type) {
1459 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1460 return new ByteConstant ((byte) Value, Location);
1462 if (target_type == TypeManager.sbyte_type) {
1463 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1464 return new SByteConstant ((sbyte) Value, Location);
1466 if (target_type == TypeManager.short_type) {
1467 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1468 return new ShortConstant ((short) Value, Location);
1470 if (target_type == TypeManager.ushort_type) {
1471 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1472 return new UShortConstant ((ushort) Value, Location);
1474 if (target_type == TypeManager.int32_type) {
1475 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1476 return new IntConstant ((int) Value, Location);
1478 if (target_type == TypeManager.uint32_type) {
1479 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1480 return new UIntConstant ((uint) Value, Location);
1482 if (target_type == TypeManager.uint64_type) {
1483 CheckUnsigned (inCheckedContext, Value);
1484 return new ULongConstant ((ulong) Value, Location);
1486 if (target_type == TypeManager.float_type)
1487 return new FloatConstant ((float) Value, Location);
1488 if (target_type == TypeManager.double_type)
1489 return new DoubleConstant ((double) Value, Location);
1490 if (target_type == TypeManager.char_type) {
1491 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1492 return new CharConstant ((char) Value, Location);
1494 if (target_type == TypeManager.decimal_type)
1495 return new DecimalConstant ((decimal) Value, Location);
1502 public class ULongConstant : IntegralConstant {
1503 public readonly ulong Value;
1505 public ULongConstant (ulong v, Location loc):
1508 type = TypeManager.uint64_type;
1509 eclass = ExprClass.Value;
1513 public override void Emit (EmitContext ec)
1515 ILGenerator ig = ec.ig;
1517 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1520 public override string AsString ()
1522 return Value.ToString ();
1525 public override object GetValue ()
1530 public override DoubleConstant ConvertToDouble ()
1532 return new DoubleConstant (Value, loc);
1535 public override FloatConstant ConvertToFloat ()
1537 return new FloatConstant (Value, loc);
1540 public override ULongConstant ConvertToULong ()
1545 public override LongConstant ConvertToLong ()
1550 public override UIntConstant ConvertToUInt ()
1555 public override IntConstant ConvertToInt ()
1560 public override Constant Increment ()
1562 return new ULongConstant (checked(Value + 1), loc);
1565 public override bool IsDefaultValue {
1571 public override bool IsNegative {
1577 public override bool IsZeroInteger {
1578 get { return Value == 0; }
1581 public override Constant Reduce (bool inCheckedContext, Type target_type)
1583 if (target_type == TypeManager.byte_type) {
1584 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1585 return new ByteConstant ((byte) Value, Location);
1587 if (target_type == TypeManager.sbyte_type) {
1588 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1589 return new SByteConstant ((sbyte) Value, Location);
1591 if (target_type == TypeManager.short_type) {
1592 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1593 return new ShortConstant ((short) Value, Location);
1595 if (target_type == TypeManager.ushort_type) {
1596 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1597 return new UShortConstant ((ushort) Value, Location);
1599 if (target_type == TypeManager.int32_type) {
1600 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1601 return new IntConstant ((int) Value, Location);
1603 if (target_type == TypeManager.uint32_type) {
1604 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1605 return new UIntConstant ((uint) Value, Location);
1607 if (target_type == TypeManager.int64_type) {
1608 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1609 return new LongConstant ((long) Value, Location);
1611 if (target_type == TypeManager.float_type)
1612 return new FloatConstant ((float) Value, Location);
1613 if (target_type == TypeManager.double_type)
1614 return new DoubleConstant ((double) Value, Location);
1615 if (target_type == TypeManager.char_type) {
1616 CheckRange (inCheckedContext, Value, Char.MaxValue);
1617 return new CharConstant ((char) Value, Location);
1619 if (target_type == TypeManager.decimal_type)
1620 return new DecimalConstant ((decimal) Value, Location);
1627 public class FloatConstant : Constant {
1630 public FloatConstant (float v, Location loc):
1633 type = TypeManager.float_type;
1634 eclass = ExprClass.Value;
1638 public override void Emit (EmitContext ec)
1640 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1643 public override string AsString ()
1645 return Value.ToString ();
1648 public override object GetValue ()
1653 public override DoubleConstant ConvertToDouble ()
1655 return new DoubleConstant (Value, loc);
1658 public override FloatConstant ConvertToFloat ()
1663 public override LongConstant ConvertToLong ()
1668 public override UIntConstant ConvertToUInt ()
1673 public override IntConstant ConvertToInt ()
1678 public override Constant Increment ()
1680 return new FloatConstant (checked(Value + 1), loc);
1683 public override bool IsDefaultValue {
1689 public override bool IsNegative {
1695 public override Constant Reduce (bool inCheckedContext, Type target_type)
1697 if (target_type == TypeManager.byte_type) {
1698 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1699 return new ByteConstant ((byte) Value, Location);
1701 if (target_type == TypeManager.sbyte_type) {
1702 CheckRange (inCheckedContext, Value, sbyte.MinValue, sbyte.MaxValue);
1703 return new SByteConstant ((sbyte) Value, Location);
1705 if (target_type == TypeManager.short_type) {
1706 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1707 return new ShortConstant ((short) Value, Location);
1709 if (target_type == TypeManager.ushort_type) {
1710 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1711 return new UShortConstant ((ushort) Value, Location);
1713 if (target_type == TypeManager.int32_type) {
1714 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1715 return new IntConstant ((int) Value, Location);
1717 if (target_type == TypeManager.uint32_type) {
1718 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1719 return new UIntConstant ((uint) Value, Location);
1721 if (target_type == TypeManager.int64_type) {
1722 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1723 return new LongConstant ((long) Value, Location);
1725 if (target_type == TypeManager.uint64_type) {
1726 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1727 return new ULongConstant ((ulong) Value, Location);
1729 if (target_type == TypeManager.double_type)
1730 return new DoubleConstant ((double) Value, Location);
1731 if (target_type == TypeManager.char_type) {
1732 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1733 return new CharConstant ((char) Value, Location);
1735 if (target_type == TypeManager.decimal_type)
1736 return new DecimalConstant ((decimal) Value, Location);
1743 public class DoubleConstant : Constant {
1744 public double Value;
1746 public DoubleConstant (double v, Location loc):
1749 type = TypeManager.double_type;
1750 eclass = ExprClass.Value;
1754 public override void Emit (EmitContext ec)
1756 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1759 public override string AsString ()
1761 return Value.ToString ();
1764 public override object GetValue ()
1769 public override DoubleConstant ConvertToDouble ()
1774 public override FloatConstant ConvertToFloat ()
1779 public override ULongConstant ConvertToULong ()
1784 public override LongConstant ConvertToLong ()
1789 public override UIntConstant ConvertToUInt ()
1794 public override IntConstant ConvertToInt ()
1799 public override Constant Increment ()
1801 return new DoubleConstant (checked(Value + 1), loc);
1804 public override bool IsDefaultValue {
1810 public override bool IsNegative {
1816 public override Constant Reduce (bool inCheckedContext, Type target_type)
1818 if (target_type == TypeManager.byte_type) {
1819 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1820 return new ByteConstant ((byte) Value, Location);
1822 if (target_type == TypeManager.sbyte_type) {
1823 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1824 return new SByteConstant ((sbyte) Value, Location);
1826 if (target_type == TypeManager.short_type) {
1827 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1828 return new ShortConstant ((short) Value, Location);
1830 if (target_type == TypeManager.ushort_type) {
1831 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1832 return new UShortConstant ((ushort) Value, Location);
1834 if (target_type == TypeManager.int32_type) {
1835 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1836 return new IntConstant ((int) Value, Location);
1838 if (target_type == TypeManager.uint32_type) {
1839 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1840 return new UIntConstant ((uint) Value, Location);
1842 if (target_type == TypeManager.int64_type) {
1843 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1844 return new LongConstant ((long) Value, Location);
1846 if (target_type == TypeManager.uint64_type) {
1847 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1848 return new ULongConstant ((ulong) Value, Location);
1850 if (target_type == TypeManager.float_type)
1851 return new FloatConstant ((float) Value, Location);
1852 if (target_type == TypeManager.char_type) {
1853 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1854 return new CharConstant ((char) Value, Location);
1856 if (target_type == TypeManager.decimal_type)
1857 return new DecimalConstant ((decimal) Value, Location);
1864 public class DecimalConstant : Constant {
1865 public readonly decimal Value;
1867 public DecimalConstant (decimal d, Location loc):
1870 type = TypeManager.decimal_type;
1871 eclass = ExprClass.Value;
1875 override public string AsString ()
1877 return Value.ToString ();
1880 public override object GetValue ()
1882 return (object) Value;
1885 public override void Emit (EmitContext ec)
1887 ILGenerator ig = ec.ig;
1889 int [] words = Decimal.GetBits (Value);
1890 int power = (words [3] >> 16) & 0xff;
1892 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1894 IntConstant.EmitInt (ig, (int)Value);
1895 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1901 // FIXME: we could optimize this, and call a better
1905 IntConstant.EmitInt (ig, words [0]);
1906 IntConstant.EmitInt (ig, words [1]);
1907 IntConstant.EmitInt (ig, words [2]);
1910 IntConstant.EmitInt (ig, words [3] >> 31);
1913 IntConstant.EmitInt (ig, power);
1915 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1918 public override Constant Increment ()
1920 return new DecimalConstant (checked (Value + 1), loc);
1923 public override bool IsDefaultValue {
1929 public override bool IsNegative {
1935 public override Constant Reduce (bool inCheckedContext, Type target_type)
1937 if (target_type == TypeManager.sbyte_type)
1938 return new SByteConstant ((sbyte)Value, loc);
1939 if (target_type == TypeManager.byte_type)
1940 return new ByteConstant ((byte)Value, loc);
1941 if (target_type == TypeManager.short_type)
1942 return new ShortConstant ((short)Value, loc);
1943 if (target_type == TypeManager.ushort_type)
1944 return new UShortConstant ((ushort)Value, loc);
1945 if (target_type == TypeManager.int32_type)
1946 return new IntConstant ((int)Value, loc);
1947 if (target_type == TypeManager.uint32_type)
1948 return new UIntConstant ((uint)Value, loc);
1949 if (target_type == TypeManager.int64_type)
1950 return new LongConstant ((long)Value, loc);
1951 if (target_type == TypeManager.uint64_type)
1952 return new ULongConstant ((ulong)Value, loc);
1953 if (target_type == TypeManager.char_type)
1954 return new CharConstant ((char)Value, loc);
1955 if (target_type == TypeManager.float_type)
1956 return new FloatConstant ((float)Value, loc);
1957 if (target_type == TypeManager.double_type)
1958 return new DoubleConstant ((double)Value, loc);
1965 public class StringConstant : Constant {
1966 public readonly string Value;
1968 public StringConstant (string s, Location loc):
1971 type = TypeManager.string_type;
1972 eclass = ExprClass.Value;
1976 // FIXME: Escape the string.
1977 override public string AsString ()
1979 return "\"" + Value + "\"";
1982 public override object GetValue ()
1987 public override void Emit (EmitContext ec)
1990 ec.ig.Emit (OpCodes.Ldnull);
1992 ec.ig.Emit (OpCodes.Ldstr, Value);
1995 public override Constant Increment ()
1997 throw new NotSupportedException ();
2000 public override bool IsDefaultValue {
2002 return Value == null;
2006 public override bool IsNegative {
2012 public override Constant Reduce (bool inCheckedContext, Type target_type)