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 = ToType (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)
74 // The various ToXXXX conversion functions are used by the constant
75 // folding evaluator. A null value is returned if the conversion is
78 // Note: not all the patterns for catching `implicit_conv' are the same.
79 // some implicit conversions can never be performed between two types
80 // even if the conversion would be lossless (for example short to uint),
81 // but some conversions are explicitly permitted by the standard provided
82 // that there will be no loss of information (for example, int to uint).
84 public DoubleConstant ToDouble (Location loc)
86 DoubleConstant c = ConvertToDouble ();
89 Error_ValueCannotBeConverted (loc, TypeManager.double_type, false);
94 public FloatConstant ToFloat (Location loc)
96 FloatConstant c = ConvertToFloat ();
99 Error_ValueCannotBeConverted (loc, TypeManager.float_type, false);
104 public ULongConstant ToULong (Location loc)
106 ULongConstant c = ConvertToULong ();
109 Error_ValueCannotBeConverted (loc, TypeManager.uint64_type, false);
114 public LongConstant ToLong (Location loc)
116 LongConstant c = ConvertToLong ();
119 Error_ValueCannotBeConverted (loc, TypeManager.int64_type, false);
124 public UIntConstant ToUInt (Location loc)
126 UIntConstant c = ConvertToUInt ();
129 Error_ValueCannotBeConverted (loc, TypeManager.uint32_type, false);
134 public IntConstant ToInt (Location loc)
136 IntConstant c = ConvertToInt ();
139 Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
144 public DecimalConstant ToDecimal (Location loc)
146 DecimalConstant c = ConvertToDecimal ();
149 Error_ValueCannotBeConverted (loc, TypeManager.decimal_type, false);
154 public virtual Constant ToType (Type type, Location loc)
159 if (type == TypeManager.object_type)
162 if (!Convert.ImplicitStandardConversionExists (this, type)){
163 Error_ValueCannotBeConverted (loc, type, false);
167 // Special-case: The 0 literal can be converted to an enum value,
168 // and ImplicitStandardConversionExists will return true in that case.
169 if (IsZeroInteger && Type == TypeManager.int32_type && TypeManager.IsEnumType (type)) {
170 return new EnumConstant (this, type);
174 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
176 Error_ValueCannotBeConverted (loc, type, false);
179 // We should always catch the error before this is ever
180 // reached, by calling Convert.ImplicitStandardConversionExists
182 throw new Exception (
183 String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
187 if (type == TypeManager.int32_type)
188 retval = new IntConstant ((int) constant_value, loc);
189 else if (type == TypeManager.uint32_type)
190 retval = new UIntConstant ((uint) constant_value, loc);
191 else if (type == TypeManager.int64_type)
192 retval = new LongConstant ((long) constant_value, loc);
193 else if (type == TypeManager.uint64_type)
194 retval = new ULongConstant ((ulong) constant_value, loc);
195 else if (type == TypeManager.float_type)
196 retval = new FloatConstant ((float) constant_value, loc);
197 else if (type == TypeManager.double_type)
198 retval = new DoubleConstant ((double) constant_value, loc);
199 else if (type == TypeManager.string_type)
200 retval = new StringConstant ((string) constant_value, loc);
201 else if (type == TypeManager.short_type)
202 retval = new ShortConstant ((short) constant_value, loc);
203 else if (type == TypeManager.ushort_type)
204 retval = new UShortConstant ((ushort) constant_value, loc);
205 else if (type == TypeManager.sbyte_type)
206 retval = new SByteConstant ((sbyte) constant_value, loc);
207 else if (type == TypeManager.byte_type)
208 retval = new ByteConstant ((byte) constant_value, loc);
209 else if (type == TypeManager.char_type)
210 retval = new CharConstant ((char) constant_value, loc);
211 else if (type == TypeManager.bool_type)
212 retval = new BoolConstant ((bool) constant_value, loc);
213 else if (type == TypeManager.decimal_type)
214 retval = new DecimalConstant ((decimal) constant_value, loc);
216 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
221 protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
223 if (!inCheckedContext)
227 throw new OverflowException ();
230 protected static void CheckRange (bool inCheckedContext, double value, long min, long max)
232 if (!inCheckedContext)
235 if (((value < min) || (value > max)))
236 throw new OverflowException ();
238 if (double.IsNaN (value))
239 throw new OverflowException ();
242 protected static void CheckRange (bool inCheckedContext, double value, ulong min, ulong max)
244 if (!inCheckedContext)
247 if (((value < min) || (value > max)))
248 throw new OverflowException ();
250 if (double.IsNaN (value))
251 throw new OverflowException ();
254 protected static void CheckUnsigned (bool inCheckedContext, long value)
256 if (!inCheckedContext)
260 throw new OverflowException ();
264 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
265 /// It throws OverflowException
267 public abstract Constant Reduce (bool inCheckedContext, Type target_type);
270 /// Attempts to do a compile-time folding of a constant cast.
272 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
275 return TryReduce (ec, target_type);
277 catch (OverflowException) {
278 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
279 GetValue ().ToString (), TypeManager.CSharpName (target_type));
284 Constant TryReduce (EmitContext ec, Type target_type)
286 if (Type == target_type)
289 if (TypeManager.IsEnumType (target_type)) {
290 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
294 return new EnumConstant (c, target_type);
297 return Reduce (ec.ConstantCheckState, target_type);
301 public virtual DecimalConstant ConvertToDecimal ()
306 public virtual DoubleConstant ConvertToDouble ()
311 public virtual FloatConstant ConvertToFloat ()
316 public virtual ULongConstant ConvertToULong ()
321 public virtual LongConstant ConvertToLong ()
326 public virtual UIntConstant ConvertToUInt ()
331 public virtual IntConstant ConvertToInt ()
336 public abstract Constant Increment ();
339 /// Need to pass type as the constant can require a boxing
340 /// and in such case no optimization is possible
342 public bool IsDefaultInitializer (Type type)
345 return IsDefaultValue;
347 return Type == TypeManager.null_type;
350 public abstract bool IsDefaultValue {
354 public abstract bool IsNegative {
359 // Returns true iff 1) the stack type of this is one of Object,
360 // int32, int64 and 2) this == 0 or this == null.
362 public virtual bool IsZeroInteger {
363 get { return false; }
367 public abstract class IntegralConstant : Constant {
368 protected IntegralConstant (Location loc) :
373 public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
376 Reduce (true, target);
377 base.Error_ValueCannotBeConverted (loc, target, expl);
381 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
382 GetValue ().ToString (), TypeManager.CSharpName (target));
387 public class BoolConstant : Constant {
388 public readonly bool Value;
390 public BoolConstant (bool val, Location loc):
393 type = TypeManager.bool_type;
394 eclass = ExprClass.Value;
399 override public string AsString ()
401 return Value ? "true" : "false";
404 public override object GetValue ()
406 return (object) Value;
410 public override void Emit (EmitContext ec)
413 ec.ig.Emit (OpCodes.Ldc_I4_1);
415 ec.ig.Emit (OpCodes.Ldc_I4_0);
418 public override Constant Increment ()
420 throw new NotSupportedException ();
423 public override bool IsDefaultValue {
429 public override bool IsNegative {
435 public override bool IsZeroInteger {
436 get { return Value == false; }
439 public override Constant Reduce (bool inCheckedContext, Type target_type)
446 public class ByteConstant : IntegralConstant {
447 public readonly byte Value;
449 public ByteConstant (byte v, Location loc):
452 type = TypeManager.byte_type;
453 eclass = ExprClass.Value;
457 public override void Emit (EmitContext ec)
459 IntLiteral.EmitInt (ec.ig, Value);
462 public override string AsString ()
464 return Value.ToString ();
467 public override object GetValue ()
472 public override DoubleConstant ConvertToDouble ()
474 return new DoubleConstant (Value, loc);
477 public override FloatConstant ConvertToFloat ()
479 return new FloatConstant (Value, loc);
482 public override ULongConstant ConvertToULong ()
484 return new ULongConstant (Value, loc);
487 public override LongConstant ConvertToLong ()
489 return new LongConstant (Value, loc);
492 public override UIntConstant ConvertToUInt ()
494 return new UIntConstant (Value, loc);
497 public override IntConstant ConvertToInt ()
499 return new IntConstant (Value, loc);
502 public override Constant Increment ()
504 return new ByteConstant (checked ((byte)(Value + 1)), loc);
507 public override bool IsDefaultValue {
513 public override bool IsNegative {
519 public override bool IsZeroInteger {
520 get { return Value == 0; }
523 public override Constant Reduce (bool inCheckedContext, Type target_type)
525 if (target_type == TypeManager.sbyte_type) {
526 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
527 return new SByteConstant ((sbyte) Value, Location);
529 if (target_type == TypeManager.short_type)
530 return new ShortConstant ((short) Value, Location);
531 if (target_type == TypeManager.ushort_type)
532 return new UShortConstant ((ushort) Value, Location);
533 if (target_type == TypeManager.int32_type)
534 return new IntConstant ((int) Value, Location);
535 if (target_type == TypeManager.uint32_type)
536 return new UIntConstant ((uint) Value, Location);
537 if (target_type == TypeManager.int64_type)
538 return new LongConstant ((long) Value, Location);
539 if (target_type == TypeManager.uint64_type)
540 return new ULongConstant ((ulong) Value, Location);
541 if (target_type == TypeManager.float_type)
542 return new FloatConstant ((float) Value, Location);
543 if (target_type == TypeManager.double_type)
544 return new DoubleConstant ((double) Value, Location);
545 if (target_type == TypeManager.char_type)
546 return new CharConstant ((char) Value, Location);
547 if (target_type == TypeManager.decimal_type)
548 return new DecimalConstant ((decimal) Value, Location);
555 public class CharConstant : Constant {
556 public readonly char Value;
558 public CharConstant (char v, Location loc):
561 type = TypeManager.char_type;
562 eclass = ExprClass.Value;
566 public override void Emit (EmitContext ec)
568 IntLiteral.EmitInt (ec.ig, Value);
571 static public string descape (char c)
597 return c.ToString ();
600 public override string AsString ()
602 return "\"" + descape (Value) + "\"";
605 public override object GetValue ()
610 public override DoubleConstant ConvertToDouble ()
612 return new DoubleConstant (Value, loc);
615 public override FloatConstant ConvertToFloat ()
617 return new FloatConstant (Value, loc);
620 public override ULongConstant ConvertToULong ()
622 return new ULongConstant (Value, loc);
625 public override LongConstant ConvertToLong ()
627 return new LongConstant (Value, loc);
630 public override UIntConstant ConvertToUInt ()
632 return new UIntConstant (Value, loc);
635 public override IntConstant ConvertToInt ()
637 return new IntConstant (Value, loc);
640 public override Constant Increment ()
642 return new CharConstant (checked ((char)(Value + 1)), loc);
645 public override bool IsDefaultValue {
651 public override bool IsNegative {
657 public override bool IsZeroInteger {
658 get { return Value == '\0'; }
661 public override Constant Reduce (bool inCheckedContext, Type target_type)
663 if (target_type == TypeManager.byte_type) {
664 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
665 return new ByteConstant ((byte) Value, Location);
667 if (target_type == TypeManager.sbyte_type) {
668 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
669 return new SByteConstant ((sbyte) Value, Location);
671 if (target_type == TypeManager.short_type) {
672 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
673 return new ShortConstant ((short) Value, Location);
675 if (target_type == TypeManager.int32_type)
676 return new IntConstant ((int) Value, Location);
677 if (target_type == TypeManager.uint32_type)
678 return new UIntConstant ((uint) Value, Location);
679 if (target_type == TypeManager.int64_type)
680 return new LongConstant ((long) Value, Location);
681 if (target_type == TypeManager.uint64_type)
682 return new ULongConstant ((ulong) Value, Location);
683 if (target_type == TypeManager.float_type)
684 return new FloatConstant ((float) Value, Location);
685 if (target_type == TypeManager.double_type)
686 return new DoubleConstant ((double) Value, Location);
687 if (target_type == TypeManager.decimal_type)
688 return new DecimalConstant ((decimal) Value, Location);
695 public class SByteConstant : IntegralConstant {
696 public readonly sbyte Value;
698 public SByteConstant (sbyte v, Location loc):
701 type = TypeManager.sbyte_type;
702 eclass = ExprClass.Value;
706 public override void Emit (EmitContext ec)
708 IntLiteral.EmitInt (ec.ig, Value);
711 public override string AsString ()
713 return Value.ToString ();
716 public override object GetValue ()
721 public override DoubleConstant ConvertToDouble ()
723 return new DoubleConstant (Value, loc);
726 public override FloatConstant ConvertToFloat ()
728 return new FloatConstant (Value, loc);
731 public override ULongConstant ConvertToULong ()
734 return new ULongConstant ((ulong) Value, loc);
739 public override LongConstant ConvertToLong ()
741 return new LongConstant (Value, loc);
744 public override UIntConstant ConvertToUInt ()
749 public override IntConstant ConvertToInt ()
751 return new IntConstant (Value, loc);
754 public override Constant Increment ()
756 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
759 public override bool IsDefaultValue {
765 public override bool IsNegative {
771 public override bool IsZeroInteger {
772 get { return Value == 0; }
775 public override Constant Reduce (bool inCheckedContext, Type target_type)
777 if (target_type == TypeManager.byte_type) {
778 CheckUnsigned (inCheckedContext, Value);
779 return new ByteConstant ((byte) Value, Location);
781 if (target_type == TypeManager.short_type)
782 return new ShortConstant ((short) Value, Location);
783 if (target_type == TypeManager.ushort_type) {
784 CheckUnsigned (inCheckedContext, Value);
785 return new UShortConstant ((ushort) Value, Location);
786 } if (target_type == TypeManager.int32_type)
787 return new IntConstant ((int) Value, Location);
788 if (target_type == TypeManager.uint32_type) {
789 CheckUnsigned (inCheckedContext, Value);
790 return new UIntConstant ((uint) Value, Location);
791 } if (target_type == TypeManager.int64_type)
792 return new LongConstant ((long) Value, Location);
793 if (target_type == TypeManager.uint64_type) {
794 CheckUnsigned (inCheckedContext, Value);
795 return new ULongConstant ((ulong) Value, Location);
797 if (target_type == TypeManager.float_type)
798 return new FloatConstant ((float) Value, Location);
799 if (target_type == TypeManager.double_type)
800 return new DoubleConstant ((double) Value, Location);
801 if (target_type == TypeManager.char_type) {
802 CheckUnsigned (inCheckedContext, Value);
803 return new CharConstant ((char) Value, Location);
805 if (target_type == TypeManager.decimal_type)
806 return new DecimalConstant ((decimal) Value, Location);
813 public class ShortConstant : IntegralConstant {
814 public readonly short Value;
816 public ShortConstant (short v, Location loc):
819 type = TypeManager.short_type;
820 eclass = ExprClass.Value;
824 public override void Emit (EmitContext ec)
826 IntLiteral.EmitInt (ec.ig, Value);
829 public override string AsString ()
831 return Value.ToString ();
834 public override object GetValue ()
839 public override DoubleConstant ConvertToDouble ()
841 return new DoubleConstant (Value, loc);
844 public override FloatConstant ConvertToFloat ()
846 return new FloatConstant (Value, loc);
849 public override ULongConstant ConvertToULong ()
854 public override LongConstant ConvertToLong ()
856 return new LongConstant (Value, loc);
859 public override UIntConstant ConvertToUInt ()
864 public override IntConstant ConvertToInt ()
866 return new IntConstant (Value, loc);
869 public override Constant Increment ()
871 return new ShortConstant (checked((short)(Value + 1)), loc);
874 public override bool IsDefaultValue {
880 public override bool IsZeroInteger {
881 get { return Value == 0; }
884 public override bool IsNegative {
890 public override Constant Reduce (bool inCheckedContext, Type target_type)
892 if (target_type == TypeManager.byte_type) {
893 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
894 return new ByteConstant ((byte) Value, Location);
896 if (target_type == TypeManager.sbyte_type) {
897 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
898 return new SByteConstant ((sbyte) Value, Location);
900 if (target_type == TypeManager.ushort_type) {
901 CheckUnsigned (inCheckedContext, Value);
902 return new UShortConstant ((ushort) Value, Location);
904 if (target_type == TypeManager.int32_type)
905 return new IntConstant ((int) Value, Location);
906 if (target_type == TypeManager.uint32_type) {
907 CheckUnsigned (inCheckedContext, Value);
908 return new UIntConstant ((uint) Value, Location);
910 if (target_type == TypeManager.int64_type)
911 return new LongConstant ((long) Value, Location);
912 if (target_type == TypeManager.uint64_type) {
913 CheckUnsigned (inCheckedContext, Value);
914 return new ULongConstant ((ulong) Value, Location);
916 if (target_type == TypeManager.float_type)
917 return new FloatConstant ((float) Value, Location);
918 if (target_type == TypeManager.double_type)
919 return new DoubleConstant ((double) Value, Location);
920 if (target_type == TypeManager.char_type) {
921 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
922 return new CharConstant ((char) Value, Location);
924 if (target_type == TypeManager.decimal_type)
925 return new DecimalConstant ((decimal) Value, Location);
932 public class UShortConstant : IntegralConstant {
933 public readonly ushort Value;
935 public UShortConstant (ushort v, Location loc):
938 type = TypeManager.ushort_type;
939 eclass = ExprClass.Value;
943 public override void Emit (EmitContext ec)
945 IntLiteral.EmitInt (ec.ig, Value);
948 public override string AsString ()
950 return Value.ToString ();
953 public override object GetValue ()
958 public override DoubleConstant ConvertToDouble ()
960 return new DoubleConstant (Value, loc);
963 public override FloatConstant ConvertToFloat ()
965 return new FloatConstant (Value, loc);
968 public override ULongConstant ConvertToULong ()
970 return new ULongConstant (Value, loc);
973 public override LongConstant ConvertToLong ()
975 return new LongConstant (Value, loc);
978 public override UIntConstant ConvertToUInt ()
980 return new UIntConstant (Value, loc);
983 public override IntConstant ConvertToInt ()
985 return new IntConstant (Value, loc);
988 public override Constant Increment ()
990 return new UShortConstant (checked((ushort)(Value + 1)), loc);
993 public override bool IsDefaultValue {
999 public override bool IsNegative {
1005 public override bool IsZeroInteger {
1006 get { return Value == 0; }
1009 public override Constant Reduce (bool inCheckedContext, Type target_type)
1011 if (target_type == TypeManager.byte_type) {
1012 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1013 return new ByteConstant ((byte) Value, Location);
1015 if (target_type == TypeManager.sbyte_type) {
1016 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1017 return new SByteConstant ((sbyte) Value, Location);
1019 if (target_type == TypeManager.short_type) {
1020 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1021 return new ShortConstant ((short) Value, Location);
1023 if (target_type == TypeManager.int32_type)
1024 return new IntConstant ((int) Value, Location);
1025 if (target_type == TypeManager.uint32_type)
1026 return new UIntConstant ((uint) Value, Location);
1027 if (target_type == TypeManager.int64_type)
1028 return new LongConstant ((long) Value, Location);
1029 if (target_type == TypeManager.uint64_type)
1030 return new ULongConstant ((ulong) Value, Location);
1031 if (target_type == TypeManager.float_type)
1032 return new FloatConstant ((float) Value, Location);
1033 if (target_type == TypeManager.double_type)
1034 return new DoubleConstant ((double) Value, Location);
1035 if (target_type == TypeManager.char_type) {
1036 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1037 return new CharConstant ((char) Value, Location);
1039 if (target_type == TypeManager.decimal_type)
1040 return new DecimalConstant ((decimal) Value, Location);
1046 public class IntConstant : IntegralConstant {
1047 public readonly int Value;
1049 public IntConstant (int v, Location loc):
1052 type = TypeManager.int32_type;
1053 eclass = ExprClass.Value;
1057 static public void EmitInt (ILGenerator ig, int i)
1061 ig.Emit (OpCodes.Ldc_I4_M1);
1065 ig.Emit (OpCodes.Ldc_I4_0);
1069 ig.Emit (OpCodes.Ldc_I4_1);
1073 ig.Emit (OpCodes.Ldc_I4_2);
1077 ig.Emit (OpCodes.Ldc_I4_3);
1081 ig.Emit (OpCodes.Ldc_I4_4);
1085 ig.Emit (OpCodes.Ldc_I4_5);
1089 ig.Emit (OpCodes.Ldc_I4_6);
1093 ig.Emit (OpCodes.Ldc_I4_7);
1097 ig.Emit (OpCodes.Ldc_I4_8);
1101 if (i >= -128 && i <= 127){
1102 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
1104 ig.Emit (OpCodes.Ldc_I4, i);
1109 public override void Emit (EmitContext ec)
1111 EmitInt (ec.ig, Value);
1114 public override string AsString ()
1116 return Value.ToString ();
1119 public override object GetValue ()
1124 public override DecimalConstant ConvertToDecimal()
1126 return new DecimalConstant (Value, loc);
1129 public override DoubleConstant ConvertToDouble ()
1131 return new DoubleConstant (Value, loc);
1134 public override FloatConstant ConvertToFloat ()
1136 return new FloatConstant (Value, loc);
1139 public override ULongConstant ConvertToULong ()
1144 return new ULongConstant ((ulong) Value, loc);
1147 public override LongConstant ConvertToLong ()
1149 return new LongConstant (Value, loc);
1152 public override UIntConstant ConvertToUInt ()
1157 return new UIntConstant ((uint) Value, loc);
1160 public override IntConstant ConvertToInt ()
1165 public override Constant Increment ()
1167 return new IntConstant (checked(Value + 1), loc);
1170 public override bool IsDefaultValue {
1176 public override bool IsNegative {
1182 public override bool IsZeroInteger {
1183 get { return Value == 0; }
1186 public override Constant Reduce (bool inCheckedContext, Type target_type)
1188 if (target_type == TypeManager.byte_type) {
1189 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1190 return new ByteConstant ((byte) Value, Location);
1192 if (target_type == TypeManager.sbyte_type) {
1193 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1194 return new SByteConstant ((sbyte) Value, Location);
1196 if (target_type == TypeManager.short_type) {
1197 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1198 return new ShortConstant ((short) Value, Location);
1200 if (target_type == TypeManager.ushort_type) {
1201 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1202 return new UShortConstant ((ushort) Value, Location);
1204 if (target_type == TypeManager.uint32_type) {
1205 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1206 return new UIntConstant ((uint) Value, Location);
1208 if (target_type == TypeManager.int64_type)
1209 return new LongConstant ((long) Value, Location);
1210 if (target_type == TypeManager.uint64_type) {
1211 CheckUnsigned (inCheckedContext, Value);
1212 return new ULongConstant ((ulong) Value, Location);
1214 if (target_type == TypeManager.float_type)
1215 return new FloatConstant ((float) Value, Location);
1216 if (target_type == TypeManager.double_type)
1217 return new DoubleConstant ((double) Value, Location);
1218 if (target_type == TypeManager.char_type) {
1219 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1220 return new CharConstant ((char) Value, Location);
1222 if (target_type == TypeManager.decimal_type)
1223 return new DecimalConstant ((decimal) Value, Location);
1229 public class UIntConstant : IntegralConstant {
1230 public readonly uint Value;
1232 public UIntConstant (uint v, Location loc):
1235 type = TypeManager.uint32_type;
1236 eclass = ExprClass.Value;
1240 public override void Emit (EmitContext ec)
1242 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1245 public override string AsString ()
1247 return Value.ToString ();
1250 public override object GetValue ()
1255 public override DoubleConstant ConvertToDouble ()
1257 return new DoubleConstant (Value, loc);
1260 public override FloatConstant ConvertToFloat ()
1262 return new FloatConstant (Value, loc);
1265 public override ULongConstant ConvertToULong ()
1267 return new ULongConstant (Value, loc);
1270 public override LongConstant ConvertToLong ()
1272 return new LongConstant (Value, loc);
1275 public override UIntConstant ConvertToUInt ()
1280 public override IntConstant ConvertToInt ()
1285 public override Constant Increment ()
1287 return new UIntConstant (checked(Value + 1), loc);
1290 public override bool IsDefaultValue {
1296 public override bool IsNegative {
1302 public override bool IsZeroInteger {
1303 get { return Value == 0; }
1306 public override Constant Reduce (bool inCheckedContext, Type target_type)
1308 if (target_type == TypeManager.byte_type) {
1309 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1310 return new ByteConstant ((byte) Value, Location);
1312 if (target_type == TypeManager.sbyte_type) {
1313 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1314 return new SByteConstant ((sbyte) Value, Location);
1316 if (target_type == TypeManager.short_type) {
1317 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1318 return new ShortConstant ((short) Value, Location);
1320 if (target_type == TypeManager.ushort_type) {
1321 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1322 return new UShortConstant ((ushort) Value, Location);
1324 if (target_type == TypeManager.int32_type) {
1325 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1326 return new IntConstant ((int) Value, Location);
1328 if (target_type == TypeManager.int64_type)
1329 return new LongConstant ((long) Value, Location);
1330 if (target_type == TypeManager.uint64_type)
1331 return new ULongConstant ((ulong) Value, Location);
1332 if (target_type == TypeManager.float_type)
1333 return new FloatConstant ((float) Value, Location);
1334 if (target_type == TypeManager.double_type)
1335 return new DoubleConstant ((double) Value, Location);
1336 if (target_type == TypeManager.char_type) {
1337 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1338 return new CharConstant ((char) Value, Location);
1340 if (target_type == TypeManager.decimal_type)
1341 return new DecimalConstant ((decimal) Value, Location);
1348 public class LongConstant : IntegralConstant {
1349 public readonly long Value;
1351 public LongConstant (long v, Location loc):
1354 type = TypeManager.int64_type;
1355 eclass = ExprClass.Value;
1359 public override void Emit (EmitContext ec)
1361 EmitLong (ec.ig, Value);
1364 static public void EmitLong (ILGenerator ig, long l)
1366 if (l >= int.MinValue && l <= int.MaxValue) {
1367 IntLiteral.EmitInt (ig, unchecked ((int) l));
1368 ig.Emit (OpCodes.Conv_I8);
1371 ig.Emit (OpCodes.Ldc_I8, l);
1374 public override string AsString ()
1376 return Value.ToString ();
1379 public override object GetValue ()
1384 public override DoubleConstant ConvertToDouble ()
1386 return new DoubleConstant (Value, loc);
1389 public override FloatConstant ConvertToFloat ()
1391 return new FloatConstant (Value, loc);
1394 public override ULongConstant ConvertToULong ()
1399 return new ULongConstant ((ulong) Value, loc);
1402 public override LongConstant ConvertToLong ()
1407 public override UIntConstant ConvertToUInt ()
1412 public override IntConstant ConvertToInt ()
1417 public override Constant Increment ()
1419 return new LongConstant (checked(Value + 1), loc);
1422 public override bool IsDefaultValue {
1428 public override bool IsNegative {
1434 public override bool IsZeroInteger {
1435 get { return Value == 0; }
1438 public override Constant Reduce (bool inCheckedContext, Type target_type)
1440 if (target_type == TypeManager.byte_type) {
1441 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1442 return new ByteConstant ((byte) Value, Location);
1444 if (target_type == TypeManager.sbyte_type) {
1445 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1446 return new SByteConstant ((sbyte) Value, Location);
1448 if (target_type == TypeManager.short_type) {
1449 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1450 return new ShortConstant ((short) Value, Location);
1452 if (target_type == TypeManager.ushort_type) {
1453 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1454 return new UShortConstant ((ushort) Value, Location);
1456 if (target_type == TypeManager.int32_type) {
1457 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1458 return new IntConstant ((int) Value, Location);
1460 if (target_type == TypeManager.uint32_type) {
1461 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1462 return new UIntConstant ((uint) Value, Location);
1464 if (target_type == TypeManager.uint64_type) {
1465 CheckUnsigned (inCheckedContext, Value);
1466 return new ULongConstant ((ulong) Value, Location);
1468 if (target_type == TypeManager.float_type)
1469 return new FloatConstant ((float) Value, Location);
1470 if (target_type == TypeManager.double_type)
1471 return new DoubleConstant ((double) Value, Location);
1472 if (target_type == TypeManager.char_type) {
1473 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1474 return new CharConstant ((char) Value, Location);
1476 if (target_type == TypeManager.decimal_type)
1477 return new DecimalConstant ((decimal) Value, Location);
1484 public class ULongConstant : IntegralConstant {
1485 public readonly ulong Value;
1487 public ULongConstant (ulong v, Location loc):
1490 type = TypeManager.uint64_type;
1491 eclass = ExprClass.Value;
1495 public override void Emit (EmitContext ec)
1497 ILGenerator ig = ec.ig;
1499 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1502 public override string AsString ()
1504 return Value.ToString ();
1507 public override object GetValue ()
1512 public override DoubleConstant ConvertToDouble ()
1514 return new DoubleConstant (Value, loc);
1517 public override FloatConstant ConvertToFloat ()
1519 return new FloatConstant (Value, loc);
1522 public override ULongConstant ConvertToULong ()
1527 public override LongConstant ConvertToLong ()
1532 public override UIntConstant ConvertToUInt ()
1537 public override IntConstant ConvertToInt ()
1542 public override Constant Increment ()
1544 return new ULongConstant (checked(Value + 1), loc);
1547 public override bool IsDefaultValue {
1553 public override bool IsNegative {
1559 public override bool IsZeroInteger {
1560 get { return Value == 0; }
1563 public override Constant Reduce (bool inCheckedContext, Type target_type)
1565 if (target_type == TypeManager.byte_type) {
1566 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1567 return new ByteConstant ((byte) Value, Location);
1569 if (target_type == TypeManager.sbyte_type) {
1570 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1571 return new SByteConstant ((sbyte) Value, Location);
1573 if (target_type == TypeManager.short_type) {
1574 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1575 return new ShortConstant ((short) Value, Location);
1577 if (target_type == TypeManager.ushort_type) {
1578 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1579 return new UShortConstant ((ushort) Value, Location);
1581 if (target_type == TypeManager.int32_type) {
1582 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1583 return new IntConstant ((int) Value, Location);
1585 if (target_type == TypeManager.uint32_type) {
1586 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1587 return new UIntConstant ((uint) Value, Location);
1589 if (target_type == TypeManager.int64_type) {
1590 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1591 return new LongConstant ((long) Value, Location);
1593 if (target_type == TypeManager.float_type)
1594 return new FloatConstant ((float) Value, Location);
1595 if (target_type == TypeManager.double_type)
1596 return new DoubleConstant ((double) Value, Location);
1597 if (target_type == TypeManager.char_type) {
1598 CheckRange (inCheckedContext, Value, Char.MaxValue);
1599 return new CharConstant ((char) Value, Location);
1601 if (target_type == TypeManager.decimal_type)
1602 return new DecimalConstant ((decimal) Value, Location);
1609 public class FloatConstant : Constant {
1610 public readonly float Value;
1612 public FloatConstant (float v, Location loc):
1615 type = TypeManager.float_type;
1616 eclass = ExprClass.Value;
1620 public override void Emit (EmitContext ec)
1622 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1625 public override string AsString ()
1627 return Value.ToString ();
1630 public override object GetValue ()
1635 public override DoubleConstant ConvertToDouble ()
1637 return new DoubleConstant (Value, loc);
1640 public override FloatConstant ConvertToFloat ()
1645 public override LongConstant ConvertToLong ()
1650 public override UIntConstant ConvertToUInt ()
1655 public override IntConstant ConvertToInt ()
1660 public override Constant Increment ()
1662 return new FloatConstant (checked(Value + 1), loc);
1665 public override bool IsDefaultValue {
1671 public override bool IsNegative {
1677 public override Constant Reduce (bool inCheckedContext, Type target_type)
1679 if (target_type == TypeManager.byte_type) {
1680 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1681 return new ByteConstant ((byte) Value, Location);
1683 if (target_type == TypeManager.sbyte_type) {
1684 CheckRange (inCheckedContext, Value, sbyte.MinValue, sbyte.MaxValue);
1685 return new SByteConstant ((sbyte) Value, Location);
1687 if (target_type == TypeManager.short_type) {
1688 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1689 return new ShortConstant ((short) Value, Location);
1691 if (target_type == TypeManager.ushort_type) {
1692 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1693 return new UShortConstant ((ushort) Value, Location);
1695 if (target_type == TypeManager.int32_type) {
1696 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1697 return new IntConstant ((int) Value, Location);
1699 if (target_type == TypeManager.uint32_type) {
1700 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1701 return new UIntConstant ((uint) Value, Location);
1703 if (target_type == TypeManager.int64_type) {
1704 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1705 return new LongConstant ((long) Value, Location);
1707 if (target_type == TypeManager.uint64_type) {
1708 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1709 return new ULongConstant ((ulong) Value, Location);
1711 if (target_type == TypeManager.double_type)
1712 return new DoubleConstant ((double) Value, Location);
1713 if (target_type == TypeManager.char_type) {
1714 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1715 return new CharConstant ((char) Value, Location);
1717 if (target_type == TypeManager.decimal_type)
1718 return new DecimalConstant ((decimal) Value, Location);
1725 public class DoubleConstant : Constant {
1726 public readonly double Value;
1728 public DoubleConstant (double v, Location loc):
1731 type = TypeManager.double_type;
1732 eclass = ExprClass.Value;
1736 public override void Emit (EmitContext ec)
1738 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1741 public override string AsString ()
1743 return Value.ToString ();
1746 public override object GetValue ()
1751 public override DoubleConstant ConvertToDouble ()
1756 public override FloatConstant ConvertToFloat ()
1761 public override ULongConstant ConvertToULong ()
1766 public override LongConstant ConvertToLong ()
1771 public override UIntConstant ConvertToUInt ()
1776 public override IntConstant ConvertToInt ()
1781 public override Constant Increment ()
1783 return new DoubleConstant (checked(Value + 1), loc);
1786 public override bool IsDefaultValue {
1792 public override bool IsNegative {
1798 public override Constant Reduce (bool inCheckedContext, Type target_type)
1800 if (target_type == TypeManager.byte_type) {
1801 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1802 return new ByteConstant ((byte) Value, Location);
1804 if (target_type == TypeManager.sbyte_type) {
1805 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1806 return new SByteConstant ((sbyte) Value, Location);
1808 if (target_type == TypeManager.short_type) {
1809 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1810 return new ShortConstant ((short) Value, Location);
1812 if (target_type == TypeManager.ushort_type) {
1813 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1814 return new UShortConstant ((ushort) Value, Location);
1816 if (target_type == TypeManager.int32_type) {
1817 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1818 return new IntConstant ((int) Value, Location);
1820 if (target_type == TypeManager.uint32_type) {
1821 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1822 return new UIntConstant ((uint) Value, Location);
1824 if (target_type == TypeManager.int64_type) {
1825 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1826 return new LongConstant ((long) Value, Location);
1828 if (target_type == TypeManager.uint64_type) {
1829 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1830 return new ULongConstant ((ulong) Value, Location);
1832 if (target_type == TypeManager.float_type)
1833 return new FloatConstant ((float) Value, Location);
1834 if (target_type == TypeManager.char_type) {
1835 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1836 return new CharConstant ((char) Value, Location);
1838 if (target_type == TypeManager.decimal_type)
1839 return new DecimalConstant ((decimal) Value, Location);
1846 public class DecimalConstant : Constant {
1847 public readonly decimal Value;
1849 public DecimalConstant (decimal d, Location loc):
1852 type = TypeManager.decimal_type;
1853 eclass = ExprClass.Value;
1857 override public string AsString ()
1859 return Value.ToString ();
1862 public override object GetValue ()
1864 return (object) Value;
1867 public override void Emit (EmitContext ec)
1869 ILGenerator ig = ec.ig;
1871 int [] words = Decimal.GetBits (Value);
1872 int power = (words [3] >> 16) & 0xff;
1874 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1876 IntConstant.EmitInt (ig, (int)Value);
1877 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1883 // FIXME: we could optimize this, and call a better
1887 IntConstant.EmitInt (ig, words [0]);
1888 IntConstant.EmitInt (ig, words [1]);
1889 IntConstant.EmitInt (ig, words [2]);
1892 IntConstant.EmitInt (ig, words [3] >> 31);
1895 IntConstant.EmitInt (ig, power);
1897 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1900 public override Constant Increment ()
1902 return new DecimalConstant (checked (Value + 1), loc);
1905 public override bool IsDefaultValue {
1911 public override bool IsNegative {
1917 public override Constant Reduce (bool inCheckedContext, Type target_type)
1919 if (target_type == TypeManager.sbyte_type)
1920 return new SByteConstant ((sbyte)Value, loc);
1921 if (target_type == TypeManager.byte_type)
1922 return new ByteConstant ((byte)Value, loc);
1923 if (target_type == TypeManager.short_type)
1924 return new ShortConstant ((short)Value, loc);
1925 if (target_type == TypeManager.ushort_type)
1926 return new UShortConstant ((ushort)Value, loc);
1927 if (target_type == TypeManager.int32_type)
1928 return new IntConstant ((int)Value, loc);
1929 if (target_type == TypeManager.uint32_type)
1930 return new UIntConstant ((uint)Value, loc);
1931 if (target_type == TypeManager.int64_type)
1932 return new LongConstant ((long)Value, loc);
1933 if (target_type == TypeManager.uint64_type)
1934 return new ULongConstant ((ulong)Value, loc);
1935 if (target_type == TypeManager.char_type)
1936 return new CharConstant ((char)Value, loc);
1937 if (target_type == TypeManager.float_type)
1938 return new FloatConstant ((float)Value, loc);
1939 if (target_type == TypeManager.double_type)
1940 return new DoubleConstant ((double)Value, loc);
1947 public class StringConstant : Constant {
1948 public readonly string Value;
1950 public StringConstant (string s, Location loc):
1953 type = TypeManager.string_type;
1954 eclass = ExprClass.Value;
1958 // FIXME: Escape the string.
1959 override public string AsString ()
1961 return "\"" + Value + "\"";
1964 public override object GetValue ()
1969 public override void Emit (EmitContext ec)
1972 ec.ig.Emit (OpCodes.Ldnull);
1974 ec.ig.Emit (OpCodes.Ldstr, Value);
1977 public override Constant Increment ()
1979 throw new NotSupportedException ();
1982 public override bool IsDefaultValue {
1984 return Value == null;
1988 public override bool IsNegative {
1994 public override Constant Reduce (bool inCheckedContext, Type target_type)