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));
192 if (type == TypeManager.int32_type)
193 retval = new IntConstant ((int) constant_value, loc);
194 else if (type == TypeManager.uint32_type)
195 retval = new UIntConstant ((uint) constant_value, loc);
196 else if (type == TypeManager.int64_type)
197 retval = new LongConstant ((long) constant_value, loc);
198 else if (type == TypeManager.uint64_type)
199 retval = new ULongConstant ((ulong) constant_value, loc);
200 else if (type == TypeManager.float_type)
201 retval = new FloatConstant ((float) constant_value, loc);
202 else if (type == TypeManager.double_type)
203 retval = new DoubleConstant ((double) constant_value, loc);
204 else if (type == TypeManager.string_type)
205 retval = new StringConstant ((string) constant_value, loc);
206 else if (type == TypeManager.short_type)
207 retval = new ShortConstant ((short) constant_value, loc);
208 else if (type == TypeManager.ushort_type)
209 retval = new UShortConstant ((ushort) constant_value, loc);
210 else if (type == TypeManager.sbyte_type)
211 retval = new SByteConstant ((sbyte) constant_value, loc);
212 else if (type == TypeManager.byte_type)
213 retval = new ByteConstant ((byte) constant_value, loc);
214 else if (type == TypeManager.char_type)
215 retval = new CharConstant ((char) constant_value, loc);
216 else if (type == TypeManager.bool_type)
217 retval = new BoolConstant ((bool) constant_value, loc);
218 else if (type == TypeManager.decimal_type)
219 retval = new DecimalConstant ((decimal) constant_value, loc);
221 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
226 protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
228 if (!inCheckedContext)
232 throw new OverflowException ();
235 protected static void CheckRange (bool inCheckedContext, double value, long min, long max)
237 if (!inCheckedContext)
240 if (((value < min) || (value > max)))
241 throw new OverflowException ();
243 if (double.IsNaN (value))
244 throw new OverflowException ();
247 protected static void CheckRange (bool inCheckedContext, double value, ulong min, ulong max)
249 if (!inCheckedContext)
252 if (((value < min) || (value > max)))
253 throw new OverflowException ();
255 if (double.IsNaN (value))
256 throw new OverflowException ();
259 protected static void CheckUnsigned (bool inCheckedContext, long value)
261 if (!inCheckedContext)
265 throw new OverflowException ();
269 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
270 /// It throws OverflowException
272 public abstract Constant Reduce (bool inCheckedContext, Type target_type);
275 /// Attempts to do a compile-time folding of a constant cast.
277 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
280 return TryReduce (ec, target_type);
282 catch (OverflowException) {
283 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
284 GetValue ().ToString (), TypeManager.CSharpName (target_type));
289 Constant TryReduce (EmitContext ec, Type target_type)
291 if (Type == target_type)
294 if (TypeManager.IsEnumType (target_type)) {
295 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
299 return new EnumConstant (c, target_type);
302 return Reduce (ec.ConstantCheckState, target_type);
306 public virtual DecimalConstant ConvertToDecimal ()
311 public virtual DoubleConstant ConvertToDouble ()
316 public virtual FloatConstant ConvertToFloat ()
321 public virtual ULongConstant ConvertToULong ()
326 public virtual LongConstant ConvertToLong ()
331 public virtual UIntConstant ConvertToUInt ()
336 public virtual IntConstant ConvertToInt ()
341 public abstract Constant Increment ();
344 /// Need to pass type as the constant can require a boxing
345 /// and in such case no optimization is possible
347 public bool IsDefaultInitializer (Type type)
350 return IsDefaultValue;
352 return Type == TypeManager.null_type;
355 public abstract bool IsDefaultValue {
359 public abstract bool IsNegative {
364 // Returns true iff 1) the stack type of this is one of Object,
365 // int32, int64 and 2) this == 0 or this == null.
367 public virtual bool IsZeroInteger {
368 get { return false; }
372 public abstract class IntegralConstant : Constant {
373 protected IntegralConstant (Location loc) :
378 public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
381 Reduce (true, target);
382 base.Error_ValueCannotBeConverted (loc, target, expl);
386 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
387 GetValue ().ToString (), TypeManager.CSharpName (target));
392 public class BoolConstant : Constant {
393 public readonly bool Value;
395 public BoolConstant (bool val, Location loc):
398 type = TypeManager.bool_type;
399 eclass = ExprClass.Value;
404 override public string AsString ()
406 return Value ? "true" : "false";
409 public override object GetValue ()
411 return (object) Value;
415 public override void Emit (EmitContext ec)
418 ec.ig.Emit (OpCodes.Ldc_I4_1);
420 ec.ig.Emit (OpCodes.Ldc_I4_0);
423 public override Constant Increment ()
425 throw new NotSupportedException ();
428 public override bool IsDefaultValue {
434 public override bool IsNegative {
440 public override bool IsZeroInteger {
441 get { return Value == false; }
444 public override Constant Reduce (bool inCheckedContext, Type target_type)
451 public class ByteConstant : IntegralConstant {
452 public readonly byte Value;
454 public ByteConstant (byte v, Location loc):
457 type = TypeManager.byte_type;
458 eclass = ExprClass.Value;
462 public override void Emit (EmitContext ec)
464 IntLiteral.EmitInt (ec.ig, Value);
467 public override string AsString ()
469 return Value.ToString ();
472 public override object GetValue ()
477 public override DoubleConstant ConvertToDouble ()
479 return new DoubleConstant (Value, loc);
482 public override FloatConstant ConvertToFloat ()
484 return new FloatConstant (Value, loc);
487 public override ULongConstant ConvertToULong ()
489 return new ULongConstant (Value, loc);
492 public override LongConstant ConvertToLong ()
494 return new LongConstant (Value, loc);
497 public override UIntConstant ConvertToUInt ()
499 return new UIntConstant (Value, loc);
502 public override IntConstant ConvertToInt ()
504 return new IntConstant (Value, loc);
507 public override Constant Increment ()
509 return new ByteConstant (checked ((byte)(Value + 1)), loc);
512 public override bool IsDefaultValue {
518 public override bool IsNegative {
524 public override bool IsZeroInteger {
525 get { return Value == 0; }
528 public override Constant Reduce (bool inCheckedContext, Type target_type)
530 if (target_type == TypeManager.sbyte_type) {
531 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
532 return new SByteConstant ((sbyte) Value, Location);
534 if (target_type == TypeManager.short_type)
535 return new ShortConstant ((short) Value, Location);
536 if (target_type == TypeManager.ushort_type)
537 return new UShortConstant ((ushort) Value, Location);
538 if (target_type == TypeManager.int32_type)
539 return new IntConstant ((int) Value, Location);
540 if (target_type == TypeManager.uint32_type)
541 return new UIntConstant ((uint) Value, Location);
542 if (target_type == TypeManager.int64_type)
543 return new LongConstant ((long) Value, Location);
544 if (target_type == TypeManager.uint64_type)
545 return new ULongConstant ((ulong) Value, Location);
546 if (target_type == TypeManager.float_type)
547 return new FloatConstant ((float) Value, Location);
548 if (target_type == TypeManager.double_type)
549 return new DoubleConstant ((double) Value, Location);
550 if (target_type == TypeManager.char_type)
551 return new CharConstant ((char) Value, Location);
552 if (target_type == TypeManager.decimal_type)
553 return new DecimalConstant ((decimal) Value, Location);
560 public class CharConstant : Constant {
561 public readonly char Value;
563 public CharConstant (char v, Location loc):
566 type = TypeManager.char_type;
567 eclass = ExprClass.Value;
571 public override void Emit (EmitContext ec)
573 IntLiteral.EmitInt (ec.ig, Value);
576 static public string descape (char c)
602 return c.ToString ();
605 public override string AsString ()
607 return "\"" + descape (Value) + "\"";
610 public override object GetValue ()
615 public override DoubleConstant ConvertToDouble ()
617 return new DoubleConstant (Value, loc);
620 public override FloatConstant ConvertToFloat ()
622 return new FloatConstant (Value, loc);
625 public override ULongConstant ConvertToULong ()
627 return new ULongConstant (Value, loc);
630 public override LongConstant ConvertToLong ()
632 return new LongConstant (Value, loc);
635 public override UIntConstant ConvertToUInt ()
637 return new UIntConstant (Value, loc);
640 public override IntConstant ConvertToInt ()
642 return new IntConstant (Value, loc);
645 public override Constant Increment ()
647 return new CharConstant (checked ((char)(Value + 1)), loc);
650 public override bool IsDefaultValue {
656 public override bool IsNegative {
662 public override bool IsZeroInteger {
663 get { return Value == '\0'; }
666 public override Constant Reduce (bool inCheckedContext, Type target_type)
668 if (target_type == TypeManager.byte_type) {
669 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
670 return new ByteConstant ((byte) Value, Location);
672 if (target_type == TypeManager.sbyte_type) {
673 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
674 return new SByteConstant ((sbyte) Value, Location);
676 if (target_type == TypeManager.short_type) {
677 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
678 return new ShortConstant ((short) Value, Location);
680 if (target_type == TypeManager.int32_type)
681 return new IntConstant ((int) Value, Location);
682 if (target_type == TypeManager.uint32_type)
683 return new UIntConstant ((uint) Value, Location);
684 if (target_type == TypeManager.int64_type)
685 return new LongConstant ((long) Value, Location);
686 if (target_type == TypeManager.uint64_type)
687 return new ULongConstant ((ulong) Value, Location);
688 if (target_type == TypeManager.float_type)
689 return new FloatConstant ((float) Value, Location);
690 if (target_type == TypeManager.double_type)
691 return new DoubleConstant ((double) Value, Location);
692 if (target_type == TypeManager.decimal_type)
693 return new DecimalConstant ((decimal) Value, Location);
700 public class SByteConstant : IntegralConstant {
701 public readonly sbyte Value;
703 public SByteConstant (sbyte v, Location loc):
706 type = TypeManager.sbyte_type;
707 eclass = ExprClass.Value;
711 public override void Emit (EmitContext ec)
713 IntLiteral.EmitInt (ec.ig, Value);
716 public override string AsString ()
718 return Value.ToString ();
721 public override object GetValue ()
726 public override DoubleConstant ConvertToDouble ()
728 return new DoubleConstant (Value, loc);
731 public override FloatConstant ConvertToFloat ()
733 return new FloatConstant (Value, loc);
736 public override ULongConstant ConvertToULong ()
739 return new ULongConstant ((ulong) Value, loc);
744 public override LongConstant ConvertToLong ()
746 return new LongConstant (Value, loc);
749 public override UIntConstant ConvertToUInt ()
754 public override IntConstant ConvertToInt ()
756 return new IntConstant (Value, loc);
759 public override Constant Increment ()
761 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
764 public override bool IsDefaultValue {
770 public override bool IsNegative {
776 public override bool IsZeroInteger {
777 get { return Value == 0; }
780 public override Constant Reduce (bool inCheckedContext, Type target_type)
782 if (target_type == TypeManager.byte_type) {
783 CheckUnsigned (inCheckedContext, Value);
784 return new ByteConstant ((byte) Value, Location);
786 if (target_type == TypeManager.short_type)
787 return new ShortConstant ((short) Value, Location);
788 if (target_type == TypeManager.ushort_type) {
789 CheckUnsigned (inCheckedContext, Value);
790 return new UShortConstant ((ushort) Value, Location);
791 } if (target_type == TypeManager.int32_type)
792 return new IntConstant ((int) Value, Location);
793 if (target_type == TypeManager.uint32_type) {
794 CheckUnsigned (inCheckedContext, Value);
795 return new UIntConstant ((uint) Value, Location);
796 } if (target_type == TypeManager.int64_type)
797 return new LongConstant ((long) Value, Location);
798 if (target_type == TypeManager.uint64_type) {
799 CheckUnsigned (inCheckedContext, Value);
800 return new ULongConstant ((ulong) Value, Location);
802 if (target_type == TypeManager.float_type)
803 return new FloatConstant ((float) Value, Location);
804 if (target_type == TypeManager.double_type)
805 return new DoubleConstant ((double) Value, Location);
806 if (target_type == TypeManager.char_type) {
807 CheckUnsigned (inCheckedContext, Value);
808 return new CharConstant ((char) Value, Location);
810 if (target_type == TypeManager.decimal_type)
811 return new DecimalConstant ((decimal) Value, Location);
818 public class ShortConstant : IntegralConstant {
819 public readonly short Value;
821 public ShortConstant (short v, Location loc):
824 type = TypeManager.short_type;
825 eclass = ExprClass.Value;
829 public override void Emit (EmitContext ec)
831 IntLiteral.EmitInt (ec.ig, Value);
834 public override string AsString ()
836 return Value.ToString ();
839 public override object GetValue ()
844 public override DoubleConstant ConvertToDouble ()
846 return new DoubleConstant (Value, loc);
849 public override FloatConstant ConvertToFloat ()
851 return new FloatConstant (Value, loc);
854 public override ULongConstant ConvertToULong ()
859 public override LongConstant ConvertToLong ()
861 return new LongConstant (Value, loc);
864 public override UIntConstant ConvertToUInt ()
869 public override IntConstant ConvertToInt ()
871 return new IntConstant (Value, loc);
874 public override Constant Increment ()
876 return new ShortConstant (checked((short)(Value + 1)), loc);
879 public override bool IsDefaultValue {
885 public override bool IsZeroInteger {
886 get { return Value == 0; }
889 public override bool IsNegative {
895 public override Constant Reduce (bool inCheckedContext, Type target_type)
897 if (target_type == TypeManager.byte_type) {
898 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
899 return new ByteConstant ((byte) Value, Location);
901 if (target_type == TypeManager.sbyte_type) {
902 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
903 return new SByteConstant ((sbyte) Value, Location);
905 if (target_type == TypeManager.ushort_type) {
906 CheckUnsigned (inCheckedContext, Value);
907 return new UShortConstant ((ushort) Value, Location);
909 if (target_type == TypeManager.int32_type)
910 return new IntConstant ((int) Value, Location);
911 if (target_type == TypeManager.uint32_type) {
912 CheckUnsigned (inCheckedContext, Value);
913 return new UIntConstant ((uint) Value, Location);
915 if (target_type == TypeManager.int64_type)
916 return new LongConstant ((long) Value, Location);
917 if (target_type == TypeManager.uint64_type) {
918 CheckUnsigned (inCheckedContext, Value);
919 return new ULongConstant ((ulong) Value, Location);
921 if (target_type == TypeManager.float_type)
922 return new FloatConstant ((float) Value, Location);
923 if (target_type == TypeManager.double_type)
924 return new DoubleConstant ((double) Value, Location);
925 if (target_type == TypeManager.char_type) {
926 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
927 return new CharConstant ((char) Value, Location);
929 if (target_type == TypeManager.decimal_type)
930 return new DecimalConstant ((decimal) Value, Location);
937 public class UShortConstant : IntegralConstant {
938 public readonly ushort Value;
940 public UShortConstant (ushort v, Location loc):
943 type = TypeManager.ushort_type;
944 eclass = ExprClass.Value;
948 public override void Emit (EmitContext ec)
950 IntLiteral.EmitInt (ec.ig, Value);
953 public override string AsString ()
955 return Value.ToString ();
958 public override object GetValue ()
963 public override DoubleConstant ConvertToDouble ()
965 return new DoubleConstant (Value, loc);
968 public override FloatConstant ConvertToFloat ()
970 return new FloatConstant (Value, loc);
973 public override ULongConstant ConvertToULong ()
975 return new ULongConstant (Value, loc);
978 public override LongConstant ConvertToLong ()
980 return new LongConstant (Value, loc);
983 public override UIntConstant ConvertToUInt ()
985 return new UIntConstant (Value, loc);
988 public override IntConstant ConvertToInt ()
990 return new IntConstant (Value, loc);
993 public override Constant Increment ()
995 return new UShortConstant (checked((ushort)(Value + 1)), loc);
998 public override bool IsDefaultValue {
1004 public override bool IsNegative {
1010 public override bool IsZeroInteger {
1011 get { return Value == 0; }
1014 public override Constant Reduce (bool inCheckedContext, Type target_type)
1016 if (target_type == TypeManager.byte_type) {
1017 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1018 return new ByteConstant ((byte) Value, Location);
1020 if (target_type == TypeManager.sbyte_type) {
1021 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1022 return new SByteConstant ((sbyte) Value, Location);
1024 if (target_type == TypeManager.short_type) {
1025 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1026 return new ShortConstant ((short) Value, Location);
1028 if (target_type == TypeManager.int32_type)
1029 return new IntConstant ((int) Value, Location);
1030 if (target_type == TypeManager.uint32_type)
1031 return new UIntConstant ((uint) Value, Location);
1032 if (target_type == TypeManager.int64_type)
1033 return new LongConstant ((long) Value, Location);
1034 if (target_type == TypeManager.uint64_type)
1035 return new ULongConstant ((ulong) Value, Location);
1036 if (target_type == TypeManager.float_type)
1037 return new FloatConstant ((float) Value, Location);
1038 if (target_type == TypeManager.double_type)
1039 return new DoubleConstant ((double) Value, Location);
1040 if (target_type == TypeManager.char_type) {
1041 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1042 return new CharConstant ((char) Value, Location);
1044 if (target_type == TypeManager.decimal_type)
1045 return new DecimalConstant ((decimal) Value, Location);
1051 public class IntConstant : IntegralConstant {
1052 public readonly int Value;
1054 public IntConstant (int v, Location loc):
1057 type = TypeManager.int32_type;
1058 eclass = ExprClass.Value;
1062 static public void EmitInt (ILGenerator ig, int i)
1066 ig.Emit (OpCodes.Ldc_I4_M1);
1070 ig.Emit (OpCodes.Ldc_I4_0);
1074 ig.Emit (OpCodes.Ldc_I4_1);
1078 ig.Emit (OpCodes.Ldc_I4_2);
1082 ig.Emit (OpCodes.Ldc_I4_3);
1086 ig.Emit (OpCodes.Ldc_I4_4);
1090 ig.Emit (OpCodes.Ldc_I4_5);
1094 ig.Emit (OpCodes.Ldc_I4_6);
1098 ig.Emit (OpCodes.Ldc_I4_7);
1102 ig.Emit (OpCodes.Ldc_I4_8);
1106 if (i >= -128 && i <= 127){
1107 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
1109 ig.Emit (OpCodes.Ldc_I4, i);
1114 public override void Emit (EmitContext ec)
1116 EmitInt (ec.ig, Value);
1119 public override string AsString ()
1121 return Value.ToString ();
1124 public override object GetValue ()
1129 public override DecimalConstant ConvertToDecimal()
1131 return new DecimalConstant (Value, loc);
1134 public override DoubleConstant ConvertToDouble ()
1136 return new DoubleConstant (Value, loc);
1139 public override FloatConstant ConvertToFloat ()
1141 return new FloatConstant (Value, loc);
1144 public override ULongConstant ConvertToULong ()
1149 return new ULongConstant ((ulong) Value, loc);
1152 public override LongConstant ConvertToLong ()
1154 return new LongConstant (Value, loc);
1157 public override UIntConstant ConvertToUInt ()
1162 return new UIntConstant ((uint) Value, loc);
1165 public override IntConstant ConvertToInt ()
1170 public override Constant Increment ()
1172 return new IntConstant (checked(Value + 1), loc);
1175 public override bool IsDefaultValue {
1181 public override bool IsNegative {
1187 public override bool IsZeroInteger {
1188 get { return Value == 0; }
1191 public override Constant Reduce (bool inCheckedContext, Type target_type)
1193 if (target_type == TypeManager.byte_type) {
1194 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1195 return new ByteConstant ((byte) Value, Location);
1197 if (target_type == TypeManager.sbyte_type) {
1198 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1199 return new SByteConstant ((sbyte) Value, Location);
1201 if (target_type == TypeManager.short_type) {
1202 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1203 return new ShortConstant ((short) Value, Location);
1205 if (target_type == TypeManager.ushort_type) {
1206 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1207 return new UShortConstant ((ushort) Value, Location);
1209 if (target_type == TypeManager.uint32_type) {
1210 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1211 return new UIntConstant ((uint) Value, Location);
1213 if (target_type == TypeManager.int64_type)
1214 return new LongConstant ((long) Value, Location);
1215 if (target_type == TypeManager.uint64_type) {
1216 CheckUnsigned (inCheckedContext, Value);
1217 return new ULongConstant ((ulong) Value, Location);
1219 if (target_type == TypeManager.float_type)
1220 return new FloatConstant ((float) Value, Location);
1221 if (target_type == TypeManager.double_type)
1222 return new DoubleConstant ((double) Value, Location);
1223 if (target_type == TypeManager.char_type) {
1224 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1225 return new CharConstant ((char) Value, Location);
1227 if (target_type == TypeManager.decimal_type)
1228 return new DecimalConstant ((decimal) Value, Location);
1234 public class UIntConstant : IntegralConstant {
1235 public readonly uint Value;
1237 public UIntConstant (uint v, Location loc):
1240 type = TypeManager.uint32_type;
1241 eclass = ExprClass.Value;
1245 public override void Emit (EmitContext ec)
1247 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1250 public override string AsString ()
1252 return Value.ToString ();
1255 public override object GetValue ()
1260 public override DoubleConstant ConvertToDouble ()
1262 return new DoubleConstant (Value, loc);
1265 public override FloatConstant ConvertToFloat ()
1267 return new FloatConstant (Value, loc);
1270 public override ULongConstant ConvertToULong ()
1272 return new ULongConstant (Value, loc);
1275 public override LongConstant ConvertToLong ()
1277 return new LongConstant (Value, loc);
1280 public override UIntConstant ConvertToUInt ()
1285 public override IntConstant ConvertToInt ()
1290 public override Constant Increment ()
1292 return new UIntConstant (checked(Value + 1), loc);
1295 public override bool IsDefaultValue {
1301 public override bool IsNegative {
1307 public override bool IsZeroInteger {
1308 get { return Value == 0; }
1311 public override Constant Reduce (bool inCheckedContext, Type target_type)
1313 if (target_type == TypeManager.byte_type) {
1314 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1315 return new ByteConstant ((byte) Value, Location);
1317 if (target_type == TypeManager.sbyte_type) {
1318 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1319 return new SByteConstant ((sbyte) Value, Location);
1321 if (target_type == TypeManager.short_type) {
1322 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1323 return new ShortConstant ((short) Value, Location);
1325 if (target_type == TypeManager.ushort_type) {
1326 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1327 return new UShortConstant ((ushort) Value, Location);
1329 if (target_type == TypeManager.int32_type) {
1330 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1331 return new IntConstant ((int) Value, Location);
1333 if (target_type == TypeManager.int64_type)
1334 return new LongConstant ((long) Value, Location);
1335 if (target_type == TypeManager.uint64_type)
1336 return new ULongConstant ((ulong) 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 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1343 return new CharConstant ((char) Value, Location);
1345 if (target_type == TypeManager.decimal_type)
1346 return new DecimalConstant ((decimal) Value, Location);
1353 public class LongConstant : IntegralConstant {
1354 public readonly long Value;
1356 public LongConstant (long v, Location loc):
1359 type = TypeManager.int64_type;
1360 eclass = ExprClass.Value;
1364 public override void Emit (EmitContext ec)
1366 EmitLong (ec.ig, Value);
1369 static public void EmitLong (ILGenerator ig, long l)
1371 if (l >= int.MinValue && l <= int.MaxValue) {
1372 IntLiteral.EmitInt (ig, unchecked ((int) l));
1373 ig.Emit (OpCodes.Conv_I8);
1376 ig.Emit (OpCodes.Ldc_I8, l);
1379 public override string AsString ()
1381 return Value.ToString ();
1384 public override object GetValue ()
1389 public override DoubleConstant ConvertToDouble ()
1391 return new DoubleConstant (Value, loc);
1394 public override FloatConstant ConvertToFloat ()
1396 return new FloatConstant (Value, loc);
1399 public override ULongConstant ConvertToULong ()
1404 return new ULongConstant ((ulong) Value, loc);
1407 public override LongConstant ConvertToLong ()
1412 public override UIntConstant ConvertToUInt ()
1417 public override IntConstant ConvertToInt ()
1422 public override Constant Increment ()
1424 return new LongConstant (checked(Value + 1), loc);
1427 public override bool IsDefaultValue {
1433 public override bool IsNegative {
1439 public override bool IsZeroInteger {
1440 get { return Value == 0; }
1443 public override Constant Reduce (bool inCheckedContext, Type target_type)
1445 if (target_type == TypeManager.byte_type) {
1446 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1447 return new ByteConstant ((byte) Value, Location);
1449 if (target_type == TypeManager.sbyte_type) {
1450 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1451 return new SByteConstant ((sbyte) Value, Location);
1453 if (target_type == TypeManager.short_type) {
1454 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1455 return new ShortConstant ((short) Value, Location);
1457 if (target_type == TypeManager.ushort_type) {
1458 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1459 return new UShortConstant ((ushort) Value, Location);
1461 if (target_type == TypeManager.int32_type) {
1462 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1463 return new IntConstant ((int) Value, Location);
1465 if (target_type == TypeManager.uint32_type) {
1466 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1467 return new UIntConstant ((uint) Value, Location);
1469 if (target_type == TypeManager.uint64_type) {
1470 CheckUnsigned (inCheckedContext, Value);
1471 return new ULongConstant ((ulong) Value, Location);
1473 if (target_type == TypeManager.float_type)
1474 return new FloatConstant ((float) Value, Location);
1475 if (target_type == TypeManager.double_type)
1476 return new DoubleConstant ((double) Value, Location);
1477 if (target_type == TypeManager.char_type) {
1478 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1479 return new CharConstant ((char) Value, Location);
1481 if (target_type == TypeManager.decimal_type)
1482 return new DecimalConstant ((decimal) Value, Location);
1489 public class ULongConstant : IntegralConstant {
1490 public readonly ulong Value;
1492 public ULongConstant (ulong v, Location loc):
1495 type = TypeManager.uint64_type;
1496 eclass = ExprClass.Value;
1500 public override void Emit (EmitContext ec)
1502 ILGenerator ig = ec.ig;
1504 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1507 public override string AsString ()
1509 return Value.ToString ();
1512 public override object GetValue ()
1517 public override DoubleConstant ConvertToDouble ()
1519 return new DoubleConstant (Value, loc);
1522 public override FloatConstant ConvertToFloat ()
1524 return new FloatConstant (Value, loc);
1527 public override ULongConstant ConvertToULong ()
1532 public override LongConstant ConvertToLong ()
1537 public override UIntConstant ConvertToUInt ()
1542 public override IntConstant ConvertToInt ()
1547 public override Constant Increment ()
1549 return new ULongConstant (checked(Value + 1), loc);
1552 public override bool IsDefaultValue {
1558 public override bool IsNegative {
1564 public override bool IsZeroInteger {
1565 get { return Value == 0; }
1568 public override Constant Reduce (bool inCheckedContext, Type target_type)
1570 if (target_type == TypeManager.byte_type) {
1571 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1572 return new ByteConstant ((byte) Value, Location);
1574 if (target_type == TypeManager.sbyte_type) {
1575 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1576 return new SByteConstant ((sbyte) Value, Location);
1578 if (target_type == TypeManager.short_type) {
1579 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1580 return new ShortConstant ((short) Value, Location);
1582 if (target_type == TypeManager.ushort_type) {
1583 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1584 return new UShortConstant ((ushort) Value, Location);
1586 if (target_type == TypeManager.int32_type) {
1587 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1588 return new IntConstant ((int) Value, Location);
1590 if (target_type == TypeManager.uint32_type) {
1591 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1592 return new UIntConstant ((uint) Value, Location);
1594 if (target_type == TypeManager.int64_type) {
1595 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1596 return new LongConstant ((long) Value, Location);
1598 if (target_type == TypeManager.float_type)
1599 return new FloatConstant ((float) Value, Location);
1600 if (target_type == TypeManager.double_type)
1601 return new DoubleConstant ((double) Value, Location);
1602 if (target_type == TypeManager.char_type) {
1603 CheckRange (inCheckedContext, Value, Char.MaxValue);
1604 return new CharConstant ((char) Value, Location);
1606 if (target_type == TypeManager.decimal_type)
1607 return new DecimalConstant ((decimal) Value, Location);
1614 public class FloatConstant : Constant {
1615 public readonly float Value;
1617 public FloatConstant (float v, Location loc):
1620 type = TypeManager.float_type;
1621 eclass = ExprClass.Value;
1625 public override void Emit (EmitContext ec)
1627 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1630 public override string AsString ()
1632 return Value.ToString ();
1635 public override object GetValue ()
1640 public override DoubleConstant ConvertToDouble ()
1642 return new DoubleConstant (Value, loc);
1645 public override FloatConstant ConvertToFloat ()
1650 public override LongConstant ConvertToLong ()
1655 public override UIntConstant ConvertToUInt ()
1660 public override IntConstant ConvertToInt ()
1665 public override Constant Increment ()
1667 return new FloatConstant (checked(Value + 1), loc);
1670 public override bool IsDefaultValue {
1676 public override bool IsNegative {
1682 public override Constant Reduce (bool inCheckedContext, Type target_type)
1684 if (target_type == TypeManager.byte_type) {
1685 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1686 return new ByteConstant ((byte) Value, Location);
1688 if (target_type == TypeManager.sbyte_type) {
1689 CheckRange (inCheckedContext, Value, sbyte.MinValue, sbyte.MaxValue);
1690 return new SByteConstant ((sbyte) Value, Location);
1692 if (target_type == TypeManager.short_type) {
1693 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1694 return new ShortConstant ((short) Value, Location);
1696 if (target_type == TypeManager.ushort_type) {
1697 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1698 return new UShortConstant ((ushort) Value, Location);
1700 if (target_type == TypeManager.int32_type) {
1701 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1702 return new IntConstant ((int) Value, Location);
1704 if (target_type == TypeManager.uint32_type) {
1705 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1706 return new UIntConstant ((uint) Value, Location);
1708 if (target_type == TypeManager.int64_type) {
1709 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1710 return new LongConstant ((long) Value, Location);
1712 if (target_type == TypeManager.uint64_type) {
1713 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1714 return new ULongConstant ((ulong) Value, Location);
1716 if (target_type == TypeManager.double_type)
1717 return new DoubleConstant ((double) Value, Location);
1718 if (target_type == TypeManager.char_type) {
1719 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1720 return new CharConstant ((char) Value, Location);
1722 if (target_type == TypeManager.decimal_type)
1723 return new DecimalConstant ((decimal) Value, Location);
1730 public class DoubleConstant : Constant {
1731 public readonly double Value;
1733 public DoubleConstant (double v, Location loc):
1736 type = TypeManager.double_type;
1737 eclass = ExprClass.Value;
1741 public override void Emit (EmitContext ec)
1743 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1746 public override string AsString ()
1748 return Value.ToString ();
1751 public override object GetValue ()
1756 public override DoubleConstant ConvertToDouble ()
1761 public override FloatConstant ConvertToFloat ()
1766 public override ULongConstant ConvertToULong ()
1771 public override LongConstant ConvertToLong ()
1776 public override UIntConstant ConvertToUInt ()
1781 public override IntConstant ConvertToInt ()
1786 public override Constant Increment ()
1788 return new DoubleConstant (checked(Value + 1), loc);
1791 public override bool IsDefaultValue {
1797 public override bool IsNegative {
1803 public override Constant Reduce (bool inCheckedContext, Type target_type)
1805 if (target_type == TypeManager.byte_type) {
1806 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1807 return new ByteConstant ((byte) Value, Location);
1809 if (target_type == TypeManager.sbyte_type) {
1810 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1811 return new SByteConstant ((sbyte) Value, Location);
1813 if (target_type == TypeManager.short_type) {
1814 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1815 return new ShortConstant ((short) Value, Location);
1817 if (target_type == TypeManager.ushort_type) {
1818 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1819 return new UShortConstant ((ushort) Value, Location);
1821 if (target_type == TypeManager.int32_type) {
1822 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1823 return new IntConstant ((int) Value, Location);
1825 if (target_type == TypeManager.uint32_type) {
1826 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1827 return new UIntConstant ((uint) Value, Location);
1829 if (target_type == TypeManager.int64_type) {
1830 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1831 return new LongConstant ((long) Value, Location);
1833 if (target_type == TypeManager.uint64_type) {
1834 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1835 return new ULongConstant ((ulong) Value, Location);
1837 if (target_type == TypeManager.float_type)
1838 return new FloatConstant ((float) Value, Location);
1839 if (target_type == TypeManager.char_type) {
1840 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1841 return new CharConstant ((char) Value, Location);
1843 if (target_type == TypeManager.decimal_type)
1844 return new DecimalConstant ((decimal) Value, Location);
1851 public class DecimalConstant : Constant {
1852 public readonly decimal Value;
1854 public DecimalConstant (decimal d, Location loc):
1857 type = TypeManager.decimal_type;
1858 eclass = ExprClass.Value;
1862 override public string AsString ()
1864 return Value.ToString ();
1867 public override object GetValue ()
1869 return (object) Value;
1872 public override void Emit (EmitContext ec)
1874 ILGenerator ig = ec.ig;
1876 int [] words = Decimal.GetBits (Value);
1877 int power = (words [3] >> 16) & 0xff;
1879 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1881 IntConstant.EmitInt (ig, (int)Value);
1882 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1888 // FIXME: we could optimize this, and call a better
1892 IntConstant.EmitInt (ig, words [0]);
1893 IntConstant.EmitInt (ig, words [1]);
1894 IntConstant.EmitInt (ig, words [2]);
1897 IntConstant.EmitInt (ig, words [3] >> 31);
1900 IntConstant.EmitInt (ig, power);
1902 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1905 public override Constant Increment ()
1907 return new DecimalConstant (checked (Value + 1), loc);
1910 public override bool IsDefaultValue {
1916 public override bool IsNegative {
1922 public override Constant Reduce (bool inCheckedContext, Type target_type)
1924 if (target_type == TypeManager.sbyte_type)
1925 return new SByteConstant ((sbyte)Value, loc);
1926 if (target_type == TypeManager.byte_type)
1927 return new ByteConstant ((byte)Value, loc);
1928 if (target_type == TypeManager.short_type)
1929 return new ShortConstant ((short)Value, loc);
1930 if (target_type == TypeManager.ushort_type)
1931 return new UShortConstant ((ushort)Value, loc);
1932 if (target_type == TypeManager.int32_type)
1933 return new IntConstant ((int)Value, loc);
1934 if (target_type == TypeManager.uint32_type)
1935 return new UIntConstant ((uint)Value, loc);
1936 if (target_type == TypeManager.int64_type)
1937 return new LongConstant ((long)Value, loc);
1938 if (target_type == TypeManager.uint64_type)
1939 return new ULongConstant ((ulong)Value, loc);
1940 if (target_type == TypeManager.char_type)
1941 return new CharConstant ((char)Value, loc);
1942 if (target_type == TypeManager.float_type)
1943 return new FloatConstant ((float)Value, loc);
1944 if (target_type == TypeManager.double_type)
1945 return new DoubleConstant ((double)Value, loc);
1952 public class StringConstant : Constant {
1953 public readonly string Value;
1955 public StringConstant (string s, Location loc):
1958 type = TypeManager.string_type;
1959 eclass = ExprClass.Value;
1963 // FIXME: Escape the string.
1964 override public string AsString ()
1966 return "\"" + Value + "\"";
1969 public override object GetValue ()
1974 public override void Emit (EmitContext ec)
1977 ec.ig.Emit (OpCodes.Ldnull);
1979 ec.ig.Emit (OpCodes.Ldstr, Value);
1982 public override Constant Increment ()
1984 throw new NotSupportedException ();
1987 public override bool IsDefaultValue {
1989 return Value == null;
1993 public override bool IsNegative {
1999 public override Constant Reduce (bool inCheckedContext, Type target_type)